Pin numbers match include/pins.h and pinout.md.
Shared bus.
| Signal | ESP32 GPIO | Diagram pad |
|---|---|---|
| SDA | GPIO0 | GP0 → PCA9685 SDA, OLED SDA |
| SCL | GPIO1 | GP1 → PCA9685 SCL, Waveshare OLED SCL |
| Device | Address | Firmware behaviour if missing |
|---|---|---|
| PCA9685 | 0x40 |
Hard fail: hang, 1 red blink (see blink codes) |
| SSD1306 OLED | 0x3C |
Soft fail: tests continue without display |
Bus start: Wire.begin(I2C_SDA, I2C_SCL) with no explicit frequency → Arduino-ESP32 default (typically 100 kHz). Not set in this repo.
PCA9685 VCC = 3V3. OLED VCC = 3V3. Pull-ups are on the main control board and on a typical OLED; the Adafruit PCA9685 breakout has its own. No extra pull-ups.
Device: MAX98357A (mono class-D). No MCLK wire.
| Signal | ESP32 GPIO | Amp pin (as drawn) |
|---|---|---|
| BCLK | GPIO2 / GP2 | BCLK |
| WS / LRC | GPIO3 / GP3 | LRC |
| DATA | GPIO4 / GP4 | DIN |
Bring-up configuration in src/main.cpp:
| Parameter | Value |
|---|---|
| Mode | I2S_MODE_STD |
| Sample rate | 22050 (SAMPLE_RATE) |
| Width | I2S_DATA_BIT_WIDTH_16BIT |
| Slots | I2S_SLOT_MODE_STEREO |
Firmware writes identical samples to both stereo slots. MAX98357A is mono. On the main control board, gain is the solder jumper next to the amplifier (board README). On the advanced breakout, GAIN and SD stay unwired (GAIN floating ≈ 9 dB, SD pulled up ≈ left channel) — wiring.md.
On the main control board, amp Vin is AUDIO_5V (net-tied from SERVO_5V after the eFuse), not raw USB +5V — power.md. On the advanced breakout, amp Vin is the shared USB 5V rail — wiring.md. I2S wires are 3.3 V logic. Speaker connects to SPK+ / SPK− — main-control-board.md.
Warning
MAX98357A SPK- is not ground.
Generated by PCA9685, not by ESP32 LEDC/MCPWM.
- I2C command from ESP32
- 12-bit PWM, 50 Hz
- Channels 0–4
- Pulse mapping: servos.md
ESP32 GPIO is not wired to servo SIG lines.
| Signal | ESP32 GPIO | Notes |
|---|---|---|
| OE | GPIO5 / GP5 | Active LOW — outputs enabled. Firmware drives HIGH during PCA9685 init, then LOW after neutral PWM is written |
Default on (PCA9685_OE_WIRED = true in include/pins.h). Blocks invalid PWM during boot and flash resets. Set PCA9685_OE_WIRED to false only if OE is hard-tied off-chip (e.g. permanently to GND) so firmware must not drive GP5.
Single USB-C on the robot: the main control board.
| Net | Board USB-C | ESP32 / loads |
|---|---|---|
| VBUS | through fuse → +5V | ESP32 5V pad; eFuse input → SERVO_5V (servos + amp) |
| GND | common GND | GND |
| D− | data | GPIO18 |
| D+ | data | GPIO19 |
One cable for robot power, flash, and serial CDC (ARDUINO_USB_MODE=1, ARDUINO_USB_CDC_ON_BOOT=1, monitor 115200). Leave the C3-Zero onboard USB-C unused when the board USB-C supplies power and data — power.md.
The advanced path wires the same nets from an Adafruit 5993 — wiring.md.
C3-Zero has no USB–UART bridge. If CDC does not enumerate, hold BOOT (GPIO9) then attach USB (Waveshare flashing note).
| Interface | Pads | Notes |
|---|---|---|
| UART0 | GPIO21 TX / GPIO20 RX | Silkscreen; console is USB CDC |
| BLE | antenna | Hardware may be present; out of scope — product uses Wi-Fi only |
| ESP32 onboard USB-C | — | Unused when the board USB-C supplies power + data |