dobrovolskiy.com
RU
← Notes2026-08-30 · by Dmitriy Dobrovolskiy

Generating a complete KiCad schematic and PCB from Python: a 4G mains lighting controller in one day

How a 1.5k-line Python generator (own s-expression parser, pcbnew placement, freerouting, kicad-cli) produced a KiCad 10 project for a 220 V lighting controller with ESP32-S3, an A7682E LTE modem, 4 relays and 8 mains-sense inputs — ERC-clean, reproducible, built in a day.

Instead of drawing a board by hand I wrote a Python generator that emits the whole KiCad 10 project: it parses .kicad_sym libraries, embeds symbols, places instances on a 2.54 mm grid, wires every pin with global labels, then drives pcbnew for placement and zones, freerouting for routing and kicad-cli for fabrication outputs. The test case was a 175 × 115 mm 220 VAC lighting controller — ESP32-S3, SIMCom A7682E LTE, four 16 A relays, eight opto-isolated mains inputs — designed in a single day.

The idea

Most of my boards are variations on one theme: a microcontroller, a cellular modem, relays, mains-sense inputs, a power tree. Drawing the fifth variation by hand is not engineering, it is typing. So on 8 July 2026 I tried the other way round: describe the board in Python and let the script produce the KiCad project. tools/kigen.py and its companions are about 1 500 lines.

What the generator does

  1. Parses KiCad s-expressions. A small from-scratch parser reads .kicad_sym libraries (including easyeda2kicad conversions of LCSC parts), so the generator can embed the exact symbols the board needs.
  2. Places symbol instances on a 2.54 mm grid and computes rotated pin endpoints, so wires and labels land on pins for any rotation.
  3. Wires every pin with global labels. No drawn wires; each net is a label at each pin. It is not pretty, but it is unambiguous, ERC-clean and trivially diffable.
  4. Generates the board through the pcbnew Python API: footprint placement by functional group, board outline, copper zones, and net classes.
  5. Routes and exports with freerouting (via a Specctra DSN) and kicad-cli, then a post-route step re-applies zones and rules.

The chain is one command: gen_sch → ERC → netlist → gen_pcb → DSN → freerouting → post_route → export_all. Change a part in the generator, rerun, get a new project.

The board it produced

A 220 VAC lighting controller on a two-layer 175 × 115 mm board:

Mains and logic areas are physically separated with dedicated net classes: MAINS with 2.5 mm / 1.5 mm clearance, MAINS_SENSE, POWER and RF. Every part is stockable at LCSC/JLCPCB on purpose.

Honest status

The generated schematic passes ERC; the board is placed with zones and rules. It is not routed yet — freerouting is in the chain but the run has not been finished — so this is a generator demo and a design study, not a fabricated board. The fabricated boards of the same family are the FOURLEDS controllers, drawn by hand in KiCad.

Why bother

Because the second board takes an afternoon instead of a week, because every design decision is in version control as code, and because a reviewer can read gen_sch.py faster than they can click through forty sheets. The parser and the placement helpers are reusable; the board description is the only thing that changes.

What I would do differently

Generate real wires for the short local nets (decoupling, LED resistors) and keep global labels only for buses and power — the all-labels schematic is correct but hard to read for anyone else. And run freerouting to completion before calling it a day.

FAQ

Which KiCad version and API does the generator use?

KiCad 10: the schematic is written as s-expressions by the generator itself, the board is built through the pcbnew Python API, and exports use kicad-cli. Routing is done by freerouting through a Specctra DSN file.

Is the board manufacturable?

Design-wise yes — mains clearances, fused and MOV-protected input, LCSC/JLCPCB-stockable parts — but it is currently unrouted, so treat it as a design study. The fabricated boards from the same family are the FOURLEDS controllers.

Can you generate or review a board for me?

Yes. Schematic review, KiCad automation or a controller design like this one are typical hourly sessions on a shared screen.

Want something like this?

I build it live on a Zoom call, you watch the screen, the timer stops when you say stop. First 15 minutes are free.

$50 / hourBook an hour

More projects

Script-generated LTE controllerA complete 4G mains lighting controller PCB, generated end-to-end from Python instead of drawn by hand.