Skip to the content
2 layers100 × 80 mmBalance bot, the printed circuit board in 3D

Two-wheel self-balancing robot motherboard PCB — schematic in SKiDL, placement in pcbnew

Size
100 × 80 mm
Copper layers
2
Thickness
1.6 mm
Parts
43
Nets
39
Pads
166
Tracks, vias
395, 107
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
5 Aug 2026
Updated
5 Aug 2026

Overview

Balance bot is an open-source printed circuit board by MarkDunne, from the MarkDunne/balance-bot repository on GitHub. It is a 2-layer board of 100 × 80 mm with 43 parts on 39 nets, routed with 395 tracks and 107 vias.

Its parts include 12 resistors, 11 connectors, 7 capacitors, 3 diodes and 3 transistors. It belongs with the robots and motor control and computers and single-board computers boards of this library.

README

README.md

balance-bot

A two-wheel self-balancing robot. This repo currently holds the hardware design: a passive motherboard PCB that every module plugs into.

The routed board

100 × 80mm, 2-layer, routed and poured, DRC-clean. Every image here is generated by just render from the board file — nothing is drawn by hand, including the routing.

  • ESP32-S3-DevKitC-1 — controller, socketed
  • TB6612FNG breakout — dual motor driver, socketed
  • GY-521 / MPU6050 — 6-axis IMU, socketed
  • 2S Li-ion — 7.4V nominal, XT30 in, charged off-board
  • 2 × N20 encoder motors — 6-pin JST-PH each, winding and encoder together

The schematic is Python. hardware/balance_bot.py is the single source of truth for the netlist and the pin map — nothing is transcribed by hand between them, so they cannot drift apart.

Getting started

sh
just bootstrap    # clone KiCad symbol libraries, sync the venv
just check        # build the netlist, run the design rules

just check writes build/balance_bot.net and regenerates docs/pinmap.md. KiCad is not needed for any of that — only for laying out the board.

The netlist is committed on purpose. It is deterministic, so git diff on it shows exactly what a change to the schematic did to the connectivity.

Visualising it

sh
just view     # -> build/board.html

Every socket rendered pin by pin, with click-to-trace net highlighting — the view you want when wiring the thing up or checking a module pinout. Generated from the circuit, so it cannot go stale.

sh
just svg      # -> build/schematic.svg   (needs: pnpm add -g netlistsvg)

A schematic-style drawing with proper symbols, refdes and values. Good for spotting a wrong part; not a schematic you would hand to someone, because SKiDL feeds netlistsvg pin numbers rather than pin names and emits no net labels. See hardware/schematic_svg.py for why patching that around makes it worse.

SKiDL's generate_schematic hangs on this circuit — don't bother. For a real board, use KiCad.

Layout

  1. just check
  2. just route — places, routes, pours ground and runs DRC, no GUI involved
  3. Open it in Pcbnew only to look at it

Re-running just check after a schematic change and re-importing updates the board without disturbing what is already placed — refdes are pinned in the source rather than auto-numbered.

Read next

  • docs/workflow.md — how this board was designed, the tooling gotchas, what the checks catch and what they miss, and how to start the next one
  • docs/design.md — architecture, power budget, the decisions worth knowing about, and what to verify before ordering boards
  • docs/mechanical.md — board envelope and mounting, for designing the chassis
  • docs/fab.md — PCBWay order parameters and what gets uploaded
  • docs/pinmap.md — generated pin assignments
  • docs/bom.md — shopping list

Board

sh
just board      # generate hardware/balance_bot.kicad_pcb from the netlist
just netclasses # trace widths, derived from the currents in docs/design.md
just route      # board -> DSN -> Freerouting -> SES -> board -> pour -> DRC
just pour       # ground plane on both layers, stitched (part of `just route`)
just plot       # look at the placement
just drc        # headless design rule check
just fab        # DRC, then Gerbers + drill -> build/balance-bot-fab.zip

just board places every footprint, draws the outline and mounting holes, and assigns all 38 nets. just route then calls it, autoroutes, pours ground and runs DRC — so the board is regenerated from source each time rather than edited in place, and re-running gives the same board.

That holds only while every track came out of the autorouter. The moment you hand-route anything in Pcbnew, just board and just route both destroy it, and from that point the .kicad_pcb is the artifact — schematic changes go in through Pcbnew's netlist re-import instead.

Placement is checked in the script rather than by eye: every courtyard is tested against every other and against the mounting-hole keepouts, and the build fails on a clash. That includes the modules that plug in on top: a socket's courtyard is its pin row, while the module is a PCB many times the size, so the check uses the module outline instead. Flat SMD may sit underneath; through-hole parts may not.

just fab runs DRC first and refuses to produce an upload package if it fails — so an unrouted or violating board cannot reach PCBWay.

Status

Schematic complete and checked. Board placed, clear, routed and poured: all 99 connections routed, ground on both layers stitched into one plane, and DRC reports 0 violations and 0 unconnected items. just fab produces an upload package. No firmware yet.

Routing is generated, not drawn — just route runs the whole chain and is reproducible, so the board can be regenerated from source rather than preserved. That is the opposite of the usual advice and the reason the warning about never re-running just board is now narrower than it was: it holds only once something is hand-routed.

TopBottom
TopBottom

The bottom is the clearer look at the routing: gold pads, traces, and the regular grid of stitching vias tying the two ground planes together. Most of what looks like bare board on both sides is ground pour.

The placement was solved against the checks rather than drawn: the floorplan is a design decision — USB left, motors and battery bottom, switch right, IMU centred laterally — and each passive then sits as close to what it serves as the module outlines allow. The module outlines are still assumed, not measured, and the whole layout rests on them. See the checklist in docs/design.md before ordering.

100 × 80mm, 2-layer, hand-soldered; motors mount to the chassis rather than the board. See docs/mechanical.md to design the chassis in parallel.

Parts

43
QtyValueFootprintReferences
12R_0805_2012MetricR_0805_2012MetricR1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12
4C_0805_2012MetricC_0805_2012MetricC2, C5, C6, C7
4MountingHole_3.2mm_M3MountingHole_3.2mm_M3H1, H2, H3, H4
3CP_Radial_D8.0mm_P3.50mmCP_Radial_D8.0mm_P3.50mmC1, C3, C4
3PinHeader_1x08_P2.54mm_VerticalPinHeader_1x08_P2.54mm_VerticalJ5, J6, J7
3SOT-23SOT-23Q1, Q2, Q3
2JST_PH_B6B-PH-K_1x06_P2.00mm_VerticalJST_PH_B6B-PH-K_1x06_P2.00mm_VerticalJ8, J9
2LED_0805_2012MetricLED_0805_2012MetricD2, D3
2PinHeader_1x04_P2.54mm_VerticalPinHeader_1x04_P2.54mm_VerticalJ2, J10
2PinHeader_1x22_P2.54mm_VerticalPinHeader_1x22_P2.54mm_VerticalJ3, J4
1AMASS_XT30PW-M_1x02_P2.50mm_HorizontalAMASS_XT30PW-M_1x02_P2.50mm_HorizontalJ1
1Buzzer_12x9.5RM7.6Buzzer_12x9.5RM7.6BZ1
1D_SMAD_SMAD1
1PinHeader_1x06_P2.54mm_VerticalPinHeader_1x06_P2.54mm_VerticalJ11
1SW_PUSH_6mm_H5mmSW_PUSH_6mm_H5mmSW2
1SW_Slide_SPDT_Angled_CK_OS102011MA1QSW_Slide_SPDT_Angled_CK_OS102011MA1QSW1

Similar boards

  • 2 layers52.2 × 52.2 mmBase, the printed circuit board in 3D

    Base

    google/mozc-devices

    Circuit diagrams and firmware source code for Gboard DIY keyboards

    43 parts3kApache-2.0
  • 2 layers33 × 34 mmESP32-bat monitor latch, the printed circuit board in 3D

    ESP32-bat monitor latch

    pcbreflux/espressif

    all espressif stuff will committed here

    43 parts608GPL-3.0
  • 2 layers42.9 × 19 mmPoly kb 2.25U, the printed circuit board in 3D

    Poly kb 2.25U

    thpoll83/PolyKybd

    PolyKybd

    43 parts411CERN-OHL-W-2.0
  • 2 layers99.1 × 99.7 mmRC6502 Prototyping, the printed circuit board in 3D

    RC6502 Prototyping

    tebl/RC6502-Apple-1-Replica

    An expandable SBC-version of the Apple 1 computer, easy to get started with and lot of cool stuff that can be added to it!

    43 parts193GPL-3.0
  • 2 layers26.6 × 38.7 mmMdb slave esp32s3-mini, the printed circuit board in 3D

    Mdb slave esp32s3-mini

    nodestark/mdb-esp32-cashless

    ESP32-based MDB cashless device for vending machines, supporting EVA DTS DEX/DDCMP telemetry and payments over the MDB protocol via Bluetooth and MQTT

    43 parts190MIT
  • 2 layers97.3 × 71 mmZynScreen v1, the printed circuit board in 3D

    ZynScreen v1

    zynthian/zynthian-hw

    Zynthian hardware stuff: PCBs, schemes, parts specifications, pin assignment, ...

    43 parts156

Questions

How big is the Balance bot PCB?

It measures 100 × 80 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Balance bot use?

43 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Balance bot KiCad files?

From the MarkDunne/balance-bot repository on GitHub, at the commit this page was made from: the board is hardware/balance_bot.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.

Can I use the Balance bot design in my own project?

Its repository states no licence, so its author keeps all rights: ask MarkDunne before reusing the design.