ESP32-C3 Robot App
🤖 explore · 🛠️ build · 🚀 deploy
tap to skip
بِسْمِ اللهِ الرَّحْمٰنِ الرَّحِيْمِ

ESP32-C3 Robot App

🤖 explore · 🛠️ build · 🚀 deploy

Disconnected
STATUS: ONLINE CHIP: ESP32-C3 CORE: arduino-esp32 CLEARANCE: NEWBIE 14 MISSIONS LOADED
⚡ MISSION 01 — BRIEFING — what are we hacking?

// objective: understand the rig before touching it

ESP32-C3

RISC-V chip with built-in WiFi + Bluetooth. The brain of your robot.

Arduino framework

The friendly C++ dialect with setup(), loop(), digitalWrite().

PlatformIO

The build tool. Downloads libs, compiles, flashes, monitors. Driven from launch.sh.

HARDWARE

Servos · NeoPixel LEDs · buzzer · OLED · ultrasonic · BT phone control

// FAST PATH Skip the reading. Run ./launch.sh → option 0 → grab a snack. The launcher does everything.
🗺 MISSION 02 — LAYOUT — the bunker map

// objective: know which file does what

01_app/ # project root (you are here) ├── platformio.ini # ⚙ build orders ├── launch.sh # 🎮 the menu │ ├── 01_src/ # 🔧 firmware — one .h/.cpp per system │ ├── 01_src.ino # entry point (setup + loop) │ ├── 00_config.h # pin map │ ├── 02_data.{h,cpp} # shared state │ ├── 03_remotexy.{h,cpp} # 📱 phone control │ ├── 05_buzzer.{h,cpp} # 🔊 sounds │ ├── 06_neopixels.{h,cpp} # 💡 LEDs │ ├── 09_servos.{h,cpp} # 🦾 motors │ ├── 12_ultrasonic.{h,cpp} # 📡 distance │ ├── 13_oled.{h,cpp} # 📺 display │ └── ... │ ├── 02_web/ # 🌐 browser flasher + docs ├── 03_logs/ # 📜 past command logs └── .pio/ # 🛠 build cache (ignore)
// PRO TIP The NN_ prefix is reading order only. Compiler ignores it. Top-down = config → data → features → demos.
🔮 MISSION 03 — .INO MAGIC — what Arduino does behind your back

// objective: stop being mystified by .ino files

An .ino file is C++ with two cheats:

CHEAT 1

Auto-injects #include <Arduino.h> at the top — gives you pinMode, Serial, etc. for free.

CHEAT 2

Auto-generates forward declarations — call any function before defining it.

// WHAT YOU WRITE (.ino)

void setup() {
    pinMode(LED, OUTPUT);
    blink();          // OK in .ino
}
void loop() { delay(1000); }
void blink() {
    digitalWrite(LED, HIGH);
}

// WHAT COMPILER SEES

#include <Arduino.h>   // injected
void blink();          // injected

void setup() {
    pinMode(LED, OUTPUT);
    blink();
}
void loop() { delay(1000); }
void blink() {
    digitalWrite(LED, HIGH);
}
// REQUIRED Every sketch needs setup() (runs once) and loop() (runs forever). The framework calls them — main() is hidden inside Arduino.h.
⚙️ MISSION 04 — CONFIG — platformio.ini decoded

// objective: read the build orders

[env:esp32-c3-devkitm-1]
platform     = espressif32 @ 6.7.0   ; PINNED — ESP-IDF 5.1, fixes RMT bug
board        = esp32-c3-devkitm-1    ; pin map + flash size
framework    = arduino               ; activates Arduino API
monitor_speed = 115200               ; serial baud rate

build_flags =
    -D FASTLED_RMT_MAX_CHANNELS=1    ; C3 has only 2 RMT slots
    -D FASTLED_RMT_BUILTIN_DRIVER=1  ; use IDF's tested RMT driver

lib_deps =
    RemoteXY                         ; phone control via BLE
    fastled/FastLED @ ^3.7.0         ; NeoPixel (version pinned)
    madhephaestus/ESP32Servo         ; servo library
    adafruit/Adafruit GFX Library    ; OLED graphics
    adafruit/Adafruit SSD1306        ; OLED driver
// VERSION PINNING — why bother? @ 6.7.0 = exactly this version. @ ^3.7.0 = 3.x but ≥ 3.7. Without pins, today's build differs from tomorrow's — silent regressions sneak in. Pinning = reproducibility.
// LESSON LEARNED The old unpinned platform = espressif32 shipped ESP-IDF 4.x with a buggy RMT ISR. NeoPixels caused random Guru Meditation crashes. Pinning to 6.7.0 (ESP-IDF 5.1) fixed it. See BUG-001.
🚀 MISSION 05 — LAUNCHER — the cockpit

// objective: stop typing commands. Press numbers.

+============================================================+ | * ROBOT-01 LAUNCHER . ESP32-C3 firmware toolkit | +============================================================+ [O.O] os: windows-bash port: COM8 pio: OK >>> 0) [bot] SETUP MY ROBOT (one-click install) <<< s) ⚙️ toolchain — check & install the goods b) 🔥 deploy 4) compile # pio run 5) clean # pio run -t clean 6) upload (flash) # pio run -t upload 7) erase flash # esptool erase_flash 8) serial monitor # pio device monitor 9) select port # pick COM / ttyUSB 10) full flash ← the one-shot mission w) 🌐 cyberspace — IDE, dashboards & web tools g) 📡 git ops — track your code ⚡ shortcuts: 4=build 10=flash 8=monitor q=quit

Accordion menu: press a letter (s, b, w, g) to expand a section, or just type the number directly. Numbers always work whether expanded or not.

🎯 ONE-SHOT

./launch.sh flash — compile + upload + monitor in one command.

🔧 HOTKEYS

./launch.sh compile
./launch.sh upload
./launch.sh monitor

🚨 PORT OVERRIDE

PORT=COM7 ./launch.sh upload
forces a specific port

🛠 MISSION 06 — FIRST DEPLOY — bootstrap sequence

// objective: install everything, transparently

Pick option 0. The launcher runs four automatic levels:

L1

Python check

If missing, runs winget install Python.Python.3.13 automatically. No clicks.

L2

PlatformIO

pip install -U platformio · ~30 MB download.

L3

esp32 platform

The big one. Arduino-ESP32 core + toolchain + libs · ~150 MB. Grab a snack.

L4

VS Code ext

Optional. Adds PlatformIO IDE in the editor sidebar.

// MSYS2 WARNING If you're in a UCRT64/MINGW64 shell, the launcher dodges MSYS2's broken POSIX Python automatically. If only MSYS2 Python is found, you'll get a clear pacman / python.org instruction.
🔄 MISSION 07 — BUILD PIPELINE — code → robot

// objective: see what happens when you press "compile"

YOUR CODE 01_src/*.cpp+.ino PIO RUN compile + link ~60 s 3 BINARIES bootloader.bin partitions.bin firmware.bin ROBOT BOOTS via USB · esptool option 4 option 6 USB

Option 10 = full flash = compile + upload + monitor in one shot.

💾 MISSION 08 — FLASH MAP — where bytes live

// objective: know what gets written where

The 3 binaries are written at fixed offsets in the chip's 4 MB flash:

BOOT0x0
PART0x8000
FIRMWARE (your code)0x10000 → end
SegmentWhat it does
bootloader.binThe first code that runs on power-up. Loads the partition table, then jumps to firmware.
partitions.binA tiny table saying "firmware lives here, OTA backup there, NVS data over there."
firmware.binYOUR sketch — every .cpp in 01_src/ compiled together.
// ERASE Option 7 wipes ALL flash. Use after flashing weird firmware or when the chip acts haunted.
🔁 MISSION 09 — BOOT/RESET TRICK — when upload fails

// objective: force the chip into bootloader mode manually

ESP32-C3 CHIP BOOT RST HOLD BOOT · TAP RESET · RELEASE BOOT · RETRY UPLOAD

// the chip enters bootloader mode and accepts the next flash operation

🌐 MISSION 10 — WEB FLASHER — share without installing

// objective: let anyone flash via Chrome — no terminal required

Step 1 · Package

./launch.sh package-web — builds + copies bins to 02_web/firmware/

Step 2 · Serve

./launch.sh serve — starts http://localhost:8000

Step 3 · Click

Plug board → flash.html → click Connect & install. Done.

// COMPATIBILITY Web Serial only works in Chrome and Edge. Firefox + Safari don't support it yet.
🚨 MISSION 11 — TROUBLESHOOTING — when things go sideways

// objective: diagnose like a pro

// "FAILED TO CONNECT" / TIMEOUT See MISSION 09 — the BOOT/RESET trick. Works 90% of the time.
// NO PORT DETECTED Windows: install CP210x or CH340 USB-serial driver.
macOS: use /dev/cu.usbserial-*, not /dev/tty.*.
Linux: sudo usermod -aG dialout $USER then log out/in.
// "ImportError: pyexpat" (MSYS2 only) Your /usr/bin/python3 is broken. Either install python.org Python (launcher auto-detects it) or:
pacman -Syu
pacman -S mingw-w64-ucrt-x86_64-python mingw-w64-ucrt-x86_64-python-pip
// "library X not found" Pick option 3 (install board files) or 16 (update libs).
// "pio: command not found" — but install succeeded Pip put it in a dir not on PATH. The launcher works around this via python -m platformio. To fix permanently, paste the suggested export PATH=… into your ~/.bashrc.
🔍 MISSION 12 — DEBUG — decoding crash dumps with addr2line

// objective: turn a wall of hex into a function name

When the ESP32-C3 panics, you get a "Guru Meditation" register dump. Those 0x4038xxxx addresses look like noise — but they're real instructions in your firmware. The addr2line tool maps them back to filename.cpp:line_number. This is the move that solved BUG-001.

Guru Meditation Error: Core 0 panic'ed (Instruction access fault) Core 0 register dump: MEPC : 0x3fc9027c RA : 0x4038c53c SP : 0x3fc8f8d0 MCAUSE : 0x00000001 ; 1 = instruction access fault MTVAL : 0x3fc9027c ; jumped to RAM (not executable!)

Three registers to read first:

  • MEPCwhere the CPU was when it died. 0x4038xxxx = inside flash code (decode!). 0x3fc8xxxx = inside RAM = corrupted return address.
  • RAwhere it was returning to. Decode this to find the caller.
  • MCAUSEwhy it died. 0x01 = invalid code jump. 0x05/0x07 = bad memory access. 0x02 = illegal instruction.

// run addr2line

# Linux / macOS / Git Bash:
~/.platformio/packages/toolchain-riscv32-esp/bin/riscv32-esp-elf-addr2line \
    -fipe .pio/build/esp32-c3-devkitm-1/firmware.elf \
    0x4038c53c 0x403801ee 0x4038907e 0x40389094

# Output:
_global_interrupt_handler at .../riscv/interrupt.c:66
ESP32RMTController::interruptHandler at .../idf4_rmt_impl.cpp:827
vPortEnterCritical at .../freertos/port/riscv/port.c:246
// flag soup decoded -f = show function name · -i = inline expansion · -p = pretty print · -e = ELF file path

// reading the stack

  • Repeating frames at fixed offsets (e.g. every 0xC0 bytes) = recursion. Intentional or runaway (stack overflow).
  • Counter decrementing across frames = loop variable, often recursion depth.
  • Same RA repeated across many frames = function calling itself (or being re-interrupted).

That's exactly what BUG-001 looked like: ESP32RMTController::interruptHandler repeating 9× with 192-byte frames = the ISR re-entering itself before iret, overflowing the stack in milliseconds.

// gotcha: ELF file SHA256 = all zeros addr2line still works — but decode against the same firmware.elf you flashed. A stale ELF gives wrong line numbers.

// the workflow

1

Capture

Run ./launch.sh monitor, reproduce the crash, copy the full register dump.

2

Decode

Feed MEPC, RA, and a few stack pointers through addr2line.

3

Pattern-match

Look for repeating frames, decrementing counters, RAM-pointed MEPC.

4

Log it

Add a bug entry to audit.html. Future-you will thank present-you.

💻 MISSION 13 — PRO MODE — raw commands

// objective: skip the menu when you know what you're doing

# compile
python -m platformio run

# upload
python -m platformio run -t upload --upload-port COM3

# erase chip
python -m esptool --chip esp32c3 --port COM3 erase_flash

# serial monitor
python -m platformio device monitor -b 115200 --port COM3

# clean
python -m platformio run -t clean

# update everything
python -m platformio pkg update

If pio is on PATH, drop the python -m prefix.

🎨 MISSION 14 — ARDUINO IDE — the fallback path

// objective: build the same code without PlatformIO

The source in 01_src/ is plain Arduino C++ — Arduino IDE 2.x can compile it too. You'll redo the config by hand (no platformio.ini in IDE land).

Setup checklist

1

Open the sketch

File → Open → pick 01_src/01_src.ino. Folder name must match the .ino name — Arduino IDE requirement.

2

Install board

Boards Manager → search esp32 → install esp32 by Espressif Systems

3

Install 5 libraries

Library Manager: FastLED, ESP32Servo, Adafruit GFX Library, Adafruit SSD1306, RemoteXY

4

Pick the board

Tools → Board → ESP32 Arduino → ESP32C3 Dev Module

5

Tools menu config

USB CDC On Boot = Enabled
Core Debug Level = Info
Upload Speed = 921600
Partition Scheme = Huge APP

6

Upload

Plug board → pick port → click ✅ Verify, then ➜ Upload. If it fails, try the BOOT/RESET trick.

What won't carry over from PlatformIO

PlatformIO featureArduino IDE equivalent
pinned lib_deps versionsLibrary Manager — no version pinning
build_flags = -DXYZ=…only what's in the Tools menu
[env:debug] / [env:release]none — change settings each time
esp32_exception_decoder filternone — crash dumps stay raw hex
./launch.sh flash one-shotVerify + Upload separately
// WHEN TO USE WHICH PlatformIO for daily work — faster, reproducible, scriptable, the launcher works.
Arduino IDE for a quick test on a borrowed laptop, or when teaching someone who already knows Arduino.
// SAME SOURCE Both tools compile the exact same code in 01_src/. Different toolchains, identical firmware.
🏠 Home 📋 Audit & Bugs ⚡ Web Flasher