Digital is analogue with agreed thresholds. A 3.3V chip typically reads anything above roughly 2.0V as HIGH and below about 0.8V as LOW — and the band between is undefined, where a slowly-changing or noisy signal can be read as either, or oscillate.
| Family | Supply | Notes |
|---|---|---|
| 5V (classic Arduino Uno) | 5V | Forgiving, tolerant, increasingly legacy |
| 3.3V (ESP32, most modern) | 3.3V | Standard now. Many are not 5V-tolerant on inputs |
Sinking vs sourcing: an LED can be wired from the pin to ground (pin sources current, HIGH turns it on) or from the supply to the pin (pin sinks current, LOW turns it on). Both are valid, the second is often slightly stronger electrically, and mixing them up produces logic that reads backwards in code.
10-bit ADC, 3.3V reference:
0 = 0V
1023 = 3.3V
resolution = 3.3 / 1024 = 3.2 mV per step
reading a divider: V = raw × 3.3 / 1023
Practical cautions: the reference voltage is what accuracy depends on, so a sagging supply skews every reading; a high-impedance source (a divider above ~100kΩ) may not charge the ADC's sampling capacitor in time, giving readings that drift or read low; and averaging several samples is nearly free and dramatically improves stability.
Switching a pin on and off rapidly, varying the duty cycle. At 50% duty the average is half the supply. For LEDs and motors the average is all you need — the device's own inertia does the smoothing. For a genuine analogue voltage, add a low-pass filter, as in the Inductors & AC page.
Note that LED brightness perception is logarithmic, so a linear duty ramp looks wrong — most of the visible change happens in the bottom quarter. Squaring the value before writing it produces a fade that looks smooth.
| UART | I²C | SPI | |
|---|---|---|---|
| Wires | TX, RX (+GND) | SDA, SCL (+GND) | MOSI, MISO, SCK, CS |
| Devices | Two only | Many, by address | Many, one CS each |
| Speed | Slow (9600–115200 baud) | 100k–400kHz typical | Fast, MHz |
| Pull-ups needed | No | Yes — 4.7kΩ on both lines | No |
| Typical use | Debug console, GPS, serial modules | Sensors, small displays, RTCs | Displays, SD cards, radios |
Wiring gotchas, one per bus. UART must be crossed — TX to RX, RX to TX — and connecting TX to TX is the most common serial mistake there is. I²C needs pull-up resistors on both lines (many breakout boards include them, and stacking several boards can over-pull the bus); each device also needs a unique address, and address clashes are why two identical sensors often will not co-exist without an address-select pin. SPI needs a separate chip-select line per device, and getting the clock polarity/phase mode wrong yields data that looks like plausible garbage.
An I²C sensor is not detected by a bus scan. Ground is shared and the wiring matches the diagram. What do you check next?