Build it yourself

ESP32 build.

An alternate brain board. The main build uses a Raspberry Pi Pico 2 W. This path is for people who would rather use an ESP32. Same body, same firmware, a few extra command-line steps.

≈ 20 MIN · COMMAND LINE · ANY 2.4 GHz ESP32

BUY THE $99 KIT →
The finished Growbot body: two servo legs, a battery pack, and a phone as the mind

same body, an ESP32 for a brain

With help by olie-o, who first tested Growbot on the ESP32. The body, servos, wiring and gluing are identical to the main build. Only the brain board and the flashing steps change.
01

What you need

  • An ESP32 dev board (classic ESP32, or S3/C3) with a data USB cable, not charge-only.
  • 2× servos and a 5-6 V battery for the body, same as the main build.
  • Python 3 on your computer.
  • The GrowBot Body Kit (firmware files and 3D prints).
02

Get the firmware

Download the kit from the main build page (Step 05, Download the kit) and unzip it. You work inside the growbot-body-kit/firmware/ folder.

Then grab a MicroPython image for your ESP32 from micropython.org/download. Pick your exact board, download the .bin, and save it into that firmware/ folder.

03

Install the tools

In a terminal, inside the growbot-body-kit/firmware/ folder:

pip install esptool mpremote

Optional but tidy: make a virtualenv first, python3 -m venv .venv then source .venv/bin/activate (macOS/Linux) or .venv\Scripts\Activate.ps1 (Windows).

04

Flash MicroPython

Plug the ESP32 into your computer with a data USB cable (a charge-only cable will not show a serial port), then find its port:

mpremote connect list # any OS, shows the port # macOS: ls /dev/cu.* # Linux: ls /dev/ttyUSB* /dev/ttyACM* # Windows: a COMx port

Erase, then flash the .bin you downloaded (replace the port and filename):

esptool --chip esp32 --port PORT erase-flash esptool --chip esp32 --port PORT write-flash 0x1000 YOUR_FIRMWARE.bin
Flash offset. Classic ESP32 uses 0x1000 (above). ESP32-S3 / C3 flash at 0x0 instead: use --chip esp32s3 (or esp32c3) and write-flash 0x0 …. Some boards need you to hold the BOOT button while flashing starts.
05

Point the driver at your pins

The servo driver auto-detects a Pico carrier board. On a bare ESP32 you tell it to drive the pins directly. Open firmware/PicoRobotics.py, find the config block near the top, and set FORCE plus your two pins:

FORCE = "gpio" # was None GPIO_PINS = {1: 18, 3: 19} # left, right, pick from the table below

Use two free PWM-capable output GPIOs, then wire each servo's signal (orange) to its pin. The safe defaults differ by chip, and the big trap is the S3/C3 native-USB pins:

CHIP GOOD PINS (LEFT, RIGHT) AVOID FOR SERVOS
ESP32 (classic) {1: 18, 3: 19} 34-39 (input-only), 0/2/12/15 (strapping)
ESP32-S3 {1: 4, 3: 5} 19/20 = USB! · 0/3/45/46 (strapping)
ESP32-C3 {1: 4, 3: 5} 18/19 = USB! · 2/8/9 (strapping)
On the S3/C3, putting a servo on a USB pin fights the board's USB connection (random resets or disconnects), use the pins above instead. Servos draw power from the battery rail, never from an ESP32 pin, a GPIO cannot source servo current and will brown out or reset.
06

Add your Wi-Fi & upload

Copy the template, fill in your 2.4 GHz network (the ESP32 is 2.4 GHz only):

2.4 GHz only. That is the Wi-Fi band, not your internet type: 5G home, fibre and cable all work. Most routers broadcast a 2.4 GHz network; if you only see one, enable or split it in your router settings.
cp secrets.example.py secrets.py # then edit secrets.py: # WIFI_SSID = "YourNetwork" # WIFI_PASSWORD = "YourPassword"

Upload all four files (relay_chip.py becomes main.py):

mpremote cp secrets.py :secrets.py mpremote cp PicoRobotics.py :PicoRobotics.py mpremote cp act_engine.py :act_engine.py mpremote cp relay_chip.py :main.py mpremote reset

On reset the ESP32 runs the leg-check, then joins your Wi-Fi and dials the GrowBot relay.

07

Read your pairing code

The code prints at boot, but ESP32 dev boards reset when the serial port opens, so it is easy to miss. You do not need to catch it: the code is just gb- plus the chip's hardware id, so print it any time:

mpremote exec "import binascii,machine; print('gb-'+binascii.hexlify(machine.unique_id()).decode()[-6:])"

That prints something like gb-7a3f0c. It is the same every boot, so write it down once. (To watch the live boot log instead: mpremote repl, then tap the board's reset.)

08

Connect your phone

Your phone reaches the robot over Wi-Fi, through the relay, not over the USB cable. On your phone, open the controller, type your pairing code, and connect:

▶ OPEN THE CONTROLLER

Green dot means connected. Then drive it: Manual, Policy and voice. Pairing code shown plus phone connected means you are done. Send a clip!

Troubleshooting

SYMPTOM FIX
"No module named PicoRobotics" A file did not upload. Repeat the mpremote cp step and check each succeeds.
no green dot / won't connect Wi-Fi is 2.4 GHz? secrets.py correct? Code typed exactly (lowercase)? Confirm it joined: mpremote exec "import network;print(network.WLAN(network.STA_IF).isconnected())"
servos don't move Signal wires on the GPIOs from your GPIO_PINS, shared ground, servos on the battery (not a GPIO), and the Step 05 edit saved.
board resets / USB drops when a servo moves A servo is on a USB pin. S3 = GPIO19/20, C3 = GPIO18/19. Move it to a safe pin (Step 05) and update GPIO_PINS.
flashing fails Right port? Right --chip and offset for your board? Data USB cable? Close other serial apps; some boards need BOOT held.
ESP32 support is community-tested, with help from olie-o. Found a better GPIO setup or a board-specific fix? Share it in the Discord and we will fold it in.

Rather skip all this?

The Founder Batch kit has every part in one box, numbered, with a one-click flasher. Same robot, same free software, none of the command line.

SEE THE $99 KIT →

Questions or stuck? info@growbot.dev or join the Discord. Or go back to the main Pico build.