Think of It as Light Switches
Imagine 8 light switches on a wall. Each switch is OFF or ON. That row of 8 switches is a byte. Each switch is a bit.
Switch: 7 6 5 4 3 2 1 0
State: OFF OFF OFF OFF OFF OFF OFF ON
Binary: 0 0 0 0 0 0 0 1
That pattern, 00000001, is the number 1 in binary. Flip switch 1 on too and you get 00000011, which is 3. With 8 switches you can make 256 different patterns (0 through 255).
Binary Counting
| Decimal | Binary | Which bits are on | |---------|--------|-------------------| | 0 | 0000 | none | | 1 | 0001 | bit 0 | | 2 | 0010 | bit 1 | | 3 | 0011 | bits 0, 1 | | 4 | 0100 | bit 2 | | 5 | 0101 | bits 0, 2 | | 6 | 0110 | bits 1, 2 | | 7 | 0111 | bits 0, 1, 2 | | 8 | 1000 | bit 3 | | 15 | 1111 | bits 0, 1, 2, 3 |
Each bit position has a value that doubles going left:
Bit: 7 6 5 4 3 2 1 0
Value: 128 64 32 16 8 4 2 1
To convert binary to decimal, add up the values of the ON bits. 00001011 = 8 + 2 + 1 = 11.
Why This Matters on Arduino
When you call digitalWrite() on 8 pins, you are setting 8 bits one at a time. A shift register lets you set all 8 at once by sending a single byte:
// Without shift register: 8 lines, 8 pins
digitalWrite(2, HIGH);
digitalWrite(3, LOW);
// ...6 more lines...
// With shift register: 1 line, 1 byte
shiftOut(dataPin, clockPin, MSBFIRST, 0b10000001);
Bitwise Operators
These work on individual bits. They are different from &&, ||, and ! which work on true/false.
<< Left Shift (target a specific bit)
1 << 0 = 00000001 = 1 (bit 0 on)
1 << 1 = 00000010 = 2 (bit 1 on)
1 << 3 = 00001000 = 8 (bit 3 on)
1 << 7 = 10000000 = 128 (bit 7 on)
Think of 1 << n as "create a byte where only bit n is on."
>> Right Shift
Slides bits right. Shifting right by n is the same as dividing by 2^n.
| OR (turn bits ON)
If either bit is 1, the result is 1.
byte leds = 0b00000001; // LED 0 on
leds = leds | (1 << 3); // Also turn on LED 3
// leds is now 0b00001001
OR never turns bits off. It can only turn them on.
& AND (check or mask bits)
Result is 1 only if both bits are 1.
byte switches = 0b00001010;
if (switches & (1 << 3)) {
// bit 3 is set (result is 00001000, non-zero = true)
}
~ NOT (flip all bits)
byte leds = 0b00001111;
leds = leds & ~(1 << 2); // Turn off bit 2
// ~(1 << 2) = ~00000100 = 11111011
// 00001111 & 11111011 = 00001011
^ XOR (toggle bits)
Result is 1 if bits are different.
leds = leds ^ (1 << 2); // Flip bit 2
leds = leds ^ (1 << 2); // Flip it back
Quick Reference
| Goal | Code | |------|------| | Turn on bit n | value | (1 << n) | | Turn off bit n | value & ~(1 << n) | | Toggle bit n | value ^ (1 << n) | | Check if bit n is on | value & (1 << n) | | All bits on | 0xFF | | All bits off | 0x00 |
Hexadecimal
Hex is base-16. Each hex digit maps to exactly 4 binary digits.
| Hex | Binary | Hex | Binary | |-----|--------|-----|--------| | 0x0 | 0000 | 0x8 | 1000 | | 0x1 | 0001 | 0x9 | 1001 | | 0x2 | 0010 | 0xA | 1010 | | 0x3 | 0011 | 0xB | 1011 | | 0x4 | 0100 | 0xC | 1100 | | 0x5 | 0101 | 0xD | 1101 | | 0x6 | 0110 | 0xE | 1110 | | 0x7 | 0111 | 0xF | 1111 |
A full byte is two hex digits: 0xFF = 11111111 = 255.
Binary Literals
Arduino supports 0b notation. Great for visualizing LED patterns:
byte pattern = 0b10101010; // every other LED on
byte edges = 0b10000001; // first and last only
Shift Register Patterns
1 << n // one specific LED on
0xFF // all on
0x00 // all off
0x0F // first 4 on (00001111)
0xF0 // last 4 on (11110000)
0xAA // alternating (10101010)
// Build up a pattern
byte p = 0;
p = p | (1 << 0); // turn on LED 0
p = p | (1 << 3); // turn on LED 3
p = p | (1 << 7); // turn on LED 7
// p is now 10001001
Common Mistakes
| Mistake | What Happens | Fix | |---------|-------------|-----| | Confusing | with || | Logical OR gives 0 or 1, not a bit pattern | Use single-character operators for bits | | Off-by-one (bits count from 0) | 1 << 3 is the 4th bit, not the 3rd | Check your wiring to see which end is bit 0 | | byte wrapping | 200 + 100 = 44 (wraps past 255) | A byte holds 0 to 255, nothing more | | Shifting by 8 on a byte | Pushes the 1 completely out, result is 0 | Max shift for a byte is 7 | | Forgetting to latch | Variable changes but LEDs stay the same | Send the byte to the shift register after every change |