The Maker’s Companion to the PO-33 ESP32-S3 Firmware
A study guide for Make: Electronic Music from Scratch × Ravine: Phoenix
Audience: complete novices. Every technical term is defined the first time it appears. If you’ve never written a line of code or soldered a single joint, you are the intended reader.
How to use this book. Each chapter pairs one chapter of Kirk Pearson’s Make: Electronic Music from Scratch (Dogbotic, 2024) with one slice of our PO-33 firmware. The first half of each chapter is a friendly recap of Pearson’s chapter in plain language. The second half shows you how to make our firmware do the same thing — usually in a UART shell session, since that’s how a headless developer tests the firmware. There are no math prerequisites and no C-code-reading prerequisites; the few lines of code we do quote are heavily commented.
Table of contents
- How to use this book
- Setup: from zero to a beeping ESP32 in fifteen minutes
- Companion to Pearson Chapter 1 — A People’s History of Electronic Music
- Companion to Pearson Chapter 2 — Musical Electricity for Electrophobes
- Companion to Pearson Chapter 3 — The Hello World Oscillator
- Companion to Pearson Chapter 4 — Amps, Reverbs, and Talkboxes
- Companion to Pearson Chapter 5 — Soldering, Enclosures, and UI
- Companion to Pearson Chapter 6 — Chaining Oscillators
- Companion to Pearson Chapter 7 — Schematics and Mass Transit
- Companion to Pearson Chapter 8 — Filters
- Companion to Pearson Chapter 9 — Harmonization
- Companion to Pearson Chapter 10 — Modulation
- Companion to Pearson Chapter 11 — Sequencers
- Companion to Pearson Chapter 12 — Electronic Percussion
- Companion to Pearson Chapter 13 — Phase-Locked Loops
- Companion to Pearson Chapter 14 — The Dogbotophone MK1
- Companion to Pearson Chapter 15 — Thoughts on Automation
- Companion to the Appendices
- Glossary
- Index
How to use this book
This book assumes you have either:
- a flashed ESP32-S3 board with our firmware running, or
- a copy of the firmware source you can build and flash yourself.
If neither is true yet, jump straight to the Setup chapter below. It walks you through getting a board talking to your computer over USB.
Once you’re set up, you have two reasonable ways to read this book:
- Sequential, in lock-step with Pearson. Read Pearson chapter N, then our chapter N. The two are designed to be read together; the conceptual debt from one chapter is paid by the next.
- Topical, dipping in as you need it. If you already know Pearson and just want to see how a particular concept maps to our firmware, the Glossary lists every concept Pearson introduces and points to the chapter of ours that explains the digital equivalent.
There are three kinds of paragraphs in this book, and they’re marked so you can skip the parts that don’t interest you:
- 🎓 Background. Conceptual explanation. Read these if you’re new to the topic. Skip them if you’ve already read Pearson.
- 🔧 Try it. A concrete exercise using the UART shell on the ESP32. These are short — usually under five commands — and they’re the most valuable part of the book. Do them, even if you read nothing else.
- 🛠 Code reference. A small pointer into our firmware source. These exist so an engineer reading this book can find the implementation quickly. Skip them if you’re not an engineer.
A note about honesty: this book is not a marketing document. Where our firmware can simulate a Pearson project, we’ll show you. Where it can’t, we’ll tell you and link to the relevant section of our design document so you know why.
Setup
This chapter assumes you’ve never touched an ESP32 before. If you have, skim to the Quick start at the end.
What you’ll need
- An ESP32-S3-WROOM-1-N16R8 dev board. This is the specific variant we support. It has 16 MB of flash and 8 MB of PSRAM, both of which we need. The board costs about $5 from any major electronics supplier (Mouser, Digikey, AliExpress). Look for the words “WROOM-1-N16R8” silkscreened on the metal shield on the back of the module.
- A USB-C cable. The board uses USB-C for both power and serial communication. Any data cable will do; some charge-only cables will silently fail to enumerate as a serial device, so try a different cable if you can’t connect.
- A computer with a serial terminal. Any of:
- Linux or macOS:
minicom,screen, or justcatover/dev/ttyUSB0(Linux) or/dev/tty.usbserial-*(macOS). - Windows: PuTTY, Tera Term, or the built-in Windows Terminal.
- Browser-based: the one-click web flasher on ravine.1une.cc can open a serial terminal in your browser. This is the easiest option.
- Linux or macOS:
- (Optional) Headphones or an external speaker. The ESP32-S3 dev
board has no built-in speaker; the firmware outputs audio via the I²S
pins. Our hardware guide (
hardware/HARDWARE.md) shows how to wire a $2 PCM5102A DAC chip to the board and connect it to a 3.5 mm jack.
If you bought a fully assembled Ravine: Phoenix device rather than building your own, you can skip the hardware steps entirely. The firmware already works on the off-the-shelf hardware.
Plug it in
- Plug the USB-C cable into the board and your computer.
- If a red or blue LED lights up on the board, congratulations — the power section is working. If nothing lights up, try a different cable or USB port.
- The board will enumerate as a serial device. The exact name depends
on your operating system:
- Linux:
/dev/ttyUSB0or/dev/ttyACM0. You may need to add yourself to thedialoutgroup:sudo usermod -a -G dialout $USERand then log out and back in. - macOS:
/dev/tty.usbserial-*. No driver install needed. - Windows:
COM3,COM4, etc. You may need to install the Silicon Labs CP210x driver from silabs.com/developers/usb-to-uart-bridge-vcp-drivers.
- Linux:
Open a serial terminal
Set your terminal to 115 200 baud, 8 data bits, no parity, 1 stop bit (115200-8-N-1). No flow control. No line ending translation.
In minicom:
minicom -D /dev/ttyUSB0 -b 115200
In screen:
screen /dev/ttyUSB0 115200
In cat (read-only — for testing):
cat /dev/ttyUSB0
Press the reset button on the board (or send Ctrl+T Ctrl+R via the
ESP-IDF monitor, if you’re using idf.py monitor). You should see
something like this scroll by:
I (312) boot: ESP-IDF v6.1.2 2nd stage bootloader
I (421) cpu_start: Pro cpu start user code
...
I (1024) main: Ravine: Phoenix PO-33 firmware v0.6.0 starting.
I (1025) amy: AMY 1.0 ready.
I (1026) main: >
The > is the shell prompt. You are now talking to the firmware. Type
help and press Enter:
> help
The firmware prints a list of every shell command it understands. There are about 30. This book will only use a handful of them, and we’ll introduce each one the first time we need it.
Quick start
If you already have a flashed board and a working serial connection:
- Type
helpand read the output. - Type
statusto see what the firmware currently knows about (active pattern, BPM, slot count, etc.). - Type
playto start the empty pattern. Typestopto stop it. - You’re ready to begin Chapter 1.
Your work is auto-saved: every 5 minutes of inactivity (and on
the sleep UART verb) the firmware writes the active sketch’s
patterns + chain + samples to flash. The next boot brings them
back automatically — the device is “where you left it”. The
explicit save / load verbs and sketch new / sketch load <id> are belt-and-braces; you don’t need to think about saving.
If anything goes wrong, the firmware has a panic log printed to the
serial port. Copy-pasting the last 30 lines into a search engine or a
GitHub issue is almost always enough to diagnose the problem.
The shell verbs this book uses
Here’s the cheat sheet for every UART command this book will use. We introduce them one at a time in the chapters where they matter, but if you skim ahead, this table tells you what’s available.
| Verb | Args | What it does | Pearson analog |
|---|---|---|---|
play |
(none) | Start the active pattern | Chapter 11 sequencers |
stop |
(none) | Stop playback | Chapter 11 |
record_mic |
<slot> <seconds> |
Record from the I²S mic into a slot | Chapter 2 (speaker as mic) |
slot_play |
<slot> |
Play a recorded slot | Chapter 11 (sequencer steps) |
slot_clear |
<slot> |
Erase a slot, free the audio buffer | Chapter 12 (drum sample delete) |
slot_copy |
<dst> <src> |
Copy a slot’s audio into another slot | Chapter 4 (amp + reverb = layered sample) |
slot_info |
(none) | List all slots: empty vs recorded, length in ms | Chapter 5 (UI: see what you have) |
pattern_info |
(none) | Show the active pattern’s 16 steps | Chapter 11 (sequencer readout) |
pattern_copy |
<dst> <src> |
Copy one pattern into another slot | Chapter 14 (Dogbotophone “pattern-changing sequencer”) |
chain_show |
(none) | Print the chain (which patterns play in order) | Chapter 11 (sequencer) |
chain_append |
<pattern> |
Add a pattern to the end of the chain | Chapter 11 |
chain_swap |
<i> <j> |
Swap two entries in the chain | Chapter 11 (live re-order) |
chain_insert |
<at> <pattern> |
Insert a pattern into the chain at a given index | Chapter 11 |
chain_remove |
<i> |
Remove a chain entry | Chapter 11 |
chain_clear |
(none) | Wipe the entire chain | Chapter 11 |
bpm |
<value> |
Set the sequencer tempo (60–240) | Chapter 11 (clock) |
fx |
<name> |
Pick the next-step effect (e.g. LOOP_16, STUTTER_4) |
Chapter 6 (vactrol arpeggiator), Chapter 10 (modulation) |
tweak_filter |
<cutoff> <resonance> |
Apply a low-pass filter on the next triggered note (knob units, 0–255) | Chapter 8 (filters) |
note |
<slot> <midi_note> |
Play a slot at a specific pitch (MIDI note number, 0–127) | Chapter 9 (octave harmonizer) |
alarm_set |
<HH> <MM> <slot> |
Schedule a sample to fire at a wall-clock time | Chapter 6 (timing circuits), bonus feature |
sync_in_toggle |
(none) | Toggle whether incoming sync pulses drive the sequencer | Chapter 13 (PLL — same idea, different medium) |
save |
(none) | Belt-and-braces: write the active sketch to flash (auto-save already covers this) | “Chapter 0” |
load |
(none) | Belt-and-braces: re-read the active sketch from flash (boot already did this) | “Chapter 0” |
sketch list |
(none) | List every saved sketch with its 4-hex id | “Chapter 0” |
sketch new |
(none) | Save the active sketch under a new 4-hex id (becomes the new active sketch) | “Chapter 0” |
sketch load |
<4-hex id> |
Load a saved sketch into PSRAM; future boots land here | “Chapter 0” |
sketch del |
<4-hex id> |
Delete a sketch from flash (samples are in PSRAM only) | “Chapter 0” |
status |
(none) | Dump everything the firmware knows | “Chapter 0” |
Two of these verbs — fx and tweak_filter — are the most-used in this
book. They directly correspond to Pearson’s chapters 6, 8, 10, and 12.