Embedded Thinking Cheatsheet
A one-page reference for embedded systems concepts. Keep this open during labs.
1. Execution Models
Understanding how your code runs is fundamental to embedded engineering.
| Model | Description | When to Use | Limitation |
|---|---|---|---|
| Polling (Round-Robin) | Main loop checks everything sequentially | Simple systems, few tasks | Slow response, wastes CPU |
| Event-Driven | Code runs in response to events | Medium complexity | Still single-threaded |
| Interrupt-Driven | Hardware triggers immediate response | Time-critical events | ISR must be short |
| State Machine | Explicit states + transitions | Complex behavior | More code structure |
| RTOS | Multiple tasks, scheduler decides | Many concurrent tasks | Overhead, complexity |
COMPLEXITY SPECTRUM:
Polling ──▶ Events ──▶ Interrupts ──▶ FSM ──▶ RTOS
simple complex
slow response fast response
easy to debug harder to debug
2. Time Vocabulary
These terms appear constantly in embedded systems. Know them precisely.
| Term | Definition | Typical Range | Example |
|---|---|---|---|
| Latency | Time from event to response | µs to ms | Button press to LED on |
| Jitter | Variation in timing | µs to ms | PWM period varying ±5µs |
| Deadline | Maximum allowed latency | Defined by application | Motor update every 10ms |
| Throughput | Events processed per second | Hz or events/sec | 1000 sensor readings/sec |
| Period | Time between repetitions | ms to s | Control loop runs every 20ms |
| Duty Cycle | ON time / total period | 0-100% | 50% PWM = half power |
Time Budget Example
Main loop iteration: 20ms deadline
├── Read sensors: 5ms
├── Process data: 3ms
├── Update motors: 2ms
├── Update display: 8ms
└── Margin: 2ms ← ALWAYS leave margin!
────
20ms
3. The Golden Rules
ISR Rules (Interrupt Service Routines)
- Keep it SHORT - Set a flag, update a counter, return
- No blocking - Never use
sleep(),delay(), or wait loops - No I/O - Never use
print(), UART, or file operations - Volatile variables - Shared data must be marked
volatile - Atomic access - Multi-byte variables need protection
# GOOD ISR pattern
button_pressed = False # Should be volatile in C
def button_isr(pin):
global button_pressed
button_pressed = True # Just set flag, return immediately
# Main loop handles the work
while True:
if button_pressed:
button_pressed = False
handle_button() # Complex logic here, not in ISR
Measurement Rules
- Measure FIRST - Before tuning, understand the system
- Multiple samples - One reading is anecdote, 100 is data
- Quantify uncertainty - "25 ± 1.5 cm" not just "25 cm"
- Log everything - Data explains behavior better than observation
- Validate claims - "It works" needs evidence
Design Rules
- Non-blocking - Never
sleep()in the main loop if you can avoid it - State machines - Make behavior explicit and testable
- Timing budgets - Know how long each operation takes
- Fail safely - What happens when sensors fail?
- Document assumptions - Future you will thank present you
4. Shared Resources
Embedded systems have limited resources. Know what's shared.
| Resource | Shared By | Danger | Solution |
|---|---|---|---|
| CPU | Main loop, ISRs, (tasks) | Starvation, jitter | Time budgets, priorities |
| Memory (RAM) | All code, stack, heap | Overflow, corruption | Static allocation, monitoring |
| Peripherals | Multiple code paths | Race conditions | Locks, careful design |
| I/O Pins | Hardware, software | Conflicts | Clear ownership |
| Communication | Multiple messages | Corruption, loss | Protocols, error checking |
5. Common Patterns
Pattern: Debounce
# Problem: Button bounces cause multiple triggers
# Solution: Ignore changes for debounce period
last_press_time = 0
DEBOUNCE_MS = 50
def button_handler():
global last_press_time
now = time.ticks_ms()
if time.ticks_diff(now, last_press_time) > DEBOUNCE_MS:
last_press_time = now
# Handle the press
Pattern: Non-Blocking Timing
# Problem: sleep() blocks everything
# Solution: Check elapsed time
last_update = time.ticks_ms()
UPDATE_INTERVAL = 100 # ms
while True:
now = time.ticks_ms()
if time.ticks_diff(now, last_update) >= UPDATE_INTERVAL:
last_update = now
do_periodic_task()
# Other tasks can run here!
do_other_stuff()
Pattern: State Machine
# States
STATE_IDLE = 0
STATE_MOVING = 1
STATE_STOPPED = 2
state = STATE_IDLE
while True:
if state == STATE_IDLE:
if start_button_pressed():
start_motors()
state = STATE_MOVING
elif state == STATE_MOVING:
if obstacle_detected():
stop_motors()
state = STATE_STOPPED
elif goal_reached():
stop_motors()
state = STATE_IDLE
elif state == STATE_STOPPED:
if obstacle_cleared():
start_motors()
state = STATE_MOVING
6. Quick Reference: MicroPython
Timing
import time
time.ticks_ms() # Current time in ms
time.ticks_us() # Current time in µs
time.ticks_diff(a,b) # Difference (handles overflow)
time.sleep(1) # Sleep 1 second (BLOCKING!)
time.sleep_ms(100) # Sleep 100ms (BLOCKING!)
GPIO
from machine import Pin
# Output (onboard LED)
led = Pin("LED", Pin.OUT)
led.value(1) # HIGH
led.value(0) # LOW
led.toggle()
# Input with pull-up
button = Pin(14, Pin.IN, Pin.PULL_UP)
if button.value() == 0: # Pressed (active low)
pass
# Interrupt
button.irq(trigger=Pin.IRQ_FALLING, handler=callback)
PWM
from machine import Pin, PWM
# PWM on buzzer (GPIO 15) - frequency controls pitch
buzzer = PWM(Pin(15))
buzzer.freq(440) # 440 Hz = A4 note
buzzer.duty_u16(32768) # 50% duty for clear tone
buzzer.duty_u16(0) # Silence
ADC
from machine import ADC
adc = ADC(26) # GPIO26 = ADC0
raw = adc.read_u16() # 0-65535
voltage = raw * 3.3 / 65535
7. Debugging Checklist
When something doesn't work:
- [ ] Power - Is the device powered? Battery charged?
- [ ] Connections - Wires connected? Correct pins?
- [ ] Code uploaded - Latest version on device?
- [ ] Print statements - Add them to trace execution
- [ ] Timing - Is something blocking? Check with timestamps
- [ ] Scope/Analyzer - Look at actual signals if available
- [ ] Simplify - Remove code until it works, add back incrementally
8. The Engineering Mindset
Before ES101: "It works!"
After ES101: "It works, and here's the data that proves it,
explains why, and predicts when it won't."
Questions to Always Ask
- How do I know it works? (Not "I tested it once")
- Under what conditions? (Temperature, battery, surface...)
- What's the uncertainty? (±X, confidence interval)
- What could fail? (Edge cases, environmental factors)
- How would I detect failure? (Monitoring, validation)
Cross-Reference
- [[Reference/extras/mental-models-map|Mental Models Map]]
- [[Tutorials/robot-unboxing|Tutorial: Robot Unboxing]]
- [[Tutorials/hardware-abstraction|Hardware Abstraction tutorial]]