Skip to content

Commit 48fdfa4

Browse files
zeulewanclaude
andcommitted
PCB routed: All nets connected, DRC clean
- Fixed export_dsn.py to use actual pad sizes (was using 600x600um for all) - Improved component placement for better routing clearance - FreeRouting now routes cleanly with correct pad keepouts - 188 track segments, 17 vias, 0 unconnected items - Only cosmetic violations remain (silkscreen overlap) Key learnings added to kicad-agent.md skill file: - DSN export must include proper pad sizes per footprint - Correct pad size is critical for FreeRouting clearance - Java 21 required for FreeRouting 2.0.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2c21ce8 commit 48fdfa4

File tree

11 files changed

+3586
-250
lines changed

11 files changed

+3586
-250
lines changed

.claude/skills/kicad-agent.md

Lines changed: 135 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ Use this skill when user provides PCB project requirements.
99
## Workflow Overview
1010

1111
```
12-
Requirements → Component Selection → Library Import → Schematic → Layout → Routing → DRC → Export → Order
12+
Requirements → Component Selection → Library Import → Schematic (Netlist) → PCB Creation →
13+
Visual Check → Manual Fix → Auto-Route → Visual Check → Manual Fix → DRC → Export → Order
1314
```
1415

16+
**Key Principle:** Always render and visually inspect after algorithmic steps, then fix manually as needed.
17+
1518
## Phase 1: Requirements Gathering
1619

1720
When user provides project requirements, capture in `kicad/specs.md`:
@@ -53,7 +56,7 @@ For each required component:
5356
- Extended parts: $3 setup fee per unique part
5457
- If out of stock: find alternative
5558

56-
**Common Issue:** Many specialty chips (e.g., MH2024K, WT2003S, JQ6500) are NOT on LCSC.
59+
**Common Issue:** Many specialty chips (e.g., MH2024K, WT2003S, JQ6500, ISD1820) are NOT on LCSC.
5760
Always verify availability before committing to a design.
5861

5962
## Phase 2.5: Library Import with easyeda2kicad
@@ -75,11 +78,17 @@ easyeda2kicad --lcsc_id CXXXXXX --full --output libs/project.kicad_sym
7578
- `libs/project.pretty/` - Footprint library folder
7679
- `libs/project.3dshapes/` - 3D models (.wrl and .step)
7780

81+
**IMPORTANT: Upgrade footprints to KiCad 8/9 format:**
82+
```bash
83+
kicad-cli fp upgrade --force libs/project.pretty
84+
```
85+
7886
**Important notes:**
7987
- Each `--full` call adds to the same library file
8088
- Some parts may fail to import (no EasyEDA data)
8189
- For generic parts (passives, connectors), use KiCad built-in libraries
8290
- Symbols include LCSC Part property for BOM generation
91+
- easyeda2kicad outputs older format - MUST upgrade with kicad-cli
8392

8493
**Verify imports:**
8594
```bash
@@ -88,83 +97,115 @@ ls libs/project.pretty/ # List footprints
8897
ls libs/project.3dshapes/ # List 3D models
8998
```
9099

91-
## Phase 3: Schematic Design
100+
## Phase 3: Schematic Design with SKiDL
92101

93-
Using SKiDL (code-first approach):
102+
Using SKiDL (code-first approach) to generate netlist:
94103

95104
```python
96105
from skidl import *
106+
set_default_tool(KICAD8)
107+
lib_search_paths[KICAD8].append('libs')
97108

98-
# Example structure
99-
mcu = Part('MCU_Microchip_ATmega', 'ATmega328P-AU',
100-
footprint='Package_QFP:TQFP-32_7x7mm_P0.8mm')
109+
# Import custom parts from project library
110+
mcu = Part('project', 'PartName', footprint='project:FootprintName', ref='U1')
101111

102112
# Connect power
103-
mcu['VCC'] += Net('VCC')
113+
mcu['VCC'] += Net('+3V')
104114
mcu['GND'] += Net('GND')
105115

106-
# Generate netlist
116+
# Generate netlist (SKiDL doesn't support KiCad 8 schematic generation)
107117
generate_netlist(file_='project.net')
108118
```
109119

110-
**Verification:**
111-
1. Run ERC: `kicad-cli sch erc --output erc.json --format json project.kicad_sch`
112-
2. Review and fix any errors
120+
**IMPORTANT:** SKiDL does NOT generate KiCad 8 schematics - only netlists.
121+
The netlist contains all connectivity info needed for PCB generation.
113122

114-
## Phase 4: PCB Layout
123+
## Phase 4: PCB Creation from Netlist
115124

116-
1. Set board outline based on user dimensions
117-
2. Place components:
118-
- MCU/main IC in center
125+
Use custom Python script to create PCB from netlist:
126+
127+
1. Parse netlist for components, footprints, and nets
128+
2. Load footprints from library files
129+
3. Place components algorithmically:
130+
- Main ICs in center
119131
- Connectors on edges
120132
- Decoupling caps near IC power pins
121133
- Keep sensitive analog away from digital
122-
3. Document placement decisions in `kicad/design-log.md`
134+
4. Assign nets to pads
135+
5. Write KiCad PCB file
136+
137+
**CRITICAL: Visual verification after placement:**
138+
```bash
139+
kicad-cli pcb render --output renders/top.png --side top --width 2048 --height 1536 --quality high project.kicad_pcb
140+
kicad-cli pcb render --output renders/perspective.png --perspective --rotate "45,0,45" --zoom 1.5 --quality high project.kicad_pcb
141+
```
142+
143+
Review renders:
144+
- Check component placement makes sense
145+
- Verify all components are present
146+
- Check for overlapping footprints
147+
- Verify 3D models are loading
148+
149+
If issues found, manually adjust positions in `create_pcb.py` and regenerate.
123150

124151
## Phase 5: Routing
125152

153+
**Note:** kicad-cli does NOT have DSN export. Use custom `export_dsn.py` script.
154+
126155
1. Export DSN for auto-routing:
127156
```bash
128-
kicad-cli pcb export dsn --output board.dsn project.kicad_pcb
157+
python export_dsn.py # Creates project.dsn
129158
```
130159

131-
2. Run FreeRouting (if installed):
160+
2. Run FreeRouting:
132161
```bash
133-
java -jar freerouting.jar -de board.dsn -do board.ses
162+
# Download FreeRouting if not present
163+
curl -L -o freerouting.jar "https://github.com/freerouting/freerouting/releases/download/v2.0.1/freerouting-2.0.1.jar"
164+
165+
# Auto-route (headless mode)
166+
java -jar freerouting.jar -de project.dsn -do project.ses
134167
```
135168

136-
3. Import SES back into KiCad
169+
3. Import SES back into KiCad (requires custom script or manual import)
137170

138-
4. Manual cleanup if needed
171+
4. **CRITICAL: Visual verification after routing:**
172+
```bash
173+
kicad-cli pcb render --output renders/top_routed.png --side top --width 2048 --height 1536 project.kicad_pcb
174+
```
175+
176+
Review renders:
177+
- Check all nets are connected
178+
- Look for routing issues
179+
- Verify power traces are wide enough
139180

140181
## Phase 6: Design Rule Check
141182

142183
```bash
143-
kicad-cli pcb drc --output drc.json --format json --exit-code-violations project.kicad_pcb
184+
kicad-cli pcb drc --output drc.json --format json project.kicad_pcb
185+
```
186+
187+
Parse results:
188+
```bash
189+
cat drc.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'Violations: {len(d.get(\"violations\",[]))}'); print(f'Unconnected: {len(d.get(\"unconnected_items\",[]))}')"
144190
```
145191

146-
**Fix common issues:**
147-
- Clearance violations: adjust trace spacing
148-
- Unconnected nets: complete routing
149-
- Silk overlap: move silkscreen text
192+
**Common DRC issues:**
193+
- `lib_footprint_issues`: Footprint library paths - usually cosmetic, ignore if footprints are embedded
194+
- `silk_over_copper`: Silkscreen clipped - minor cosmetic issue
195+
- `silk_overlap`: Text overlap - move silkscreen elements
196+
- Unconnected items: Need to complete routing
150197

151-
## Phase 7: Visual Verification
198+
## Phase 7: Final Visual Verification
152199

153-
Generate renders for inspection:
200+
Generate comprehensive renders:
154201

155202
```bash
156-
# Top view
157-
kicad-cli pcb render --output kicad/renders/top.png --side top --width 2048 --height 2048 project.kicad_pcb
158-
159-
# Bottom view
160-
kicad-cli pcb render --output kicad/renders/bottom.png --side bottom --width 2048 --height 2048 project.kicad_pcb
203+
# All views
204+
kicad-cli pcb render --output renders/top.png --side top --width 2048 --height 1536 --quality high project.kicad_pcb
205+
kicad-cli pcb render --output renders/bottom.png --side bottom --width 2048 --height 1536 --quality high project.kicad_pcb
206+
kicad-cli pcb render --output renders/perspective.png --perspective --rotate "45,0,45" --zoom 1.5 --quality high project.kicad_pcb
161207
```
162208

163-
**Check:**
164-
- Component placement looks correct
165-
- Silkscreen readable
166-
- No obvious routing issues
167-
168209
## Phase 8: Fabrication Export
169210

170211
Using KiBot (recommended):
@@ -173,11 +214,17 @@ Using KiBot (recommended):
173214
kibot -c kibot.yaml -b project.kicad_pcb
174215
```
175216

176-
Output files for JLCPCB:
177-
- Gerber files (all layers)
178-
- Drill files
179-
- BOM (CSV format)
180-
- CPL/Pick-and-Place (CSV format)
217+
Or use kicad-cli directly:
218+
```bash
219+
# Gerbers
220+
kicad-cli pcb export gerbers --output output/gerbers/ project.kicad_pcb
221+
222+
# Drill files
223+
kicad-cli pcb export drill --output output/ project.kicad_pcb
224+
225+
# Position file (for assembly)
226+
kicad-cli pcb export pos --output output/project-pos.csv project.kicad_pcb
227+
```
181228

182229
## Phase 9: Ordering
183230

@@ -192,46 +239,64 @@ Output files for JLCPCB:
192239
- Shipping method
193240
- Total cost confirmation
194241

195-
## File Locations
242+
## File Structure
196243

197244
```
198-
kicad/
199-
├── specs.md # Project requirements
200-
├── component-selection.md # Selected parts
201-
├── design-log.md # Design decisions
202-
├── project.kicad_pro # KiCad project
203-
├── project.kicad_sch # Schematic
204-
├── project.kicad_pcb # PCB layout
205-
├── kibot.yaml # KiBot config
206-
├── output/ # Generated files
207-
│ ├── gerbers/ # Gerber files
208-
│ ├── bom.csv # Bill of materials
209-
│ └── cpl.csv # Pick and place
210-
└── renders/ # Visual inspection
211-
├── top.png
212-
└── bottom.png
245+
project/
246+
├── venv/ # Python virtual environment
247+
├── freerouting.jar # Auto-routing tool
248+
├── .claude/skills/
249+
│ └── kicad-agent.md # This skill file
250+
├── kicad/
251+
│ ├── specs.md # Project requirements
252+
│ ├── component-selection.md # Selected parts
253+
│ ├── schematic-design.md # Schematic documentation
254+
│ ├── design-log.md # Design decisions
255+
│ ├── libs/
256+
│ │ ├── project.kicad_sym # Symbol library
257+
│ │ ├── project.pretty/ # Footprint library
258+
│ │ └── project.3dshapes/ # 3D models
259+
│ ├── create_pcb.py # PCB generation script
260+
│ ├── export_dsn.py # DSN export script
261+
│ ├── project.net # SKiDL netlist
262+
│ ├── project.dsn # Specctra DSN for routing
263+
│ ├── project.ses # Routed session file
264+
│ ├── project.kicad_pro # KiCad project
265+
│ ├── project.kicad_sch # Schematic (may be minimal)
266+
│ ├── project.kicad_pcb # PCB layout
267+
│ ├── drc-report.json # DRC results
268+
│ ├── renders/ # Visual inspection images
269+
│ └── output/ # Fabrication files
213270
```
214271

215272
## Error Recovery
216273

217274
**Component out of stock:**
218275
→ Search for pin-compatible alternative
219276
→ Update component-selection.md
220-
→ Re-run schematic
277+
→ Re-run schematic generation
221278

222279
**DRC failures:**
223-
→ Read error details from JSON
224-
→ Fix in PCB editor
280+
→ Parse JSON for specific issues
281+
→ Fix in PCB generation script
282+
→ Regenerate PCB
225283
→ Re-run DRC until clean
226284

227285
**Routing incomplete:**
286+
→ Check DSN export captured all nets
228287
→ Try different FreeRouting settings
229-
→ Or route manually via MCP server
288+
→ Manual routing may be needed for complex sections
289+
290+
**3D models not showing:**
291+
→ Check model paths are relative to project
292+
→ Use ${KIPRJMOD}/ prefix for project-relative paths
293+
→ Verify .wrl/.step files exist
230294

231-
## Context Management
295+
## Best Practices
232296

233-
This is a long project. To maintain context:
234-
- Keep `specs.md` updated with current requirements
235-
- Log decisions in `design-log.md`
236-
- Reference `workflow-reference.md` for commands
237-
- Check `tool-setup.md` for tool versions
297+
1. **Always render after algorithmic changes** - Don't blindly trust generated files
298+
2. **Commit frequently** - Save working states before major changes
299+
3. **Document decisions** - Update design-log.md with rationale
300+
4. **Verify LCSC availability early** - Avoid redesign later
301+
5. **Keep skill file updated** - Document new learnings and workarounds
302+
6. **Use screenshots for debugging** - Visual inspection catches many issues

kicad/create_pcb.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,24 +57,48 @@ def parse_netlist(netlist_file):
5757
return components, nets
5858

5959
def place_components(components):
60-
"""Calculate placement positions for components."""
60+
"""Calculate placement positions for components.
61+
62+
Improved placement with more spacing to allow cleaner routing.
63+
Key principles:
64+
- U1 (MCU) in center-left area
65+
- U2 (SPI flash) to the right with clear path for SPI signals
66+
- Bypass caps close to their associated IC power pins
67+
- Connectors on edges
68+
- Button accessible but not in routing path
69+
"""
70+
# Center point for main layout
71+
cx = BOARD_ORIGIN_X + 38 # Shift left to give room for SPI flash on right
72+
cy = BOARD_ORIGIN_Y + BOARD_HEIGHT/2
73+
6174
positions = {
62-
'U1': (BOARD_ORIGIN_X + BOARD_WIDTH/2, BOARD_ORIGIN_Y + BOARD_HEIGHT/2, 0),
63-
'U2': (BOARD_ORIGIN_X + BOARD_WIDTH/2 + 15, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 - 10, 0),
64-
'BT1': (BOARD_ORIGIN_X + BOARD_WIDTH - 18, BOARD_ORIGIN_Y + BOARD_HEIGHT/2, 0),
65-
'C1': (BOARD_ORIGIN_X + BOARD_WIDTH/2 - 10, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 - 10, 0),
66-
'C2': (BOARD_ORIGIN_X + BOARD_WIDTH/2 - 10, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 + 10, 0),
67-
'C3': (BOARD_ORIGIN_X + BOARD_WIDTH/2 + 10, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 - 10, 0),
68-
'C4': (BOARD_ORIGIN_X + BOARD_WIDTH/2 - 15, BOARD_ORIGIN_Y + BOARD_HEIGHT/2, 0),
69-
'C5': (BOARD_ORIGIN_X + BOARD_WIDTH/2 + 10, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 + 10, 0),
70-
'C6': (BOARD_ORIGIN_X + BOARD_WIDTH/2 + 22, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 - 5, 0),
71-
'R1': (BOARD_ORIGIN_X + 12, BOARD_ORIGIN_Y + 20, 0),
72-
'R2': (BOARD_ORIGIN_X + 22, BOARD_ORIGIN_Y + 15, 90),
73-
'R3': (BOARD_ORIGIN_X + BOARD_WIDTH/2 - 18, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 - 15, 0),
74-
'R4': (BOARD_ORIGIN_X + BOARD_WIDTH/2 - 18, BOARD_ORIGIN_Y + BOARD_HEIGHT/2 + 15, 0),
75-
'J1': (BOARD_ORIGIN_X + 15, BOARD_ORIGIN_Y + BOARD_HEIGHT - 8, 0),
76-
'J2': (BOARD_ORIGIN_X + 35, BOARD_ORIGIN_Y + BOARD_HEIGHT - 8, 0),
77-
'SW1': (BOARD_ORIGIN_X + 55, BOARD_ORIGIN_Y + BOARD_HEIGHT - 12, 0),
75+
# Main ICs
76+
'U1': (cx, cy, 0), # MCU in center-left (LQFP-48 is 7x7mm)
77+
'U2': (cx + 28, cy - 8, 0), # SPI flash to the right, clear routing path (SOIC-8)
78+
79+
# Battery holder on far right
80+
'BT1': (BOARD_ORIGIN_X + BOARD_WIDTH - 18, cy, 0), # CR2032 holder
81+
82+
# Bypass capacitors - spread around U1
83+
'C1': (cx - 12, cy - 6, 0), # 0603 near U1 pin 11 (+3V)
84+
'C2': (cx - 12, cy + 6, 0), # 0805 near U1
85+
'C3': (cx + 12, cy - 6, 0), # 0603 VREG bypass
86+
'C4': (cx - 6, cy - 12, 0), # 0603 near U1 top
87+
'C5': (cx + 12, cy + 6, 0), # 0805
88+
'C6': (cx + 28, cy + 2, 0), # 0603 near U2/battery
89+
90+
# Resistors - spread out more
91+
'R1': (BOARD_ORIGIN_X + 12, cy - 8, 0), # LDR (through-hole)
92+
'R2': (BOARD_ORIGIN_X + 12, cy - 18, 0), # LDR pullup - NOT rotated, more space
93+
'R3': (cx - 6, cy - 18, 0), # RESET pullup - above U1
94+
'R4': (cx - 6, cy + 18, 0), # CSB pullup - below U1
95+
96+
# Connectors on bottom edge - spread apart to avoid routing conflicts
97+
'J1': (BOARD_ORIGIN_X + 15, BOARD_ORIGIN_Y + BOARD_HEIGHT - 8, 0), # Speaker
98+
'J2': (BOARD_ORIGIN_X + 50, BOARD_ORIGIN_Y + BOARD_HEIGHT - 8, 0), # Tab trigger (moved right)
99+
100+
# Button on right side, away from main routing
101+
'SW1': (cx + 28, cy + 18, 0), # Button near bottom right
78102
}
79103

80104
placements = []

0 commit comments

Comments
 (0)