Skip to main content

Coding Guide 2 — Build and flash the Butter Bot firmware with Visual Studio Code

Install VS Code and the ESP-IDF extension, clone the firmware, compile it and flash it to the robot. The first step if you want to change the firmware itself.

A
Written by Albert Gajsak

What you'll do

The Butter Bot's brain is an ESP32-S3 chip. The program it runs (the firmware) is open source and lives on GitHub. In this guide you will:

  1. Install the free tools (Visual Studio Code + the ESP-IDF extension).

  2. Download ("clone") the firmware source code.

  3. Compile it — turn the source code into a binary the robot can run.

  4. Flash it — send that binary to the robot over USB.

You do not need to know how to program. If you can follow a recipe, you can do this.

What you need

Item

Notes

A Butter Bot

Charged, or connected to power

A USB-C data cable

⚠️ Some cheap cables are charge-only and will never show up on your computer. If in doubt, use the cable that came with a phone.

A computer

Windows 10/11, macOS 12+, or Linux

Disk space

~10 GB free (the compiler toolchain is big)

Time

1–2 hours the first time; minutes after that

Internet

Several GB will be downloaded

Which chip? Which framework? For the curious: the firmware is a standard ESP-IDF project (Espressif's official development framework) targeting the ESP32-S3. You don't need to understand ESP-IDF to follow this guide.


Step 1 — Install Visual Studio Code

Visual Studio Code (VS Code) is a free code editor from Microsoft. Get it from the official page — don't download it from anywhere else:

VS Code download page

VS Code download page

Windows

  1. Click the big blue Windows button. An installer called VSCodeUserSetup-x64-<version>.exe downloads.

  2. Double-click it, accept the license, and keep clicking Next — the default options are fine.

  3. On the last page tick "Add to PATH" if it isn't already ticked, then Finish.

macOS

  1. Click Mac (choose Apple silicon for M1/M2/M3/M4 Macs, Intel chip for older ones — if unsure, pick Universal).

  2. A .zip downloads. Double-click it, then drag Visual Studio Code.app into your Applications folder.

  3. Open it once from Applications so macOS registers it.

Linux

  1. Click .deb (Ubuntu, Debian, Mint) or .rpm (Fedora, openSUSE).

  2. Install it, e.g. on Ubuntu: bash sudo apt install ./code_*.deb (or double-click the file and use your software installer; the Snap store also has an official code package).


Step 2 — Install the prerequisites for your operating system

The ESP-IDF extension you'll install in Step 3 downloads the compiler for you, but it needs a few basics present on the system first.

Windows

Install Git for Windows (you'll need it to download the firmware, and the AI guides use it too):

The official git downloads page

The official git downloads page

  1. Go to https://git-scm.com/downloads (it redirects to the Windows install page) and download the 64-bit Git for Windows Setup (the standalone installer).

  2. Run the installer and click Next through every screen — the defaults are all fine.

(One-command alternative if you like terminals: winget install --id Git.Git -e --source winget in PowerShell.)

Everything else — Python, the compiler, the flashing tools — is handled by the ESP-IDF extension in Step 3.

⚠️ One rule on Windows: avoid spaces and OneDrive. Later, when you pick folders, use short paths like C:\esp and C:\Users\<you>\ButterBotnot Desktop/Documents folders that OneDrive syncs, and never paths with spaces. Spaces in paths are the #1 cause of mysterious build failures on Windows.

macOS

Open the Terminal app (press ⌘ + Space, type terminal, press Enter) and paste:

xcode-select --install

A dialog pops up — click Install and wait (this gives you Git and the basic build tools; 2–10 minutes). If it says "command line tools are already installed", you're done with this part.

Then check Python 3 is available:

python3 --version

Any version 3.9 or newer is fine. If that command fails, install Python from https://www.python.org/downloads/ or via Homebrew (brew install python3).

Finally, install dfu-util (a small USB utility the installer checks for). With Homebrew:

brew install dfu-util

(Don't worry about compilers, CMake or Ninja — the ESP-IDF installer in Step 3 brings its own.)

Linux (Ubuntu / Debian / Mint)

Open a terminal and paste this one command (it's the official prerequisite list of the ESP-IDF installer):

sudo apt-get install git wget flex bison gperf ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 python3 python3-pip python3-venv

Then, so that your user is allowed to talk to the robot over USB, add yourself to the dialout group:

sudo usermod -a -G dialout $USER

Log out and log back in (or reboot) — this change does not apply to already-open sessions.


Step 3 — Install and set up the ESP-IDF extension

  1. Open VS Code.

  2. Click the Extensions icon in the left sidebar (four squares, one flying away) — or press Ctrl+Shift+X (⌘+Shift+X on Mac).

  3. Type ESP-IDF in the search box.

  4. Click the one called ESP-IDF by Espressif Systems (it has ~1.5 million installs), then click Install.

The ESP-IDF extension on the VS Code marketplace

The ESP-IDF extension on the VS Code marketplace

  1. When it finishes, a new Espressif icon appears in the left sidebar.

  2. Now install ESP-IDF itself: press F1 (or Ctrl+Shift+P / ⌘+Shift+P), type "ESP-IDF: Open ESP-IDF Installation Manager" and press Enter. A small app called the Espressif Installation Manager (EIM) downloads and opens.

  3. In EIM, choose Expert Installation (not Simplified!) so you can pick the version: - ESP-IDF version: pick the v5.5.3 release for max compatibility (but newest v5.5.x release should also work). This matters — the Butter Bot firmware is built and tested against IDF 5.5.3; the "Simplified" one-click option just installs the latest stable ESP-IDF with default settings rather than letting you choose — not what we want. - Leave the install locations at their defaults (Windows: C:\Espressif; macOS/Linux: your home folder's .espressif). - On Windows, EIM checks for Git and Python and offers to install anything missing — say yes.

  4. Click through to Install and go make a coffee ☕ — it downloads the compiler toolchain (several GB, 10–40 minutes depending on your connection).

  5. When EIM reports success, go back to VS Code. If it asks which ESP-IDF version to use (or via F1"ESP-IDF: Select Current ESP-IDF Version"), pick the v5.5.x you just installed.

Windows path rules (official): the ESP-IDF install path must be under 90 characters and contain no spaces, parentheses, or special characters. The defaults are safe — just don't get creative with folder names. If a clone step later fails with a symlink error, turn on Windows Developer Mode (Settings → System → For developers) and retry. On Linux, if EIM won't open from a snap-installed VS Code, install VS Code from the official .deb instead (Step 1).


Step 4 — Download the Butter Bot firmware (the right way)

The firmware lives here:

The CircuitMess GitHub organization

The CircuitMess GitHub organization

⚠️ Do NOT use the green "Download ZIP" button

The firmware uses git submodules — three folders inside the project (components/CMF, components/ButterBot-Common, main/src/Drivers/lis3dh-pid) that live in their own separate repositories. The ZIP download leaves those folders empty, and the build fails with errors like Failed to resolve component 'CMF'. You must clone with git instead.

Windows

Open PowerShell (Start menu → type powershell → Enter), then:

cd C:\ mkdir Projects cd Projects git clone --recursive https://github.com/CircuitMess/ButterBot-Firmware-Public.git

macOS / Linux

Open a terminal:

cd ~ mkdir -p Projects && cd Projects git clone --recursive https://github.com/CircuitMess/ButterBot-Firmware-Public.git

The --recursive part is what pulls in the submodules. You should see the submodules being cloned and checked out, like this:

Cloning with submodules

Cloning with submodules

Forgot --recursive? No problem — go into the folder and run:

cd ButterBot-Firmware git submodule update --init --recursive

Quick check that everything arrived: the folder ButterBot-Firmware/components/CMF must contain files (CMakeLists.txt, README.md, …). If it's empty, run the git submodule update --init --recursive command above.

Prefer a point-and-click app? GitHub Desktop works too — it clones submodules automatically. Use File → Clone Repository → URL and paste the repository address.


Step 5 — Open the project in VS Code

  1. In VS Code: File → Open Folder… and pick the ButterBot-Firmware folder you just cloned.

  2. If VS Code asks "Do you trust the authors of the files in this folder?" click Yes, I trust the authors.

⚠️ Do NOT run "Set Espressif Device Target"

The project already comes fully configured for the ESP32-S3 (the settings live in the sdkconfig file that came with the clone). Running set-target regenerates that file from scratch and wipes the Butter Bot's tuned settings (PSRAM mode, partition layout, camera and audio configuration). If you did it by accident, restore with: bash git checkout -- sdkconfig


Step 6 — Build (compile) the firmware

  1. Press F1, type "ESP-IDF: Build Your Project", press Enter. (Shortcut: Ctrl+E B on Windows/Linux, ⌘ I B on Mac. Or use the Build icon in the blue status bar at the bottom — hover over the icons there to see what each does.)

  2. The first build compiles ~2,200 files and takes 10–20 minutes. Later builds only recompile what you changed — usually well under a minute.

  3. You'll see lots of yellow warnings scroll by — warnings are normal. Only red error lines stop the build.

A successful build ends like this:

Successful build output

Successful build output

The line to look for:

Project build complete. To flash, run: ...

Note: after the first build, git status will show sdkconfig and dependencies.lock as modified. That's the build system doing housekeeping — it's normal, ignore it.

Prefer the terminal? Everything the buttons do is also a command. In the ESP-IDF Terminal (F1ESP-IDF: Open ESP-IDF Terminal):

idf.py build

Step 7 — Connect the robot and find its port

Plug the Butter Bot into your computer with the USB-C cable and turn the robot on. Your computer sees it as a serial port; you need its name for flashing.

Good to know: the Butter Bot talks to your computer through a CH340 USB-to-serial chip. That determines what the port is called on each system and whether you need a driver.

Windows — finding the COM port

  1. Right-click the Start buttonDevice Manager.

  2. Expand the Ports (COM & LPT) section.

  3. Look for "USB-SERIAL CH340 (COMx)" — e.g. COM5. That number is your port.

  4. Not sure which one it is? Unplug the robot, watch which entry disappears, plug it back in.

Device Manager — the robot appears under Ports (COM &amp; LPT). Illustration.

Device Manager — the robot appears under Ports (COM & LPT). Illustration.

No CH340 entry, or a yellow ⚠ under "Other devices"? Windows usually fetches the CH340 driver by itself via Windows Update (give it a minute the first time, internet connected). If it doesn't, install it manually: download CH341SER.EXE from the chip maker's official page — https://www.wch-ic.com/downloads/CH341SER_EXE.html — run it, click Uninstall first (clears any stale driver), then Install, then unplug and replug the robot.

macOS — finding the port

macOS 10.14 and newer include Apple's own CH340 driver, so nothing to install. Open Terminal and run:

ls /dev/cu.*
macOS port listing

macOS port listing

Your robot is the entry that looks like /dev/cu.usbserial-XXXX (numbers vary by USB socket). Unplug/replug to see which entry comes and goes.

Two macOS notes:

  • Don't install the manufacturer's (WCH) driver — macOS's own driver works, and having both installed creates conflicting, non-working ports (you'd see an extra cu.wchusbserial-XXXX entry). If you installed one long ago and ports act strange, uninstall it.

  • On Apple Silicon Macs, if no port ever appears, check System Settings → Privacy & Security → "Allow accessories to connect" — set it to ask or allow, then replug.

Linux — finding the port

The CH340 driver is part of the Linux kernel — nothing to install. Plug the robot in and run:

ls /dev/ttyUSB*
Linux port listing

Linux port listing

The robot shows up as /dev/ttyUSB0 (or ttyUSB1, …). Two classic Linux gotchas:

  • "Permission denied" when flashing → you skipped the dialout step. Run sudo usermod -a -G dialout $USER, then log out and back in.

  • The port appears for a second and vanishes (mainly Ubuntu 22.04-era systems; fixed in Ubuntu 24.04+) → the brltty braille-display service is hijacking the CH340 chip. Fix: bash sudo apt remove brltty then unplug and replug the robot.

Nothing shows up on any OS?

  1. Try another cable — charge-only cables are the most common culprit by far.

  2. Make sure the robot is switched on.

  3. Try a different USB port (prefer plugging directly into the computer, not through a hub).


Step 8 — Flash the firmware to the robot

  1. Press F1"ESP-IDF: Select Port to Use" (or click the plug icon in the blue status bar) and pick your port from Step 7 (e.g. COM5 or /dev/cu.usbserial-110).

  2. Make sure the flash method is UART (F1"ESP-IDF: Select Flash Method" if you need to change it).

  3. Press F1, type "ESP-IDF: Flash Your Project", Enter. (Shortcut: Ctrl+E F / ⌘ I F. Or click the ⚡ Flash icon in the status bar.)

  4. You'll see Connecting...., then Writing at 0x... progress lines for each part of the firmware (the app, the voice-recognition models, the face-detection models, the sound files — the Butter Bot has several). This takes a few minutes.

  5. When you see "Flash Done ⚡️", the robot reboots and runs your freshly-built firmware. 🎉

From the terminal, the same thing is:

idf.py -p <YOUR-PORT> flash        # e.g. idf.py -p COM5 flash

If flashing fails ("Failed to connect", "No serial data received")

The robot's USB circuit puts the chip into download mode automatically — there's no button to hold. If it still won't connect:

  1. Make sure nothing else is using the port — close the serial monitor if it's open (a port can only be used by one program at a time).

  2. Double-check you picked the right port (Step 7 — unplug/replug to confirm).

  3. Power-cycle the robot (switch it off and on), then flash again.

  4. Try a different cable and a different USB port — and if you're on a USB hub, plug the robot directly into the computer.

  5. Still flaky (e.g. it disconnects partway through writing)? Flash at a slower speed: bash idf.py -p <YOUR-PORT> -b 115200 flash


Step 9 — Watch the robot think (serial monitor)

The firmware constantly prints what it's doing — priceless when you start changing things.

  • Press F1"ESP-IDF: Monitor Device" (shortcut Ctrl+E M / ⌘ I M, or the 🖥 monitor icon in the status bar).

  • To quit the monitor, press Ctrl + ] (that's Ctrl and the right square bracket).

  • Power user combo: "ESP-IDF: Build, Flash and Start a Monitor on Your Device" (Ctrl+E D / ⌘ I D) does all three steps in one go — handy once you start iterating.

Terminal equivalent:

idf.py -p <YOUR-PORT> monitor

Step 10 — Make your first change 🧈

Let's teach the robot a new joke, so you can see that you're really building your own firmware.

  1. In VS Code, open the file: components/ButterBot-Common/src/Phrases.cpp

  2. Find the block that starts with JokePhrases (around line 13). It looks like this:

static constexpr std::array JokePhrases = std::to_array<Phrases::PhraseOutput>(     {         { "I tried to optimize my code for happiness. It returned null" , 0.0f, false},         ...
  1. Add your own joke as a new line inside the inner { }, following the exact same shape — trailing comma included. The list grows automatically, so there is no size number to update:

static constexpr std::array JokePhrases = std::to_array<Phrases::PhraseOutput>(     {         { "Why did the robot go on vacation. Its circuits needed a break" , 0.0f, false},         { "I tried to optimize my code for happiness. It returned null" , 0.0f, false},         ...

(The robot speaks with a text-to-speech engine, so write the joke the way it should be pronounced — plain words, commas and periods for pauses, no emoji.)

  1. Build again (Step 6) — this time it takes ~20 seconds.

  2. Flash again (Step 8).

  3. On the robot: short-press the power button so it starts listening, then say "Tell me a joke". Keep asking — jokes are picked at random, and one of them is now yours.

Hungry for bigger changes — your own voice commands, camera-powered tricks, remapped controller buttons? Guide 5 — Program Your Butter Bot walks through all of it in full detail.


Troubleshooting cheat-sheet

Symptom

Cause → Fix

Failed to resolve component 'CMF'

Empty submodule folders (ZIP download or non-recursive clone) → git submodule update --init --recursive

command not found: idf.py

You're in a normal terminal → use the ESP-IDF Terminal from VS Code (F1ESP-IDF: Open ESP-IDF Terminal)

Failed to connect to ESP32-S3

Robot off, wrong port, or monitor still open → check port (Step 7), close monitor, power-cycle (Step 8)

Port never appears

Charge-only cable → swap cable; robot not powered on; Windows: CH340 driver missing (Step 7)

Port appears then vanishes (Linux)

brltty grabs the CH340 → sudo apt remove brltty, replug

Permission denied: '/dev/ttyUSB0' (Linux)

Not in dialout group → sudo usermod -a -G dialout $USER, log out & in

Build fails with weird path errors (Windows)

Spaces in folder path or OneDrive interference → move project to C:\Projects\

Everything broke after "set-target"

Regenerated sdkconfiggit checkout -- sdkconfig, build again

The smallest app partition is nearly full warning

Normal — the firmware nearly fills its slot. It's a warning, not an error. Keep additions small.

git status shows modified sdkconfig/dependencies.lock after building

Normal build housekeeping → ignore (or git checkout -- . to reset)


FAQ

Do I have to use VS Code? No. The project is a standard ESP-IDF project — if you prefer a plain terminal, install ESP-IDF v5.5 by itself (see Espressif's guide) and use idf.py build / idf.py -p PORT flash / idf.py -p PORT monitor directly. Guides 3 and 4 (coding with AI assistants) work great this way too.

Can I brick my Butter Bot? Practically no. The flashing bootloader lives in read-only ROM in the chip — whatever you flash, you can always flash again (the robot enters download mode automatically over USB; there's no button to hold). Worst case, restore the original firmware with the "How do I go back to the original firmware?" steps below and reflash.

How do I go back to the original firmware? Undo your changes (git checkout -- . inside the project folder, then git submodule foreach --recursive git checkout -- .), rebuild, reflash. Your robot is stock again.

Did this answer your question?