Wiring the hardware
One component at a time — wire it, verify it, then move on.
Your toolchain is set up from Setup — now build the real thing. This is the full pet on a half-size breadboard: the OLED again (this time on the breadboard), plus a buzzer for sound and an IMU so it reacts when you pick it up or shake it.
Add one component, run the verify command, then move on. Mistakes are much easier to debug when you only just added one wire.
What you're building with
| Part | Notes |
|---|---|
| ESP32-C3 SuperMini | Native USB-C |
| SSD1306 OLED, 0.96" | I²C, address 0x3C |
| GY-521 / MPU-6050 IMU | I²C, address 0x68 |
| Passive piezo buzzer | Must be passive, not active |
| Half-size breadboard | 400 tie-points is plenty |
| ~14 dupont jumpers (M-M) | Short ones (5–10 cm) work best |
| USB-C cable | Data, not power-only |
Before you start
You'll verify each component with a small bring-up test that lives in
the firmware repo. Every test is a single make target — it compiles a
tiny sketch, flashes it, and exercises just the sensor you just wired:
| Target | What it does |
|---|---|
make test-led | Blinks the ESP32-C3's onboard blue LED |
make test-oled | Draws "Hello" on the OLED |
make test-buzzer | Plays a short tone |
make test-mpu | Streams IMU data + opens a live browser visualizer |
No CLI install needed yet — these run straight from arduino-cli. The
gochi CLI comes at the end, once the
hardware is proven.
Pin map
The full wiring, for reference. Don't try to do it all at once — follow the steps below.
| ESP32-C3 | Goes to |
|---|---|
5V | breadboard + rail |
GND | breadboard − rail |
GPIO5 | OLED SDA |
GPIO6 | OLED SCK |
GPIO7 | MPU SDA |
GPIO8 | MPU SCL |
GPIO10 | Buzzer signal |
Why two I²C buses? The OLED runs on the C3's hardware I²C
(GPIO5/6). The MPU runs on a separate software I²C bus
(GPIO7/8). Stacking both on one bus dropped pull-up resistance too
low for fast-mode and corrupted address bytes.
Step 1 — Power rails
Plug the SuperMini into the breadboard so its pins straddle the centre gap.
Wire 5V → + rail.
Wire GND → − rail.
Plug in USB. The SuperMini's tiny red power LED should light up.
Verify:
make test-ledAfter flashing, the blue LED on the SuperMini starts blinking. That confirms power, USB data, and the toolchain are all wired up correctly before you add anything else.
For reference — where the pins sit on the board, and the two jumpers you run
in this step. USB powers the board, and the board feeds the breadboard: jumper
5V → + rail and GND → − rail (shown on the left). Once it's pushed into
the breadboard you can't read the silkscreen, so note that 5V and GND are
the top two on the left, and GPIO5/GPIO6 (the OLED's SDA/SCK) are the
top two on the right:
The kit's OLED and MPU are breakout modules with onboard regulators,
so 5V on the + rail is what they expect. If you swapped in a bare
3.3 V-only OLED panel, feed it 3V3 instead — 5 V will kill it.
Step 2 — OLED
Place the OLED on a free row. Read the silkscreen — pin order varies between modules.
Wire it up:
GND→−railVDD→+railSCK→GPIO6SDA→GPIO5
Verify:
make test-oledThe OLED should light up and draw "Hello". If it stays dark,
double-check SDA/SCK aren't swapped and VDD is on the right rail.
Step 3 — Buzzer
Place the buzzer on the breadboard.
Wire it up:
+(signal) →GPIO10−→−rail
Verify:
make test-buzzerYou should hear a short tone. Silence usually means an active buzzer slipped into the kit — see the callout below.
Passive piezo only. Active buzzers ignore tone signals and only beep at a fixed pitch — they will not reproduce the firmware's jingles. If you hear nothing, that's the first thing to check.
Step 4 — MPU-6050 IMU
The GY-521 has eight pins. You only use four.
Place the MPU module on a free row.
Wire it up:
VCC→+railGND→−railSCL→GPIO8SDA→GPIO7
Leave XDA, XCL, AD0, and INT unconnected.
Verify:
make test-mpuThis flashes the IMU streaming sketch and opens a live visualizer in your browser (Chrome or Edge — uses the Web Serial API). Tilt and shake the board and the values should move in real time.
GPIO8 is a strapping pin. The C3 samples it at reset to choose between normal boot (HIGH) and flash-download mode (LOW). The MPU holds it HIGH while connected. Plug the MPU in before USB, and never reset the board with the MPU unplugged — otherwise the firmware won't run.
If 0x69 shows up instead of 0x68, the AD0 pin is being pulled
HIGH. Change MPU_ADDR to 0x69 in firmware/src/config.h and
reflash.
Flash the full firmware
All four bring-up tests passed — the hardware is good. Now flash the actual pet firmware so the device runs the real face, sounds, and gesture loop:
make flashThe OLED wakes up a second or two later with the pet's eyes blinking and drifting around.
Drive it from the gochi CLI
With the hardware proven and the firmware flashed, the gochi CLI
gives you a friendlier interface to talk to the device — query state,
trigger sounds, set faces, and let agents drive the pet through its
local HTTP daemon. Install it from the repo you already cloned, not the
published package:
cd cli # inside the gochi repo
bun install
bun link # registers `gochi` globally
gochi setup # installs the daemon — it auto-starts at login
gochi ping # should print PONGIf gochi: command not found after bun link, Bun's global bin directory
probably isn't on your PATH. Add it:
export PATH="$HOME/.bun/bin:$PATH" # add to ~/.zshrc or ~/.bashrc to persistThere's no build step: the CLI runs its TypeScript sources directly (via
tsx), so editing anything under cli/src takes effect the next time you
run gochi.
Final end-to-end check:
gochi test allIt walks through serial → OLED → buzzer → IMU, asking a yes/no question after each. All green means you're done.
Troubleshooting
| Symptom | First thing to check |
|---|---|
make test-led fails to upload | USB cable (data, not power); try holding BOOT, tapping RESET, release BOOT |
OLED dark after make test-oled | SDA/SCK swapped; VDD on wrong rail; or the panel itself is dead |
Buzzer silent after make test-buzzer | It's an active buzzer, not passive |
make test-mpu shows no movement | SDA/SCL swapped, or AD0 pulled HIGH — see config note above |
| Board enters flash-download mode at boot | GPIO8 floated LOW — MPU got unplugged |
gochi ping doesn't return PONG | gochi daemon status — daemon may not be running |
Port busy / port already in use | Something else holds the serial port. Run gochi stop to release it (or gochi kill to terminate the daemon). Still busy? Unplug and replug the board, or try a different USB port. |