Debugging Layers
Problems usually fall into three layers. Learning to identify which layer you’re in separates frustrated students from successful ones.
Layer 1: “I forgot to…” (Usability)
Section titled “Layer 1: “I forgot to…” (Usability)”Symptoms: Code runs, but nothing happens. Or behaves weirdly.
Common Gotchas
Section titled “Common Gotchas”| Issue | What Happened |
|---|---|
| Buttons | Using IsPressed (checks once) vs WasPressed (event trigger) |
| Servos | Forgetting to set the pin number in the Hardware tab |
| Loops | Missing Wait blocks causing instant loops |
| Screens | Forgetting Update blocks for dynamic content |
Quick fix: Re-watch the UIFlow Interface video. Most issues are “oh, that’s where that setting lives.”
Layer 2: “The hardware isn’t talking…” (Configuration)
Section titled “Layer 2: “The hardware isn’t talking…” (Configuration)”Symptoms: Error messages like [Errno 19] ENODEV or EIO, or silent failures.
The #1 Rule
Section titled “The #1 Rule”Check physical first, code second.
| Check | How | Why It Matters |
|---|---|---|
| Power switch | Look for tiny slide switch on bases/hubs | Bases need their own power |
| Cable orientation | Yellow=SDA, White=SCL, Red=VCC, Black=GND | Wrong wiring = no communication |
| Port vs Pin | Port A = I2C (G1/G2). Header pins = PWM/GPIO | Mixing these causes “ENODEV” errors |
| I2C address conflicts | Two sensors can’t share address 0x44 | Use a scan to check |
Diagnostic Tool: I2C Scanner
Section titled “Diagnostic Tool: I2C Scanner”Run this code to see what your StickS3 actually detects:
import machinei2c = machine.I2C(0, scl=machine.Pin(1), sda=machine.Pin(2), freq=100000)print("I2C devices found:", [hex(addr) for addr in i2c.scan()])Reading results:
- Empty list
[]→ Hardware/wiring issue (Layer 2) - Shows
[0x38]or similar → Configuration/code issue (Layer 1 or 3)
Layer 3: “This should work but doesn’t…” (Firmware/Bugs)
Section titled “Layer 3: “This should work but doesn’t…” (Firmware/Bugs)”Symptoms: Code that looks correct throws weird errors, or works inconsistently.
Real Examples from Students
Section titled “Real Examples from Students”| Problem | What’s Happening | Workaround |
|---|---|---|
| ”Motion base not in hardware list” | UIFlow 2 filters by device type; StickS3 hides Atom Motion | Use raw I2C blocks at address 0x38 instead |
Servo180Unit(None, ...) in generated code | UIFlow didn’t detect pin assignment | Manually set pin in Hardware tab, or use Pin(2) in Python |
| Servo jitters, device resets | Servo drawing too much power from StickS3 battery | Keep USB plugged in during testing |
| ENV III reads 85C constantly | Sensor needs status register reset | Add 1s delay after init, or use raw SHT30 driver |
When to Suspect Layer 3
Section titled “When to Suspect Layer 3”You’ve checked Layer 1 (blocks look right) and Layer 2 (I2C scan finds device), but behavior is still wrong.
What to do:
- Switch to Python view in UIFlow
- Check the generated code for
Noneor missing values - Try raw I2C blocks instead of unit-specific blocks
- Check the M5Stack Community Forum for known issues
UIFlow 2.0 Architecture
Section titled “UIFlow 2.0 Architecture”Understanding what’s happening under the hood helps with debugging:
Your Blocks → Python Code (MicroPython) → ESP32-S3 Firmware → Hardware ↑ ↑ ↑ Visual REPL/Files Drivers (I2C, PWM, WiFi)Key insight: UIFlow is just generating Python. You can always:
- Build in blocks (fast prototyping)
- Switch to Python tab to see the code
- Edit Python directly for precision
- Use mpremote or M5Burner to manage files directly
Reading Generated Code
Section titled “Reading Generated Code”When you click the Python tab in UIFlow, look for:
| Code | What It Does |
|---|---|
M5.begin() | Initializes the device |
i2c0 = I2C(0, scl=Pin(1), sda=Pin(2)) | I2C on Port A |
Pin(17) or similar | Direct GPIO (header pins) |
while True: | The main loop (your Loop blocks) |
Red flags in generated code:
Noneinstead of aPin()object → Hardware not configured- Missing
time.sleep()→ Blocking loop consuming 100% CPU - Hardcoded addresses without scan → Brittle I2C assumptions
Was this page helpful?