Pcbflow
Python based Printed Circuit Board (PCB) layout and design package based on CuFlow.
Install / Use
/learn @michaelgale/PcbflowREADME
| | | | | --- | --- | --- | | <img src=./images/sample_top.png> | <img src=./images/sample_bot.png> | <img src=./images/sample_all.png> |
pcbflow - Python PCB layout and design (based on CuFlow)
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
This repository contains a python based Printed Circuit Board (PCB) layout and design package based on CuFlow by James Bowman.
This implementation is an experimental variation of CuFlow. It attempts to modularize the components of CuFlow and extend/modify its functionality in some key areas:
- allow component placement on top or bottom (automatically chooses top or bottom companion layers of silkscreen, soldermask, copper)
- allow customization of track widths, drill/hole types
- contain design rules in a class rather than the Board class
- improve layout metrics
- robust import of components from Eagle LBR and KiCAD mod files
- enhanced Gerber files with FileFunction assignments
- more export formats including stylized views for SVG, PNG, PDF
- integration with SKiDL for complete scripted EDA workflow
This implementation is alpha and not fully documented.
Requirements
Since the initial release of pcbflow, some changes have been made to adapt with newer versions of python and library dependancies. In particular:
- the initial versions of
pcbflowusedshapelyv.1.6+. Howevershapelyhas changed the way geometries are iterated in v.2.0.1+; thereforepcbflowhas been changed to supportshapleyversions 2.0.1+
pcbflowhas been changed to supportshapleyversions 2.0.1+ ONLY. Check your version withpip listand verifyshapleyis v.2.0.1+
Installation
The pcbflow package can be installed directly from the source code:
$ git clone https://github.com/michaelgale/pcbflow.git
$ cd pcbflow
$ pip install .
Basic Usage
After installation, the package can imported:
$ python
>>> import pcbflow
>>> pcbflow.__version__
An example of the package can be seen below
from pcbflow import *
# create a 40 mm x 30 mm PCB with outline
brd = Board((40, 30))
brd.add_outline()
# fill the top and bottom copper layers and merge nets named "GND"
brd.fill_layer("GTL", "GND")
brd.fill_layer("GBL", "GND")
# save the PCB asset files
brd.save("mypcb")
Board Object
The Board class is a top level object used to perform all the tasks to build a scripted PCB design in python. Once an instance of Board is created, calling methods to add features and configure the PCB can then be peformed as desired.
PCB Layers
pcbflow creates the following layer stack by default:
GML- Mechanical outlineGTD- Top side documentationGTP- Top side solder pasteGTO- Top side silkscreenGTS- Top side solder maskGTL- Top side copperGBL- Bottom side copperGBS- Bottom side solder maskGBO- Bottom side silkscreenGBP- Bottom side solder pasteGBD- Bottom side documentation
Additional internal copper layers can be added as follows:
brd.add_inner_copper_layer(layer_count=1)
This will insert a copper layer named GP2 inbetween GTL and GBL. Subsequent addition of copper layers will be named GP3, GP4, etc. layer_count specifies how many inner copper layers to add.
Design Rules
A basic set of design rules is stored in the Board.drc attribute. It has the following attributes:
# Copper features
self.trace_width = MILS(8)
self.via_drill = 0.5
self.via_annular_ring = MILS(8)
self.via_track_width = MILS(16)
# Clearances
self.clearance = MILS(8)
self.outline_clearance = MILS(20)
self.hole_clearance = MILS(20)
# Soldermask
self.mask_vias = False
self.mask_holes = True
self.hole_mask = MILS(16)
self.soldermask_margin = MILS(3)
# Other
self.bitmap_res = 0.04
self.silk_width = MILS(6)
self.text_silk_width = MILS(6)
Numeric Values
The default internal representation of numerical values of distance, length, etc. is metric millimetres (mm). However, pcbflow has the following convenience functions to specify values in other units:
MILS(x)- thousandths of an inchINCHES(x)- inchesMICRONS(x)- micrometres
Holes
You can add standard non-plated through holes as follows:
brd.add_hole((x, y), diameter)
Note that added holes will automatically add a keepout and solder mask margin if specified by the DRC. DRC.hole_clearance specifies the keepout border clearance, DRC.mask_holes enables/disables a solder mask region over the hole with a border width specified by DRC.hole_mask.
To add a plated through hole:
brd.add_drill((x, y), diameter)
Text
Text annotations can be applied to any layer as follows:
brd.add_text((x, y), "ABC",
scale=1.0,
angle=0.0,
side="top",
layer=None,
keepout_box=False,
soldermask_box=False,
justify="centre")
The side argument can be specified as either top or bottom. This will mirror the text for bottom layers so that it is the correct orientation for fabrication.
keepout_box specifies whether a keepout border region be applied to the text to prevent it from be lost in a poured copper layer for example.
soldermask_box specifies whether a solder mask region be applied so that the text would appear unmasked.
Bitmaps
Arbitrary bitmap logos/annotations can be applied to the PCB as follows:
brd.add_bitmap((x, y), "logo.png",
scale=None,
side="top",
layer=None,
keepout_box=False,
soldermask_box=False)
The bitmap should be a monochrome bitmap image with transparent background. It will be automatically converted into polygons and added to the desired layer. The bitmap size is can be adjusted with the scale parameter. Furthermore, keepout_box and soldermask_box can be applied as desired. Lastly, the side parameter can flip the orientation of the bitmap for bottom side layers if set to bottom
Named Polygons
Arbitary polygon regions can be added to a copper layer with a name corresponding to its net name. For example, this can be used to apply different voltage "patches" under a part requiring several voltages, or to make a split plane of several voltages or GND references.
# add a polygon with a coordinate list
# add_named_poly(coords, layer, name)
brd.add_named_poly([(1,1), (1,2), (5,1)], layer="GTL", "GND")
# convenience method for making a rectangular polygon with two corner points
# add_named_rect(top_left, bottom_right, layer, name)
brd.add_named_rect((1, 10), (20, 3), "GBL", "VCC")
Parts
Parts can be added in four ways:
- Drawing directly with primitives in class derived from
PCBPart(see thefootprintsfolder for examples) - Importing a package from an Eagle library file using
EaglePart - Importing a footprint from a KiCAD footprint library file using
KiCadPart - Instantiating a part from a SKiDL circuit using
SkiPart
# adding a generic part with SOT23(Part)
brd.add_part((10, 20), SOT23, side="top")
# adding a generic R0603(PCBPart) SMD resistor by passing the board "Drawing Context" (DC)
# PCBPart classes instantiate themselves directly from DC--this allows the part
# to derive its location, orientation, etc.
R0603(brd.DC((20, 10)), "4.7k", side="bottom")
# this is also equivalent:
brd.add_part((20, 10), R0603, val="4.7k", side="bottom")
# We can add multiple parts with an iterator:
for x in range(5):
brd.add_part((5 + x*3, 4), C0402, val="0.1u", side="top")
# adding an Eagle part called USB-B-SMT from sparkfun.lbr
# chaining the right(90) method to DC places the part 90 deg rotated
EaglePart(brd.DC((10, 10)).right(90), libraryfile="sparkfun.lbr", partname="USB-B-SMT", side="top")
# this is also equivalent:
brd.add_part((10, 10), EaglePart, libraryfile="sparkfun.lbr", partname="USB-B-SMT", side="top", rot=90)
# adding a KiCAD footprint part from file kc1.kicad_mod
# specifying the side="bottom" automatically maps the footprint copper, mask, paste,
# and silkscreen layers to the bottom (automatically mirroring in the horizontal axis)
KiCadPart(brd.DC((10, 10)), libraryfile="kc1.kicad_mod", side="bottom")
# this is also equivalent:
brd.add_part((10, 10), KiCadPart, libraryfile="kc1.kicad_mod", side="bottom")
# assigning a variable to a placed part allow us to reference it again
# later for tasks such as renaming pads, routing signals from a pad location,
# routing a group of signals as a bus (or "river" in CuFlow), etc.
usb_con = EaglePart(brd.DC((10, 10)), libraryfile="sparkfun.lbr", partname="USB-B-SMT", side="top")
# route a wire from pad 3 to 5 mm right, 10 mm up with a width 0.25 mm
# if width is omitted it will use the default trace_width in Board.DRC
usb_con.pads[3].w("r 90 f 5 l 90 f 10").wire(width=0.25)
# print a PCBPart's details (pad 3 happens to be the USB connector's D- line)
print(usb_con)
# Part: 3 top ( 10.00, 10.00) / 0 deg 6 pads
# 0: 5 (10.58, 16.80) 1: 6 (10.58, 3.20) 2: D+ (17.00, 11.88) 3: D- (22.00, 20.62) 4: GND (17.00, 9.38)
# 5: VUSB (17.00, 8.12)
# alternatively, we can reference the pad by name to do the same thing
usb_con.pad("D-").turtle("r 90 f 5 l 90 f 10").wire(width=0.25)
Saving Asset Files
pcbflow can generate a variety of output ass
Related Skills
claude-opus-4-5-migration
84.2kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
model-usage
340.5kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
diffs
340.5kUse the diffs tool to produce real, shareable diffs (viewer URL, file artifact, or both) instead of manual edit summaries.
TrendRadar
49.9k⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。
