Skip to content

RolandWa/openfixture

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenFixture - Modern PCB Test Fixture Generator

License KiCAD Python

Automated laser-cuttable PCB test fixture generation for KiCAD 8.0 and 9.0+

OpenFixture is a comprehensive PCB test fixture generator that integrates directly with KiCAD to automatically create laser-cuttable fixtures for your boards. Fully modernized with KiCAD 9.0+ API compatibility, Python 3 support, and enhanced error handling.


πŸš€ Key Features

  • βœ… Full KiCAD 9.0+ Compatibility - Tested and working with KiCAD 9.0 API
  • βœ… Backward Compatible with KiCAD 8.0 - Automatic API version detection
  • βœ… Python 3 Modern Codebase - Type hints, modern syntax, PEP 8 compliant
  • βœ… TOML Configuration - Project-specific configuration files
  • βœ… Enhanced Plugin UI - Multi-tab dialog with material presets
  • βœ… Comprehensive Error Handling - Detailed logging and user-friendly error dialogs
  • βœ… Automatic OpenSCAD Integration - Seamless 3D model and DXF generation
  • βœ… Modular Architecture - Clean, maintainable, well-documented code

πŸ“¦ Quick Start

Installation

Option 1: KiCAD Plugin Manager (Recommended)

  1. Open KiCAD PCB Editor
  2. Go to: Tools β†’ Plugin and Content Manager
  3. Search for: OpenFixture
  4. Click: Install
  5. Restart KiCAD
  6. Access: Tools β†’ External Plugins β†’ OpenFixture Generator

Option 2: Manual Installation

# 1. Clone or download this repository
git clone https://github.com/tinylabs/openfixture.git
cd openfixture

# 2. Install Python dependencies (optional, for TOML support)
pip install tomli  # Only needed for Python < 3.11

# 3. Install KiCAD plugin using sync script (recommended)
# First, set up your personal configuration:
cp sync_to_kicad_config.ps1.template sync_to_kicad_config.ps1
# Edit sync_to_kicad_config.ps1 with your KiCAD plugins path
notepad sync_to_kicad_config.ps1  # Windows
# OR nano sync_to_kicad_config.ps1  # Linux/macOS

# Then run the sync script:
.\sync_to_kicad.ps1  # Windows PowerShell

# Alternative: Copy manually to KiCAD plugins directory:
# Windows: %APPDATA%\kicad\<version>\3rdparty\plugins\
# Linux: ~/.local/share/kicad/<version>/3rdparty/plugins/
# macOS: ~/Library/Application Support/kicad/<version>/3rdparty/plugins/

cp openfixture.py <plugins_directory>/
cp GenFixture.py <plugins_directory>/

πŸ”’ Security Note

Personal configuration files (like sync_to_kicad_config.ps1) are excluded from version control to protect your privacy. Always use the .template files as a starting point and never commit files containing personal paths. See SECURITY.md for details.

Basic Usage

Command Line:

python3 GenFixture.py \
    --board your_board.kicad_pcb \
    --mat_th 3.0 \
    --out fixture-output

With Configuration File:

# 1. Create fixture_config.toml in your project directory
# 2. Run with config:
python3 GenFixture.py \
    --board your_board.kicad_pcb \
    --config fixture_config.toml \
    --out fixture-output

KiCAD Plugin:

1. Open your PCB in KiCAD PCB Editor
2. Tools β†’ External Plugins β†’ OpenFixture Generator
3. Configure parameters in dialog
4. Click "Generate Fixture"
5. Output directory opens automatically

πŸ“‹ Requirements

Software

  • KiCAD 8.0 or 9.0+
  • Python 3.8 or later
  • OpenSCAD 2015.03 or later
  • Laser cutter or laser cutting service

Python Packages

  • pcbnew (included with KiCAD)
  • tomli (optional, for Python < 3.11)

Hardware

  • M3 screws (14-20mm length)
  • M3 hex nuts
  • M3 washers (optional)
  • Pogo pins and receptacles - See POGO_PINS.md for complete specifications
  • Laser-cut material (acrylic or plywood, 2-5mm thick)

πŸ”Œ Pogo Pin (Test Probe) Hardware

Spring-loaded test probes (pogo pins) are the critical contact elements that make electrical connection to your PCB test points. OpenFixture supports standard pogo pin series from multiple manufacturers.

Quick Selection

Use Case Recommended Cost Cycle Life
Prototypes & Low Volume P75-E2 (24mm crown tip) $0.30/point 10k-50k cycles
Production & High Volume Fixtest 100 series $3.50/point 100k+ cycles

Pogo Pin Series

P75 Series (Budget-Friendly)

  • Price: $0.16-$0.22 per pin + ~$0.10 receptacle
  • Length options: 16.5-33.3mm (7 models: A2, B1, D2, D3, E2, F1, G2)
  • Cycle life: 10,000-50,000 cycles
  • Best for: Prototypes, low-volume testing, hobbyist projects

Fixtest Series 100 (Professional Grade)

  • Price: ~$3.50 per test point (receptacle + probe)
  • Length: 29.6mm (S 100.00-L receptacle)
  • Cycle life: 100,000+ cycles
  • Best for: Production testing, automated equipment, high-volume

Configuration

Set in fixture_config.toml:

[hardware]
pogo_uncompressed_length_mm = 24.0  # For P75-E2 (recommended)
# pogo_uncompressed_length_mm = 16.5  # For P75-A2/B1
# pogo_uncompressed_length_mm = 29.6  # For Fixtest 100

πŸ“˜ Complete Guide

See POGO_PINS.md for comprehensive documentation:

  • Detailed specifications for all models
  • Tip style selection guide (sharp, round, flat, crown)
  • Installation and assembly instructions
  • Maintenance and replacement schedules
  • Cost analysis and ROI calculations
  • Supplier information and alternatives
  • Troubleshooting and FAQs

Test Point Extraction

OpenFixture automatically identifies test points on your PCB using intelligent pad detection. The software scans your KiCAD PCB file and selects pads based on specific criteria designed for reliable electrical testing.

How Test Points Are Selected

The test point selection algorithm evaluates each pad on the PCB using the following criteria (in order of precedence):

1. Force Layer (Highest Priority)

  • Any pad on the force layer (default: Eco2.User) is always included as a test point
  • This overrides all other rules
  • Use this to manually designate specific pads as test points
  • Example: Draw on Eco2.User layer in KiCAD to force-include a pad

2. Ignore Layer

  • Any pad on the ignore layer (default: Eco1.User) is always excluded
  • Use this to explicitly prevent specific pads from becoming test points
  • Example: Draw on Eco1.User layer to exclude a dense BGA area

3. Solder Paste Mask Check

  • Pads with solder paste mask are excluded (they're designed for reflow soldering, not testing)
  • Only pads with exposed copper (no paste mask) are considered
  • Standard test points typically have paste mask removed in KiCAD footprint

4. Pad Type Filtering

  • SMD Pads (PAD_ATTRIB_SMD):

    • Surface mount pads (designed test points, IC pins, etc.)
    • Included if include_smd_pads = true in config
    • Same-side testing: Pogo pins contact pad directly from the test side
  • PTH Pads (PAD_ATTRIB_PTH) - Opposite Side Rule:

    • Through-hole pads (connectors, component leads, vias)
    • Included if include_pth_pads = true in config
    • Critical: Only PTH pads from components on the opposite side are used
    • Rationale: Component body blocks access from the same side
    • Example:
      • Testing from bottom (B.Cu) β†’ Uses PTH pads from top-side components (F.Cu)
      • Testing from top (F.Cu) β†’ Uses PTH pads from bottom-side components (B.Cu)
    • This allows testing through-hole connector pins from the back of the board

5. Layer Selection

  • Only pads on the selected layer are included (F.Cu for top, B.Cu for bottom)
  • Single-sided testing: Choose either top OR bottom
  • Each test point must be on the active test layer

Test Point Selection Matrix

Condition SMD Pads PTH Pads (Same Side*) PTH Pads (Opposite Side*)
On Force Layer (Eco2.User) βœ… Always βœ… Always βœ… Always
On Ignore Layer (Eco1.User) ❌ Never ❌ Never ❌ Never
Has Paste Mask ❌ Excluded ❌ Excluded ❌ Excluded
No Paste Mask + include_smd=true βœ… Included N/A N/A
No Paste Mask + include_pth=true N/A ❌ Excluded βœ… Included
include_smd=false or include_pth=false ❌ Excluded ❌ Excluded ❌ Excluded

* Same Side = Component on same layer as test points (e.g., test F.Cu, component on F.Cu)
* Opposite Side = Component on opposite layer from test points (e.g., test B.Cu, component on F.Cu)

Configuration Control

Control test point selection in fixture_config.toml:

[board]
test_layer = "F.Cu"  # "F.Cu" (top) or "B.Cu" (bottom)

[test_points]
include_smd_pads = true  # Include surface mount pads
include_pth_pads = true  # Include through-hole pads (opposite side only)

[layers]
force_layer = "Eco2.User"   # Force include pads marked with this layer
ignore_layer = "Eco1.User"  # Exclude pads marked with this layer

Practical Examples

Example 1: USB Connector Testing

  • USB connector mounted on top side (F.Cu)
  • Component body on top prevents direct access to pins from top
  • Solution: Test from bottom side (B.Cu) using PTH pads
  • Through-hole pins are accessible from bottom while connector sits on top

Example 2: Test Points Only

  • SMD test points added to top side (F.Cu)
  • No paste mask on test points
  • Solution: Test from top side (F.Cu) with include_smd=true
  • Pogo pins contact test pads directly

Example 3: Mixed Testing

  • Test points on top side (F.Cu) - use SMD pads
  • Connector pins from top components - use PTH pads from bottom side (B.Cu)
  • Configure: test_layer = "B.Cu", include_smd_pads = true, include_pth_pads = true

Verification

OpenFixture generates track.dxf overlay showing detected test points. Import this into KiCAD to verify:

  1. All required test points are detected
  2. No unwanted pads are included
  3. Alignment is correct
  4. Use force/ignore layers to adjust as needed

Parametric Generation

  • OpenSCAD-based 3D model
  • Adjustable material thickness
  • Custom hardware dimensions
  • Configurable pogo pin placement

Output Files

  • fixture.dxf - Laser-cuttable parts layout
  • fixture.png - 3D preview rendering
  • test.dxf - Material fit test piece
  • outline.dxf - Board outline reference
  • track.dxf - Test point verification overlay for selected test layer

πŸ”§ Fixture Assembly Structure

OpenFixture generates a four-layer clamshell fixture designed for single-sided testing (either top OR bottom layer test points, not both simultaneously).

Layer Structure

The assembled fixture consists of four laser-cut plates:

Top Layers (2 plates with pogo pin holes):

  1. head_base - Lower guide plate with pogo pin holes, lock tabs, and hex nut mounting points
  2. head_top - Upper alignment plate with pogo pin holes and cable relief features

Both top plates share identical pogo pin hole patterns (generated by head_base_common() module) to keep pins perfectly aligned and straight during PCB contact.

Bottom Layers (2 PCB carrier plates):

  1. Top carrier - Has precise PCB outline cutout (border = pcb_support_border, default 1mm) to securely hold the board
  2. Bottom carrier - Has smaller PCB outline cutout (border = -0.05mm) to provide clearance for components without interference

Technical Implementation

The fixture design is parametrically generated in OpenSCAD:

Pogo Pin Hole Generation:

// Both head_base and head_top call head_base_common()
// which generates holes for all test points
module head_base_common () {
    // Top side test points
    for ( i = [0 : len (test_points_top) - 1] ) {
        translate ([origin_x + test_points_top[i][0], origin_y - test_points_top[i][1]])
        circle (r = pogo_r);  // Pogo pin radius (0.75mm default)
    }
    // Bottom side test points
    for ( i = [0 : len (test_points_bottom) - 1] ) {
        translate ([origin_x + test_points_bottom[i][0], origin_y - test_points_bottom[i][1]])
        circle (r = pogo_r);
    }
}

PCB Carrier Generation:

// First carrier: precise PCB holder
carrier (pcb_outline, pcb_x, pcb_y, pcb_support_border);  // border = 1mm (default)

// Second carrier: component clearance
carrier (pcb_outline, pcb_x, pcb_y, -0.05);  // border = -0.05mm (smaller cutout)

The carrier() module scales the PCB outline based on the border parameter:

  • Positive border (e.g., 1mm): Creates cutout larger than PCB for secure fit
  • Negative border (e.g., -0.05mm): Creates cutout smaller than PCB for component clearance

Assembly Example

Assembled OpenFixture

Example of assembled fixture showing the four-layer construction with pogo pins installed in the top layers and PCB positioned in the bottom carrier plate.

3D Rendering of Fixture

3D rendering showing the clamshell design opened to reveal the four-layer structure and PCB placement.

Key Design Features

  • Dual pogo pin plates - Both top plates have identical hole patterns for perfect pin alignment
  • PCB retention - Top carrier has precise cutout (configurable via --border parameter)
  • Component clearance - Bottom carrier has smaller cutout to avoid interference with PCB components
  • Clamshell design - Hinged assembly allows easy board insertion and removal
  • Single-sided testing - Fixture is configured for either top (F.Cu) or bottom (B.Cu) test points
  • Hardware mounting - M3 screws and hex nuts secure the assembly at corners with lock tabs

Code Verification

βœ… head_base module calls head_base_common() - generates pogo pin holes (openfixture.scad:350-390)
βœ… head_top module calls head_base_common() - identical hole pattern (openfixture.scad:403-432)
βœ… carrier module with pcb_support_border parameter (openfixture.scad:686-724)
βœ… lasercut module generates two carriers with different borders (openfixture.scad:867-871)
βœ… --border command-line parameter controls pcb_support_border value (GenFixture.py:789-790)


βš™οΈ Configuration

TOML Configuration File

Create fixture_config.toml in your project directory:

[board]
thickness_mm = 1.6
test_layer = "F.Cu"  # Options: "F.Cu" (top), "B.Cu" (bottom) - select which side to test

[material]
thickness_mm = 3.0

[hardware]
screw_diameter_mm = 3.0
screw_length_mm = 16.0
nut_thickness_mm = 2.4
nut_flat_to_flat_mm = 5.45
nut_corner_to_corner_mm = 6.10
washer_thickness_mm = 1.0
border_mm = 1.0  # PCB carrier cutout border (default: 1.0mm)
                 # Larger values = looser PCB fit, smaller = tighter fit
pogo_uncompressed_length_mm = 16.0

[layers]
force_layer = "Eco2.User"  # Force include pads on this layer as test points
ignore_layer = "Eco1.User" # Exclude pads on this layer from test points

Command-Line Arguments

python3 GenFixture.py \
    --board <file.kicad_pcb>        # Required: PCB file path
    --mat_th <mm>                   # Required: Material thickness
    --out <directory>               # Required: Output directory
    --config <file.toml>            # Optional: Config file
    --pcb_th <mm>                   # Optional: PCB thickness (default: 1.6)
    --layer <F.Cu|B.Cu>             # Optional: Test point layer (top or bottom)
    --rev <string>                  # Optional: Revision string
    --screw_len <mm>                # Optional: Screw length (default: 16.0)
    --screw_d <mm>                  # Optional: Screw diameter (default: 3.0)
    --nut_th <mm>                   # Optional: Nut thickness
    --nut_f2f <mm>                  # Optional: Nut flat-to-flat
    --nut_c2c <mm>                  # Optional: Nut corner-to-corner
    --washer_th <mm>                # Optional: Washer thickness
    --border <mm>                   # Optional: PCB carrier cutout border (default: 1.0)
    --pogo-uncompressed-length <mm> # Optional: Pogo pin length
    --verbose                       # Optional: Enable verbose logging

πŸ“– Documentation

Original Documentation


πŸ”„ Migration from v1

If you're upgrading from a legacy version, see MIGRATION_GUIDE.md for detailed upgrade instructions.

Quick comparison:

Feature Legacy (Original) Current (KiCAD 9+)
KiCAD 6.0/7.0 βœ… Full ⚠️ Limited
KiCAD 8.0/9.0 ❌ No βœ… Full
Python 2 βœ… Yes ❌ No
Python 3 ⚠️ Partial βœ… Full
TOML Config ❌ No βœ… Yes
Type Hints ❌ No βœ… Yes
Modern UI ❌ No βœ… Yes
Error Handling ⚠️ Basic βœ… Complete

πŸ› οΈ Development

File Structure

openfixture/
β”œβ”€β”€ GenFixture.py              # Main generator
β”œβ”€β”€ openfixture.py             # KiCAD plugin
β”œβ”€β”€ fixture_config.toml        # Configuration template
β”œβ”€β”€ genfixture.bat             # Windows wrapper
β”œβ”€β”€ genfixture.sh              # Linux/Mac wrapper
β”œβ”€β”€ openfixture.scad           # OpenSCAD model
β”‚
β”œβ”€β”€ GenFixture.py              # Original generator (v1, legacy)
β”œβ”€β”€ openfixture.py             # Original plugin (v1, legacy)
β”œβ”€β”€ genfixture.bat             # Original wrapper (v1, legacy)
β”œβ”€β”€ genfixture.sh              # Original wrapper (v1, legacy)
β”‚
β”œβ”€β”€ copilot-instructions_openfixture.md  # Complete documentation
β”œβ”€β”€ MIGRATION_GUIDE.md                   # Legacy upgrade guide
β”œβ”€β”€ README_v2.md                         # This file
└── README.md                            # Original README

Key Classes

GenFixture.py:

class FixtureConfig:
    """Configuration container with TOML support"""

class GenFixture:
    """Main fixture generator with modern KiCAD API"""
    
    def get_test_points(self) -> None
    def get_origin_dimensions(self) -> None
    def plot_dxf(self, path: str, layer: str) -> None
    def generate(self, path: str) -> bool

openfixture.py:

class OpenFixtureDialog(wx.Dialog):
    """Modern multi-tab parameter dialog"""
    
    def _create_board_panel(self, parent) -> wx.Panel
    def _create_material_panel(self, parent) -> wx.Panel
    def _create_hardware_panel(self, parent) -> wx.Panel
    def get_parameters(self) -> dict

class OpenFixturePlugin(pcbnew.ActionPlugin):
    """KiCAD action plugin entry point"""
    
    def Run(self) -> None

πŸ› Troubleshooting

Common Issues

"No module named 'tomllib'"

# Install tomli for Python < 3.11
pip install tomli

# Or run without config file
python3 GenFixture.py --board test.kicad_pcb --mat_th 3.0 --out fixture

"No test points found"

  • Ensure SMD pads have no paste mask in KiCAD
  • Or use Eco2.User layer to force include specific pads
  • Check that correct layer (F.Cu/B.Cu) is selected

"Could not find GenFixture.py" (plugin error)

# Ensure both files are in plugins directory:
plugins/
β”œβ”€β”€ openfixture.py
└── GenFixture.py

Plugin not appearing in KiCAD

  1. Check file permissions (must be readable)
  2. Verify correct plugins directory for your KiCAD version
  3. Restart KiCAD completely
  4. Check: Tools β†’ Plugin and Content Manager

Verbose Logging

Enable detailed logging for troubleshooting:

python3 GenFixture.py --board test.kicad_pcb --mat_th 3.0 --out fixture --verbose

πŸ“ Examples

Standard 1.6mm PCB, 3mm Acrylic

python3 GenFixture.py \
    --board my_board.kicad_pcb \
    --mat_th 3.0 \
    --pcb_th 1.6 \
    --out fixture-rev01 \
    --rev "rev_01"

Thin PCB, 2.5mm Acrylic

python3 GenFixture.py \
    --board thin_board.kicad_pcb \
    --mat_th 2.45 \
    --pcb_th 0.8 \
    --screw_len 14.0 \
    --out fixture-thin

Bottom Side Testing

python3 GenFixture.py \
    --board my_board.kicad_pcb \
    --mat_th 3.0 \
    --layer B.Cu \
    --out fixture-bottom

Using Configuration File

# Create fixture_config.toml with your parameters
# Then simply run:
python3 GenFixture.py \
    --board my_board.kicad_pcb \
    --config fixture_config.toml \
    --out fixture

πŸ“œ License

Creative Commons CC BY-SA 4.0

You are free to:

  • Share - Copy and redistribute the material
  • Adapt - Remix, transform, and build upon the material

Under the following terms:

  • Attribution - Give appropriate credit
  • ShareAlike - Distribute under the same license

See: https://creativecommons.org/licenses/by-sa/4.0/


πŸ‘€ Contributors

Original Author:

Modernization & KiCAD 9+ Compatibility (February 2026):

  • For contributions, please use GitHub pull requests

Key Updates:

  • βœ… KiCAD 9.0+ Full Compatibility - All breaking API changes fixed with backward compatibility for KiCAD 8.0
  • βœ… Enhanced OpenSCAD Integration - Robust subprocess execution with proper error handling, timeouts, and path resolution
  • βœ… Python 3.11+ Modernization - Type hints, pathlib, dataclasses, comprehensive logging
  • βœ… TOML Configuration System - Project-specific fixture parameters in fixture_config.toml
  • βœ… Enhanced Plugin UI - Scrollable error dialogs with copy-to-clipboard, output file verification
  • βœ… Security Improvements - Configuration template system, no hardcoded paths, comprehensive .gitignore
  • βœ… Comprehensive Documentation - Updated README, migration guide, security documentation, AI assistant instructions

πŸ”— Links


πŸ’‘ Tips & Best Practices

PCB Design

  • Place test pads in accessible locations (not under components)
  • Use consistent pad size (β‰₯0.5mm diameter)
  • Remove both solder mask and paste mask from test pads
  • Use clear net naming for troubleshooting

Material Selection

  • Acrylic: Best precision (Β±0.05mm), transparent, but can crack
  • Plywood: Budget-friendly, strong, but lower precision (Β±0.2mm)
  • Measure actual thickness with calipers before cutting
  • Use test cut piece to verify fit before full fixture

Hardware

  • M3 hardware is the standard (readily available worldwide)
  • Measure nut dimensions with calipers (varies by manufacturer: 5.4-5.5mm typical)
  • Use nylon-insert lock nuts for fixtures that will be opened/closed frequently
  • Washer selection: Stainless steel washers provide smooth hinge operation

Pogo Pins

  • See POGO_PINS.md for complete specifications and selection guide
  • Budget builds: P75 series ($0.30/point) - 10k-50k cycles, ideal for prototypes
  • Production builds: Fixtest 100 (~$3.50/point) - 100k+ cycles, for high-volume testing
  • Compression: Target 1.0-1.5mm (configured automatically by OpenFixture)
  • Tip selection: Crown (general), Sharp (fine pitch), Flat (high current), Rounded (PTH)
  • Use two-part system (receptacle + replaceable probe) for easy maintenance
  • Keep spare probes on hand - replace before reaching 75% of cycle life

Workflow

  1. Design PCB in KiCAD with test pads
  2. Create fixture_config.toml for project
  3. Generate fixture with v2
  4. Review 3D preview PNG
  5. Cut test piece first (verify fit)
  6. Cut full fixture
  7. Assemble and test

πŸ†˜ Getting Help

  1. Check POGO_PINS.md for pogo pin selection, installation, and troubleshooting
  2. Check copilot-instructions_openfixture.md for detailed documentation
  3. Review MIGRATION_GUIDE.md if upgrading from v1
  4. Enable --verbose logging to diagnose issues
  5. Check original docs: http://tinylabs.io/openfixture
  6. Verify KiCAD version compatibility (v2 requires 8.0+)

Version: 2.0.0
Last Updated: February 15, 2026
Compatibility: KiCAD 8.0+, Python 3.8+, OpenSCAD 2015.03+

About

Open Source Hardware Test/Programming Fixture

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 58.9%
  • OpenSCAD 18.9%
  • PowerShell 18.1%
  • Batchfile 2.1%
  • Shell 2.0%