Electronics / Theory / Digital
Theory 08

Digital &
microcontrollers Where hardware meets code. A microcontroller is a small computer whose pins are wired to the physical world — and almost every frustrating bug at this boundary comes from treating a pin as if it were a software variable rather than a piece of silicon with limits.

needs Resistors, TransistorsArduino / ESP32 context
Tier 0 · Groundlogic

Logic levels and pins

Module 0.1

What HIGH and LOW actually mean

Thresholds, not exact voltages

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.

FamilySupplyNotes
5V (classic Arduino Uno)5VForgiving, tolerant, increasingly legacy
3.3V (ESP32, most modern)3.3VStandard now. Many are not 5V-tolerant on inputs
Level mismatch is the classic destroyer of dev boards. Feeding a 5V sensor output into a 3.3V pin can damage it permanently. Going the other way (3.3V output into a 5V input) usually works because 3.3V clears the 5V chip's HIGH threshold, but check. To shift down, use a voltage divider for a slow signal, or a proper level-shifter module for anything fast or bidirectional such as I²C.
Module 0.2

GPIO limits and modes

The numbers that decide whether a pin survives
  • Per-pin current: roughly 20mA source or sink on typical parts (some ESP32 pins less). An LED with a resistor is fine; anything more needs a transistor.
  • Total chip current: there is a combined limit across all pins, often around 100–200mA. Eight LEDs at 20mA each will exceed it even though each pin is within spec.
  • Input modes: plain input (floating unless something drives it), input with internal pull-up (the usual choice for buttons), and output. Configuring a pin as an output and then connecting it to another output is a short — one of the few ways to destroy a board with code alone.
  • Boot-sensitive pins: on the ESP32 in particular, certain pins must be at specific levels at power-up or the chip refuses to boot. Pulling one of them low with a button is a genuinely common and confusing failure. Check the pinout guide for the specific board before assigning pins.

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.

Tier 1 · Mechanicsperipherals

Reading and writing the analogue world

Module 1.1

ADC and PWM

In and out

ADC — voltage in, number out

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.

PWM — a square wave that pretends to be analogue

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.

Module 1.2

The three buses

UART, I²C, SPI — how modules talk
UARTI²CSPI
WiresTX, RX (+GND)SDA, SCL (+GND)MOSI, MISO, SCK, CS
DevicesTwo onlyMany, by addressMany, one CS each
SpeedSlow (9600–115200 baud)100k–400kHz typicalFast, MHz
Pull-ups neededNoYes — 4.7kΩ on both linesNo
Typical useDebug console, GPS, serial modulesSensors, small displays, RTCsDisplays, 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.

Debugging any bus: confirm shared ground first, then check pull-ups (I²C), then run an address scanner sketch — a device that does not appear is a wiring or address problem, not a code problem. A cheap logic analyser turns this from guesswork into seeing the actual bits, and is the best £10 you will spend once you are past LEDs.
Drill 1

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?

Pull-ups, then address. I²C lines are open-drain: devices can only pull them low, so without pull-ups to the supply the bus never returns HIGH and nothing is detected. Then confirm the address — the datasheet's may differ from the library's default, and the 7-bit versus 8-bit convention trips people constantly. SDA and SCL are absolutely not interchangeable.
Referencesearchable

Glossary