Robot Electronics Overview
Reference Document | Understanding the Hardware You're Programming
This document explains how the Yahboom Pico Robot is built from an electronics perspective. As EE students, understanding the hardware helps you debug issues, appreciate design trade-offs, and connect software behavior to physical reality.
Full Robot Schematic (PDF) — pin-level circuit diagram of the entire robot board.
System Block Diagram
┌─────────────────────────────────────────────────────────────────────────────┐
│ YAHBOOM PICO ROBOT │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────────────────────────────────────────┐ │
│ │ BATTERY │ │ RASPBERRY PI PICO 2 W │ │
│ │ 18650 │ │ ┌─────────────────────────────────────────────┐ │ │
│ │ 3.7V │ │ │ RP2350 (Dual Cortex-M33 @ 150MHz) │ │ │
│ │ ~2600mAh │ │ │ 520KB SRAM, 4MB Flash │ │ │
│ └──────┬───────┘ │ │ WiFi/BT (CYW43439) │ │ │
│ │ │ └─────────────────────────────────────────────┘ │ │
│ ▼ │ │ │
│ ┌──────────────┐ │ GPIO ──────► Motor Driver (TB6612) │ │
│ │ POWER MGMT │ │ GPIO ──────► WS2812B LEDs │ │
│ │ 3.3V + 5V │─────│ I2C ──────► IMU (BMI160) + OLED │ │
│ │ regulators │ │ ADC ──────► Line Sensors + Battery Monitor │ │
│ └──────────────┘ │ GPIO ──────► Ultrasonic (Trigger/Echo) │ │
│ │ GPIO ──────► IR Receiver │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ TB6612FNG │ │ 2× DC MOTOR │ │ SENSORS │ │
│ │ H-BRIDGE │◄────│ w/ GEARBOX │ │ • 5× Optocouplers (line)│ │
│ │ MOTOR DRIVER│ │ ~200 RPM │ │ • HC-SR04 (ultrasonic) │ │
│ └──────────────┘ └──────────────┘ │ • BMI160 (IMU) │ │
│ │ • IR receiver │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Power System
Battery: 18650 Li-ion Cell
| Specification | Value | Notes |
|---|---|---|
| Nominal Voltage | 3.7V | Ranges 3.0V (empty) to 4.2V (full) |
| Capacity | ~2600 mAh | Typical for quality cells |
| Chemistry | Li-ion | Requires protection circuit |
| Discharge Rate | 1-2C | Sufficient for motors |
Why 18650? - Ubiquitous, cheap, replaceable - Good energy density - Handles motor current spikes - Trade-off: Single cell = low voltage, needs boost converter
Voltage Regulation
Battery (3.0-4.2V)
│
├───► Boost Converter ───► 5V rail (motors, some sensors)
│ (typically MT3608)
│
└───► LDO Regulator ───► 3.3V rail (Pico, logic)
(typically AMS1117-3.3)
| Rail | Voltage | Consumers | Notes |
|---|---|---|---|
| VBAT | 3.0-4.2V | Battery monitor ADC | Raw battery |
| 5V | 5.0V | Motors, HC-SR04, WS2812 | Boosted from battery |
| 3.3V | 3.3V | Pico, I2C devices, line sensors | Regulated |
Trade-offs:
| Aspect | This Design | Alternative | Trade-off |
|---|---|---|---|
| Single cell | Simple, light | 2S (7.4V) | Lower voltage but simpler charging |
| Boost converter | 5V for motors | Buck from 2S | Efficiency vs complexity |
| Linear 3.3V LDO | Simple, low noise | Switching | Wastes power as heat but cleaner |
Battery Monitoring
The robot monitors battery voltage via ADC:
VBAT ────┬──[R1]──┬──► GP29 (ADC)
│ │
[R2] [C]
│ │
GND GND
Voltage divider: V_adc = VBAT × R2/(R1+R2)
Typically: R1=10k, R2=10k → V_adc = VBAT/2
Why voltage divider? - Battery can reach 4.2V - ADC max is 3.3V - Divider scales 4.2V → 2.1V (safe for ADC)
Code connection:
import machine
adc = machine.ADC(29)
raw = adc.read_u16()
voltage = (raw / 65535) * 3.3 * 2 # ×2 for divider
What's NOT Included
This robot does NOT include: - Battery charging circuit (charge externally) - Low-voltage cutoff (protect in software!) - Fuel gauge IC (estimate from voltage only)
Production designs would add these for safety and UX.
Motor Driver: TB6612FNG
What is an H-Bridge?
An H-bridge allows bidirectional DC motor control:
VCC VCC
│ │
┌───┴───┐ ┌───┴───┐
│ Q1 │ │ Q2 │
│ (HIGH)│ │ (LOW) │
└───┬───┘ └───┬───┘
│ ┌───────┐ │
├──────┤ MOTOR ├───────┤
│ └───────┘ │
┌───┴───┐ ┌───┴───┐
│ Q3 │ │ Q4 │
│ (LOW) │ │ (HIGH)│
└───┬───┘ └───┬───┘
│ │
GND GND
Q1+Q4 ON → Current flows LEFT to RIGHT → Motor spins CW
Q2+Q3 ON → Current flows RIGHT to LEFT → Motor spins CCW
TB6612FNG Specifications
| Parameter | Value | Notes |
|---|---|---|
| Channels | 2 (dual H-bridge) | One per motor |
| Voltage | 4.5-13.5V (motor), 2.7-5.5V (logic) | 5V motor rail |
| Current | 1.2A continuous, 3.2A peak | Per channel |
| PWM Frequency | Up to 100 kHz | We use ~1 kHz |
| Control | IN1, IN2, PWM per channel | Direction + speed |
Control Logic
| IN1 | IN2 | PWM | Motor Action |
|---|---|---|---|
| 0 | 0 | X | Coast (free spin) |
| 1 | 0 | duty | Forward at duty% |
| 0 | 1 | duty | Reverse at duty% |
| 1 | 1 | X | Brake (short circuit) |
Why TB6612 instead of L298N?
| Aspect | TB6612FNG | L298N |
|---|---|---|
| Technology | MOSFET | Bipolar transistor |
| Voltage drop | ~0.5V | ~2V |
| Efficiency | ~90% | ~60-70% |
| Heat | Minimal | Needs heatsink |
| Size | Small | Large |
| Cost | ~$2 | ~$1 |
Trade-off: TB6612 is more efficient and compact, but slightly more expensive. For battery-powered robots, efficiency wins.
Pin Connections
Pico GPIO TB6612 Motor
─────────────────────────────────────
GP12 (PWM) ───► AIN1 ──┐
GP13 (PWM) ───► AIN2 ──┴──► Motor A (Left)
PWMA ───► (tied to IN or separate)
GP10 (PWM) ───► BIN1 ──┐
GP11 (PWM) ───► BIN2 ──┴──► Motor B (Right)
PWMB ───► (tied to IN or separate)
STBY ───► 3.3V (always enabled)
PWM on Direction Pins
This robot uses PWM directly on IN1/IN2 rather than separate PWM pins. - Simpler wiring (fewer GPIOs needed) - Trade-off: Can't use "fast decay" brake mode easily
Sensors
Line Sensors (5× Optocouplers)
┌─────────────┐
VCC ───┤ LED │ IR light
│ (emit) ├────────►
└─────────────┘ │
│ reflects off surface
┌─────────────┐ │
ADC ◄──┤ Phototrans. │◄───────┘
│ (receive) │
└──────┬──────┘
│
GND
| Parameter | Value | Notes |
|---|---|---|
| Type | Reflective IR | TCRT5000 or similar |
| Output | Analog (0-3.3V) | Proportional to reflectance |
| Count | 5 sensors | Left-outer, Left, Center, Right, Right-outer |
| ADC Pins | GP26, GP27, GP28 | Only 3 ADC channels used |
Why analog instead of digital? - Analog gives proportional position (how far off-center) - Digital only gives "on line" or "off line" - Trade-off: More complex code, but smoother control
Why only 3 ADC pins for 5 sensors? - RP2350 has limited ADC channels - Outer sensors may use digital threshold - Or multiplexing (not on this robot)
Ultrasonic Sensor (HC-SR04)
┌─────────────────────────────┐
TRIG ──►│ Trigger pulse (10µs) │
│ │
│ ┌──────┐ ┌──────┐ │
│ │ TX │ ))) │ RX │ │
│ └──────┘ └──────┘ │
│ │
ECHO ◄──│ Echo pulse (proportional) │
└─────────────────────────────┘
Distance = (Echo pulse width × Speed of sound) / 2
= (pulse_us × 343 m/s) / 2
= pulse_us × 0.0343 / 2 cm
≈ pulse_us / 58 cm
| Parameter | Value | Notes |
|---|---|---|
| Range | 2-400 cm | Practical: 5-200 cm |
| Resolution | ~3 mm | Limited by timing precision |
| Beam angle | ~15° | Cone, not laser |
| Voltage | 5V | Needs level shifting for 3.3V MCU |
Level Shifting Issue: - HC-SR04 ECHO is 5V - Pico GPIO is 3.3V max! - Solutions: 1. Voltage divider on ECHO (simple, used here) 2. Level shifter IC (cleaner) 3. 3.3V-compatible HC-SR04P (drop-in replacement)
IMU (BMI160)
| Parameter | Value | Notes |
|---|---|---|
| Type | 6-axis (3-accel, 3-gyro) | No magnetometer |
| Interface | I2C (address 0x68 or 0x69) | Shared bus with OLED |
| Gyro range | ±125 to ±2000 °/s | Configurable |
| Accel range | ±2g to ±16g | Configurable |
| Sample rate | Up to 1600 Hz | We use ~100 Hz |
Why BMI160?
| Aspect | BMI160 | MPU6050 | Trade-off |
|---|---|---|---|
| Power | Lower | Higher | BMI160 better for battery |
| Noise | Lower | Higher | BMI160 cleaner data |
| Availability | Good | Excellent | MPU6050 more common |
| Cost | ~$3 | ~$2 | Slight premium |
Calibration Required: - Gyro has bias (reads non-zero when stationary) - Accelerometer has offset and scale errors - Must calibrate at startup or use stored values
WS2812B (NeoPixel) LEDs
| Parameter | Value | Notes |
|---|---|---|
| Count | 4-8 LEDs | Daisy-chained |
| Data pin | GP6 | Single wire protocol |
| Voltage | 5V | But 3.3V data usually works |
| Protocol | 800 kHz, 24-bit GRB | Timing-critical! |
Why single-wire protocol? - Fewer wires in cable runs - Daisy-chain simplifies PCB - Trade-off: Timing-critical (needs PIO or careful bitbang)
Voltage Level Concern: - WS2812 spec: VIH > 0.7 × VDD = 0.7 × 5V = 3.5V - Pico output: 3.3V (below spec!) - Why it works: Most WS2812s tolerate it - Robust solution: Level shifter on data line
I2C Bus
The robot uses I2C for multiple devices on a shared bus:
Pico I2C Bus (GP14=SDA, GP15=SCL)
┌──────┐ │
│ GP14 ├──────────────────────┼───────┬───────┐
│ (SDA)│ │ │ │
│ │ ┌──┴──┐ ┌──┴──┐ ┌──┴──┐
│ GP15 ├───────────────────┤ IMU │ │OLED │ │ ... │
│ (SCL)│ │0x68 │ │0x3C │ │ │
└──────┘ └─────┘ └─────┘ └─────┘
│ │ │
┌───┴───────┴───────┴───┐
│ 4.7kΩ │
│ Pull-up to 3.3V │
└───────────────────────┘
| Parameter | Value | Notes |
|---|---|---|
| Speed | 400 kHz (Fast mode) | Could use 100 kHz standard |
| Pull-ups | 4.7 kΩ to 3.3V | On robot PCB |
| Devices | IMU (0x68), OLED (0x3C) | Possibly more |
I2C Scan (discover devices):
from machine import I2C, Pin
i2c = I2C(1, sda=Pin(14), scl=Pin(15), freq=400000)
devices = i2c.scan()
print([hex(d) for d in devices]) # ['0x3c', '0x68']
Why I2C? - Only 2 wires for multiple devices - Standardized, well-supported - Trade-off: Slower than SPI, shared bus can cause conflicts
What This Robot Has vs. Professional Solutions
Why This Matters
This is a ~€30 educational robot. Understanding what's "missing" compared to a €300 hobbyist or €3000 industrial solution teaches you: - What trade-offs engineers make for cost - When cheap solutions are "good enough" - When you NEED the professional solution
Cost Tiers in Embedded Design
┌─────────────────────────────────────────────────────────────────────────────┐
│ COST vs FEATURES SPECTRUM │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ €30 Educational €150 Hobbyist €500+ Professional │
│ (This robot) (Quality kit) (Industrial/Competition) │
│ │
│ ✗ No encoders ✓ Basic encoders ✓ High-res encoders │
│ ✗ No current sense ◐ Basic current ✓ Per-motor current │
│ ✗ No charging IC ✓ Onboard charging ✓ BMS + fuel gauge │
│ ✗ Basic IMU ✓ Better IMU ✓ IMU + magnetometer │
│ ✗ Simple H-bridge ✓ Better driver ✓ Smart motor driver │
│ ✗ No protection ◐ Basic protection ✓ Full protection │
│ │
│ Good for: Learning Good for: Projects Good for: Competition/Prod │
└─────────────────────────────────────────────────────────────────────────────┘
Detailed Trade-off Analysis
1. Motor Feedback: No Encoders
What this robot has: No motor feedback. Open-loop control only.
What's missing:
┌─────────────────────────────────────────┐
ENCODER │ Quadrature encoder on motor shaft │
(missing) │ Provides: pulses per revolution │
│ Enables: closed-loop speed control │
└─────────────────────────────────────────┘
| Aspect | This Robot | With Encoders |
|---|---|---|
| Speed control | PWM duty (hope it's right) | Actual measured RPM |
| Straight driving | Guess + IMU compensation | True odometry |
| Position control | Not possible | Dead reckoning |
| Cost | €0 | +€5-15 per motor |
Why it's OK for learning: - Forces you to understand open-loop limitations - IMU provides alternative (gyro-based) heading correction - Line sensors provide closed-loop feedback for line following
When you'd need encoders: - Precise distance travel ("move 50cm forward") - Competition robots (need reproducibility) - Mapping/SLAM applications
Professional alternative: Magnetic encoders (AS5048), optical encoders (E6B2)
2. Power: No Battery Management System (BMS)
What this robot has: - Single 18650 cell - Voltage divider for monitoring - External charging
What's missing:
| Feature | This Robot | Professional BMS |
|---|---|---|
| Charging | External charger | Onboard USB-C charging |
| Protection | None (hope battery has it) | Over-charge, over-discharge, short circuit |
| Fuel gauge | Voltage estimation only | Coulomb counting (accurate %) |
| Cell balancing | N/A (single cell) | Required for multi-cell |
| Low-voltage cutoff | Software only (if you code it!) | Hardware cutoff |
THIS ROBOT: PROFESSIONAL:
Battery ──► Boost ──► 5V Battery ──► BMS IC ──► Boost ──► 5V
│ │ │
└──► ADC (monitor) │ ├── Charging circuit
│ ├── Protection FETs
(hope battery has │ ├── Fuel gauge (I2C)
internal protection!) │ └── Balancing (multi-cell)
│
└──► ADC (accurate SOC)
Why it's OK for learning: - Most 18650 cells have internal protection - Short lab sessions, not continuous operation - Easy to swap/charge batteries externally
When you'd need proper BMS: - Product that end-users charge - LiPo packs (more dangerous chemistry) - Need accurate battery percentage display - Regulatory compliance (CE, UL)
Professional components: BQ24072 (charging), BQ27441 (fuel gauge), BQ76920 (protection)
3. Motor Driver: No Current Sensing
What this robot has: TB6612 H-bridge, no feedback
What's missing:
| Feature | This Robot | Smart Motor Driver |
|---|---|---|
| Current sensing | None | Per-motor mA reading |
| Stall detection | Can't detect (motor burns?) | Automatic shutoff |
| Torque control | Not possible | Current = torque |
| Diagnostics | "Motor stopped, dunno why" | "Motor stalled at 1.2A" |
THIS ROBOT: PROFESSIONAL:
PWM ──► TB6612 ──► Motor PWM ──► DRV8871 ──► Motor
│
(no idea what current ├── Current sense (ADC)
motor is drawing) ├── Fault output (GPIO)
└── Thermal protection
Why it's OK for learning: - TB6612 has thermal protection (won't burn up) - Learn to recognize stall by other means (sound, heat, behavior) - Focus on control, not diagnostics
When you'd need current sensing: - Torque-limited applications (grippers) - Stall detection for safety - Efficiency optimization - Load estimation
Professional drivers: DRV8871 (current sense), TMC2209 (stepper, full diagnostics)
4. Sensors: Basic vs. Professional
Line Sensors
| Aspect | This Robot | Professional |
|---|---|---|
| Type | IR reflective | RGB color sensor or camera |
| Output | Analog threshold | Calibrated values |
| Ambient rejection | Poor | Good (modulated IR) |
| Line color | Black on white only | Any color detection |
Professional alternative: QTRX-HD series (Pololu), TCS34725 (color sensor), camera + CV
Distance Sensor
| Aspect | HC-SR04 (This Robot) | Professional |
|---|---|---|
| Technology | Ultrasonic ToF | Laser ToF (VL53L0X) |
| Accuracy | ±3mm | ±1mm |
| Range | 2-400cm | 5-200cm (more accurate) |
| Speed | ~60ms per reading | ~30ms |
| Beam | Wide cone (15°) | Narrow beam (25°) |
| Cost | €1 | €5-10 |
Professional alternative: VL53L1X (laser ToF), TFmini (LiDAR), structured light
IMU
| Aspect | BMI160 (This Robot) | Professional |
|---|---|---|
| Axes | 6 (accel + gyro) | 9 (+ magnetometer) |
| Heading | Gyro integration (drifts) | Magnetic compass (absolute) |
| Calibration | Manual | Factory calibrated |
| Fusion | DIY in software | Onboard sensor fusion (BNO055) |
Professional alternative: BNO055 (9-axis + fusion), ICM-20948
5. Protection Circuits: Almost None
What this robot has: - Battery's internal protection (hopefully) - TB6612 thermal shutdown - That's about it
What's missing:
| Protection | This Robot | Professional |
|---|---|---|
| Reverse polarity | ❌ None | P-MOSFET or ideal diode |
| ESD protection | ❌ None | TVS diodes on I/O |
| Overcurrent (system) | ❌ None | Resettable fuse (PTC) |
| Motor back-EMF | ✓ TB6612 internal | Dedicated flyback diodes |
| Overvoltage | ❌ None | Voltage clamps |
PROFESSIONAL PROTECTION:
Battery ──► Reverse ──► Fuse ──► Regulator ──► Power rails
polarity (PTC)
(P-FET)
GPIO ──► ESD ──► Level ──► External device
TVS shift
Why it's OK for learning: - Indoor lab environment (low ESD risk) - Supervised use (won't reverse polarity... hopefully) - Disposable if something breaks
When you'd need protection: - Any product with end users - Outdoor/industrial environment - Regulatory compliance - Expensive components downstream
6. Level Shifting: Marginal Design
What this robot has: - 3.3V MCU directly driving 5V-expecting devices - Voltage dividers for 5V → 3.3V inputs - "Works most of the time"
What's proper:
| Signal | This Robot | Professional |
|---|---|---|
| WS2812 data | 3.3V direct (out of spec!) | Level shifter (74HCT125) |
| HC-SR04 echo | Resistor divider | Level shifter or 3.3V sensor |
| I2C | Direct (OK, open drain) | OK as-is |
PROPER LEVEL SHIFTING:
3.3V MCU 5V Device
│ │
└──► 74HCT125 buffer ───────┘
(3.3V in → 5V out)
or
└──► BSS138 bidirectional ──┘
(for I2C, SPI)
Why the cheap way often works: - Many 5V devices actually trigger at 2.0-2.4V (TTL thresholds) - WS2812 has wide input tolerance in practice - Voltage dividers work for slow signals
When it fails: - Long cable runs (noise margin reduced) - Fast signals (divider RC time constant) - Cold temperatures (thresholds shift) - Device-to-device variation
Design Trade-offs Summary Table
| System | This Robot (€30) | Better (€100+) | Why Cheap is OK for Learning |
|---|---|---|---|
| Motor feedback | None | Encoders | Learn open-loop limitations |
| Power management | External charge, voltage ADC | BMS + fuel gauge | Simpler, swap batteries |
| Motor driver | TB6612 (no sensing) | DRV8871 + current | Focus on control, not diagnostics |
| Line sensors | IR analog | RGB/camera | Sufficient for basic line following |
| Distance | HC-SR04 ultrasonic | VL53L1X laser | Adequate for obstacle detection |
| IMU | 6-axis (drift) | 9-axis + fusion | Learn calibration, filtering |
| Protection | Minimal | Full protection | Lab environment, supervised |
| Level shifting | Marginal/none | Proper shifters | Usually works, learn why it shouldn't |
When "Cheap" Becomes a Problem
The educational robot's limitations become real issues when:
| Scenario | Why Cheap Fails | What You'd Need |
|---|---|---|
| Competition | Reproducibility, reliability | Encoders, current sensing |
| Outdoor use | ESD, weather, abuse | Protection circuits |
| Product | Safety, regulations, users | BMS, protection, proper design |
| Precision | Drift, noise, tolerance | Better sensors, calibration |
| Long runtime | Battery life, efficiency | Power management, sleep modes |
The Engineer's Takeaway
Design is About Trade-offs
There is no "best" design. There are only designs that: - Meet requirements - Stay within budget - Ship on time
This €30 robot makes many compromises. Understanding them teaches you: 1. What can be cut for cost savings 2. What breaks when you cut too much 3. What matters for your specific application
A professional engineer doesn't always use the "best" components. They use the right components for the constraints.
Common Failure Points and Beginner Mistakes
Hardware Failures (Robot Issues)
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Motors don't run | No movement | Dead battery, STBY pin low | Check voltage, STBY |
| One motor weaker | Curves constantly | Motor damage, wiring | Swap motors to isolate |
| Erratic behavior | Random movements | Low battery (brownout) | Charge battery |
| I2C timeout | Device not responding | Wrong address, wiring | I2C scan, check connections |
| LEDs wrong color | Colors shifted | GRB vs RGB confusion | Check library settings |
| Ultrasonic reads 0 | No distance | 5V→3.3V divider missing | Add voltage divider |
| IMU drift | Heading creeps | Gyro bias not calibrated | Calibrate at startup |
Typical Beginner Mistakes (Learn From Others!)
These are the mistakes almost everyone makes at least once:
1. Power Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| Reversing battery polarity | Magic smoke, dead components | Check twice, add protection in future designs |
| Powering from USB while motors run | USB brownout, PC disconnect | USB can't supply motor current; use battery |
| Ignoring voltage ratings | 3.3V device on 5V → dead | Always check datasheet voltage range |
| No decoupling capacitors | Random resets, noise | Add 100nF caps near power pins |
| Sharing power with motors | MCU resets when motors start | Separate power rails or big capacitors |
WRONG: RIGHT:
USB ──┬──► Pico USB ──► Pico (programming only)
│
└──► Motors (draws 2A!) Battery ──► Motors + Pico
↑ (adequate current)
USB can only supply 500mA!
2. GPIO Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| Floating inputs | Undefined readings (on RP2350: stuck 0 or 1 due to leakage current errata) | Always use pull-up/pull-down |
| Forgetting to set direction | Pin doesn't work | Pin.OUT for output, Pin.IN for input |
| Shorting output to ground | Excessive current, damage | Never connect output directly to GND or VCC |
| 5V into 3.3V input | Damage over time | Use level shifter or voltage divider |
| Too much current from GPIO | Pin damage, weak signal | GPIO max ~12mA; use transistor for more |
WRONG: RIGHT:
GPIO ──────────► LED ──► GND GPIO ──► Resistor ──► LED ──► GND
↑ (330Ω-1kΩ limits current)
No resistor!
LED may burn, GPIO stressed
3. Motor Control Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| PWM too slow | Audible whine, inefficient | Use 1kHz+ for DC motors |
| PWM too fast | FETs don't fully switch | Stay under 100kHz for simple drivers |
| Both H-bridge inputs HIGH | Shoot-through (short circuit) | Never set IN1=IN2=HIGH unless braking |
| No flyback protection | Voltage spikes damage driver | H-bridge ICs have this; discrete needs diodes |
| Starting at 100% duty | Current spike, brownout | Ramp up PWM gradually |
WRONG: RIGHT:
motor.duty(100%) # Instant! for duty in range(0, 100, 5):
motor.duty(duty)
Current spike causes time.sleep_ms(10)
brownout, resets MCU # Gradual ramp, smooth start
4. I2C Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| Missing pull-ups | No communication | I2C needs 4.7kΩ to VCC |
| Wrong address | Device not found | I2C scan to discover addresses |
| SDA/SCL swapped | Nothing works | Double-check wiring |
| Multiple devices, same address | Conflicts | Change address or use multiplexer |
| Speed too high | Errors, corruption | Start at 100kHz, increase if stable |
# ALWAYS scan first!
import machine
i2c = machine.I2C(1, sda=machine.Pin(14), scl=machine.Pin(15))
print([hex(addr) for addr in i2c.scan()])
# Expected: ['0x3c', '0x68'] for OLED + IMU
5. Sensor Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| Not calibrating | Wrong readings, bad control | Calibrate at startup or store values |
| Ignoring noise | Jittery behavior | Filter readings (average, median) |
| Blocking reads | System freezes | Use non-blocking or timeouts |
| Trusting first reading | Startup garbage | Discard first N samples |
| Wrong units | Calculations off by 1000× | Check: ms vs µs, cm vs mm, °/s vs rad/s |
# WRONG: Trust first IMU reading
gyro_z = imu.read_gyro_z() # Often garbage at startup!
# RIGHT: Calibrate
samples = [imu.read_gyro_z() for _ in range(100)]
gyro_bias = sum(samples) / len(samples)
# Now subtract bias from readings
6. Timing Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
Using sleep() everywhere |
System unresponsive | Use non-blocking timing |
| Printing in tight loops | Loop slows to ~10Hz | Buffer logs, print later |
| Forgetting timing varies | Works sometimes, fails others | Measure actual timing |
| No timeout on blocking ops | Hangs forever | Always set timeouts |
| Microsecond precision in Python | Doesn't work | Python is ~500µs per operation; use hardware |
# WRONG: Blocks everything
while True:
read_sensors()
time.sleep(0.1) # Nothing else can happen!
# RIGHT: Non-blocking
last_read = time.ticks_ms()
while True:
if time.ticks_diff(time.ticks_ms(), last_read) >= 100:
last_read = time.ticks_ms()
read_sensors()
# Other code can run here!
7. Software/Hardware Boundary Mistakes
| Mistake | What Happens | Lesson |
|---|---|---|
| Bit-banging fast protocols | Protocol fails | Use hardware (PIO, SPI, I2C) |
| Ignoring hardware limits | Unexpected behavior | Read the datasheet |
| Not checking return values | Silent failures | Always check for errors |
| Assuming instant response | Race conditions | Hardware takes time; add delays if needed |
The "Magic Smoke" Hall of Fame
Things that permanently damage hardware:
| Action | Result | Prevention |
|---|---|---|
| Reverse polarity | Dead ICs instantly | Protection diode, check before power |
| 5V to 3.3V input | Slow death or instant | Level shifter, voltage divider |
| Short output to ground | Burned GPIO pin | Series resistor, careful wiring |
| Motor stall for too long | Burned windings, driver | Current sensing, timeout |
| Static discharge | Random failures later | Ground yourself, handle by edges |
| Overvoltage to motor driver | Dead H-bridge | Check VM max rating |
The Golden Rule
When something doesn't work, check power first.
90% of "mysterious" embedded failures are: 1. Dead/low battery 2. Wrong voltage 3. Loose connection 4. Ground not connected
Check these before debugging code!
Schematic Reading Exercise
For EE Students
Practice tracing signals from the MCU to the actuator/sensor.
Exercise 1: Motor Path
Starting from GP12, trace the signal path to the left motor:
1. GP12 → TB6612 AIN1 → ...
2. What determines motor direction?
3. What determines motor speed?
Exercise 2: Sensor Path Starting from a line sensor phototransistor: 1. Light reflects → phototransistor conducts → voltage at ADC pin 2. What determines the voltage range? 3. Why does black read different from white?
Exercise 3: Power Path Trace power from battery to motor: 1. Battery → boost converter → 5V rail → TB6612 VM → motor 2. What happens if battery is low? 3. Where is current limited?
Further Reading
- TB6612FNG Datasheet - Motor driver details
- BMI160 Datasheet - IMU specifications
- WS2812B Protocol - LED timing requirements
- HC-SR04 Datasheet - Ultrasonic sensor
Related Documents
- GPIO Basics - Voltage levels, pull resistors
- PWM Reference - PWM for motor control
- Motor Basics - Hardware and control patterns
- IMU Reference - IMU usage and calibration