Power, Control & Communication
Clean power, smart control loops, and how chips talk.
Power, Control & Communication
Clean power, control loops, and chip-to-chip protocols
Navigate with ← → or Space · F to present fullscreen · N for the script
Lesson notes
The finishing day, pulling the theory together: power regulators and batteries, multitasking with millis() and PID control, and the three communication protocols — UART, SPI, and I2C — with the OLED and IMU.
Power, Control & Communication
Clean power, control loops, and chip-to-chip protocols
- Voltage regulators & batteries
- Relays & flyback
- millis() multitasking
- Open vs closed loop · PID
- UART · SPI · I2C
- OLED · MPU-6050
Linear Regulators
7805 & LM317
7805 — fixed 5 V
- 3 pins: IN, GND, OUT
- Input must exceed ~7 V (dropout)
- Burns the extra voltage as heat
LM317 — adjustable
- Set output with two resistors
- Vout = 1.25 × (1 + R2/R1)
- Same simplicity, any voltage
Linear = simple & quiet but inefficient. Dropping 12 V→5 V at 1 A wastes 7 W as heat.
Power components in the flesh
The parts that take a raw battery and hand each chip clean, safe power.
- 7805 regulator — fixed 5 V, TO-220
- Buck converter — efficient step-down
- Relay module — switches big loads
- LiPo battery — 3.7 V per cell
Switching Converters
Buck & boost — efficient power
- Buck (step-down): Higher voltage in → lower out, at 85–95% efficiency. 12 V → 5 V with little heat.
- Boost (step-up): Lower voltage in → higher out. Run 5 V electronics from a single 3.7 V cell.
- How: They rapidly switch an inductor instead of burning excess as heat — that is why they stay cool.
Relays
An electrically-controlled mechanical switch
- Coil voltage — energize the coil (5 V / 12 V) to pull the contacts
- Contact rating — how much current/voltage the switch side can carry (e.g. 10 A 250 VAC)
- Flyback diode — a diode across the coil absorbs the voltage spike when it switches off
- Isolation — separates your low-voltage logic from high-voltage loads
The flyback diode is mandatory — without it the collapsing coil field destroys your driver transistor.
How a relay switches
A small current through the coil makes an electromagnet that snaps the armature across to the NO contact — switching a much bigger load.
- Coil side = tiny control current
- Contact side = big isolated load
- COM moves between NC and NO
Watch the armature snap over and the lamp light when the coil energises.
Decoupling & EMI
Put a 100 nF capacitor next to every chip.
Decoupling (bypass) capacitors sit beside each IC’s power pins, supplying instant bursts of current and absorbing noise. Skipping them causes random resets and glitches that are miserable to debug.
EMI = electromagnetic interference. Short traces, ground planes, and decoupling are your three defenses.
Battery Chemistries
LiPo vs Li-ion vs NiMH
| LiPo | Li-ion | NiMH | |
|---|---|---|---|
| Cell voltage | 3.7 V | 3.7 V | 1.2 V |
| Form | flat pouch | 18650 cylinder | AA/AAA-like |
| Energy density | high | high | medium |
| Best for | drones, slim builds | power banks, EVs | cheap, safe, simple |
Lithium cells need protection circuitry — never over-discharge below ~3.0 V or charge unbalanced.
TP4056 Charging IC
Safely charge a single Li-ion / LiPo cell
- CC/CV charging — constant current, then constant voltage to 4.2 V
- USB input — micro/USB-C modules charge from any phone charger
- Protection variant — TP4056 + DW01 adds over-discharge/short protection
- Status LEDs — red = charging, blue/green = done
millis() for Multitasking
delay() freezes the whole program.
During delay(1000) your board cannot read a button or another sensor. millis() lets you track time WITHOUT stopping — so several things appear to run at once.
Blink without delay
- millis() = ms since boot, always counting
- Compare elapsed time instead of pausing
unsigned long last = 0;
const long interval = 500;
void loop() {
unsigned long now = millis();
if (now - last >= interval) {
last = now;
state = !state;
digitalWrite(led, state);
}
// other code keeps running here every loop!
}Open-loop vs Closed-loop
Does the system check its own result?
Open-loop
- Send a command, hope it worked
- No feedback / measurement
- Example: microwave timer, a fan at fixed speed
- Simple but drifts
Closed-loop
- Measure the result, correct continuously
- Uses sensor feedback
- Example: cruise control, thermostat
- Accurate & self-correcting
PID Control
PID drives the error to zero
Error = setpoint − measured. The controller corrects, re-measures, and repeats — until the value rests on target.
- Overshoot then settle is the classic PID response
- Good tuning = fast settle, little overshoot
- The dashed line is the goal (setpoint)
The three terms
Each reacts to the error differently.
- Proportional: Reacts to the error NOW. Bigger error → bigger push. Too much → overshoot/oscillation.
- Integral: Accumulates PAST error to erase steady offset. Too much → sluggish wobble.
- Derivative: Reacts to the RATE of change — anticipates and damps overshoot. Sensitive to noise.
The PID equation
output = Kp·e + Ki·∫e dt + Kd·(de/dt)
- e — error = setpoint − measured
- Kp/Ki/Kd — tuning gains you choose
Example: Tune by hand: raise Kp until it oscillates, back off, add Kd to damp, add a little Ki to remove offset.
Balance robots, drones, temperature controllers and motor speed loops all live on PID.
UART
The simplest link — two wires
Asynchronous serial: no shared clock, both sides just agree on a speed (baud).
Wiring
- TX of one → RX of the other (cross over)
- Common ground
- Both set the same baud rate
In code
- Serial.begin(115200)
- Serial.write() / Serial.read()
- One device to one device
Anatomy of a UART byte
With no shared clock, framing keeps both sides in sync: a start bit, the data bits, then a stop bit.
- S = start bit (line pulled low)
- b0–b7 = the 8 data bits
- P = stop bit — ready for the next byte
SPI
Fast, full-duplex, clocked
- MOSI — Master Out, Slave In — data to the device
- MISO — Master In, Slave Out — data back
- SCK — clock from the master synchronizes every bit
- CS / SS — chip-select — one line per device to pick who listens
SPI is the fastest of the three (MHz). Cost: a separate CS wire per device. Used by SD cards, displays, flash.
SPI moves data both ways at once
On every clock tick the master sends a bit on MOSI and receives one on MISO — full-duplex. CS selects which device is listening.
- MOSI + MISO = simultaneous two-way
- SCK clocks every bit
- Fastest protocol — great for displays & SD
I2C
Two wires, many devices
SDA (data) and SCL (clock) are shared. Each device has a unique address — the master calls it by name.
I2C needs pull-up resistors on SDA and SCL (often 4.7 kΩ). Many breakout boards include them.
I2C scanner — find every device
- Always run this first when wiring an I2C device
- Confirms address & wiring before you debug code
#include <Wire.h>
void setup(){
Wire.begin(); Serial.begin(115200);
for (byte a = 1; a < 127; a++){
Wire.beginTransmission(a);
if (Wire.endTransmission() == 0){
Serial.print("Found 0x"); Serial.println(a, HEX);
}
}
}OLED & IMU over I2C
Two classic I2C devices
OLED SSD1306 (0x3C)
- 128×64 monochrome display
- Adafruit_SSD1306 + GFX libraries
- display.print() then display.display()
MPU-6050 IMU (0x68)
- 3-axis accelerometer + 3-axis gyro
- Reads tilt, motion, rotation
- Core of balance bots & drones
The OLED display (SSD1306)
A tiny 0.96" screen that needs only the two I2C wires to show text, numbers, and simple graphics.
- 128×64 pixels, crisp & low-power
- I2C address 0x3C
- print() then display() to update
The MPU-6050 module (GY-521)
A tiny breakout carrying a 6-axis IMU — it talks to the MCU over just SDA and SCL.
- Accelerometer senses tilt & g-force
- Gyroscope senses rotation rate
- Default I2C address 0x68
Read the MPU-6050
- One library hides all the register reads
- Fuse accel + gyro for stable angle (complementary/Kalman)
#include <Adafruit_MPU6050.h>
Adafruit_MPU6050 mpu;
void setup(){ Wire.begin(); mpu.begin(); }
void loop(){
sensors_event_t a, g, t;
mpu.getEvent(&a, &g, &t);
Serial.println(a.acceleration.x); // m/s^2
}Software Serial
Out of hardware UARTs? Make one in software.
SoftwareSerial (or ESP32 extra hardware UARTs) lets you add more serial ports on ordinary GPIO pins — handy for GPS, GSM, or a second module while USB stays free for debugging.
UART vs SPI vs I2C — pick the right one
| UART | SPI | I2C | |
|---|---|---|---|
| Wires | 2 (TX/RX) | 4 + 1/device | 2 (SDA/SCL) |
| Clock | none (async) | shared SCK | shared SCL |
| Speed | low–med | highest | medium |
| Devices | 1 ↔ 1 | many (CS each) | many (by address) |
| Best for | GPS, modules, debug | displays, SD, flash | sensors, OLED, IMU |
Day 5 — Key Takeaways
- Linear regulators waste heat; buck/boost are efficient
- Relays isolate big loads — always add a flyback diode
- millis() multitasks; delay() blocks
- Closed-loop control measures & corrects — that’s PID
- UART: 2 wires, async · SPI: fast, full-duplex · I2C: addressed, 2 shared wires
- Run the I2C scanner first; OLED 0x3C, MPU-6050 0x68