cleanup
4
scripts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
__pycache__/
|
||||||
|
panel/
|
||||||
|
gerbers/
|
||||||
|
gcode/
|
||||||
@@ -8,319 +8,65 @@ pipx install --system-site-packages kikit
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
# KiKit Fixture Post-Processor
|
# KiKit Fixture Processor
|
||||||
|
|
||||||
Post-processing script for KiKit panelized PCBs that places any generated panel
|
Processing script for KiKit panelizes PCBs and draws a fixture sketch and positions the whole panel for easy CNC processing.
|
||||||
inside a fixed CNC fixture coordinate system.
|
|
||||||
|
|
||||||
The script:
|
The script:
|
||||||
|
|
||||||
- Centres the finished panel inside a predefined fixture opening
|
|
||||||
- Adds mechanical alignment pin holes
|
|
||||||
- Draws fixture reference geometry
|
- Draws fixture reference geometry
|
||||||
- Moves the complete design so the fixture origin is always at `(0, 0)`
|
- Centres the finished panel inside a predefined fixture frame
|
||||||
|
- Adds mechanical alignment pin holes
|
||||||
|
- Moves the finished panel to the origin `(0, 0)`
|
||||||
|
|
||||||
The resulting output is intended for repeatable CNC manufacturing workflows
|
The resulting output is intended for repeatable CNC manufacturing workflows
|
||||||
where drilling, routing, and UV exposure all share the same physical fixture
|
where drilling, routing, and UV exposure all share the same physical fixture
|
||||||
and machine datum.
|
and alignment holes.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fixture Geometry
|
|
||||||
|
|
||||||
## Outer Fixture Frame
|
|
||||||
|
|
||||||
| Parameter | Value |
|
|
||||||
|---|---|
|
|
||||||
| Width | 200.0 mm |
|
|
||||||
| Height | 130.0 mm |
|
|
||||||
|
|
||||||
## Inner Fixture Opening
|
|
||||||
|
|
||||||
| Parameter | Value |
|
|
||||||
|---|---|
|
|
||||||
| Width | 153.4 mm |
|
|
||||||
| Height | 87.0 mm |
|
|
||||||
|
|
||||||
The inner opening defines the usable panel area.
|
|
||||||
|
|
||||||
The region between the outer frame and inner opening forms the fixture rails.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Alignment Pins
|
|
||||||
|
|
||||||
The script inserts four non-plated alignment holes:
|
|
||||||
|
|
||||||
- Diameter: `Ø 3.172 mm NPTH`
|
|
||||||
- Naming: `PIN1`–`PIN4`
|
|
||||||
- Positioning: fully user-defined absolute coordinates
|
|
||||||
|
|
||||||
This allows:
|
|
||||||
|
|
||||||
- deterministic CNC coordinates
|
|
||||||
- compatibility with existing jigs
|
|
||||||
- custom asymmetric fixtures
|
|
||||||
- reuse across multiple panel layouts
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Coordinate System
|
|
||||||
|
|
||||||
After processing:
|
|
||||||
|
|
||||||
- The fixture outer top-left corner is positioned at `(0, 0)`
|
|
||||||
- All PCB data is translated accordingly
|
|
||||||
- Every generated panel shares the same global coordinate system
|
|
||||||
|
|
||||||
This creates deterministic CAM output suitable for automated tooling and
|
|
||||||
repeatable fixture-based manufacturing.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
Place `fixture_postprocess.py` next to the source `.kicad_pcb` file and run KiKit:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Panelize the PCB using the preset defined in `myPreset.json`.
|
||||||
kikit panelize \
|
kikit panelize \
|
||||||
-p myPreset.json \
|
-p myPreset.json \
|
||||||
../Flow_Controller.kicad_pcb \
|
../Flow_Controller.kicad_pcb \
|
||||||
panel/Flow_Controller_Panel.kicad_pcb
|
panel/Flow_Controller_Panel.kicad_pcb
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
Have a look at the new `panel/Flow_Controller_Panel.kicad_pcb` file. It will contain the panel out ot layout specified in `myPreset.json`. E.g.: Grid of 1 x 2 with space 2.1 mm.
|
||||||
|
|
||||||
# Panel Layout Parameters
|
```json
|
||||||
|
"layout": {
|
||||||
## Grid Layout
|
"type": "grid",
|
||||||
|
"rows": 1,
|
||||||
Adjust the panel dimensions using:
|
"cols": 2,
|
||||||
|
"hspace": "2.1mm",
|
||||||
```text
|
"vspace": "2.1mm"
|
||||||
rows: <n>
|
}
|
||||||
cols: <n>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- `1×1`
|
|
||||||
- `1×2`
|
|
||||||
- `2×2`
|
|
||||||
|
|
||||||
The script automatically recalculates centering offsets for the resulting panel size.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tool Diameter Compensation
|
|
||||||
|
|
||||||
The following values should match the routing tool diameter:
|
|
||||||
|
|
||||||
```text
|
|
||||||
space
|
|
||||||
slotwidth
|
|
||||||
```
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
space: 2.1mm
|
|
||||||
slotwidth: 2.1mm
|
|
||||||
```
|
|
||||||
|
|
||||||
This is typically equal to the outline routing bit diameter.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Processing Pipeline
|
|
||||||
|
|
||||||
The post-processing script performs the following operations:
|
|
||||||
|
|
||||||
1. Reads the fully panelized KiKit output
|
|
||||||
2. Calculates the panel bounding box
|
|
||||||
3. Calculates the offset required to centre the panel inside the fixture opening
|
|
||||||
4. Translates the complete board dataset:
|
|
||||||
- footprints
|
|
||||||
- tracks
|
|
||||||
- vias
|
|
||||||
- zones
|
|
||||||
- drawings
|
|
||||||
- board outlines
|
|
||||||
- substrate geometry
|
|
||||||
- locked items
|
|
||||||
5. Places four NPTH alignment pin footprints
|
|
||||||
6. Draws fixture reference rectangles on the `User.1` layer
|
|
||||||
7. Repositions the design so the fixture outer top-left corner equals `(0, 0)`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fixture Visualization
|
|
||||||
|
|
||||||
The script draws two rectangles on the `User.1` layer:
|
|
||||||
|
|
||||||
- Outer fixture boundary
|
|
||||||
- Inner fixture opening
|
|
||||||
|
|
||||||
These graphics:
|
|
||||||
|
|
||||||
- are visible in KiCad
|
|
||||||
- help verify positioning visually
|
|
||||||
- are NOT placed on `Edge.Cuts`
|
|
||||||
- are NOT exported into manufacturing Gerbers or NC drill files
|
|
||||||
|
|
||||||
They exist purely as fixture reference geometry.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# CNC Workflow
|
|
||||||
|
|
||||||
| Operation | File | Purpose |
|
|
||||||
|---|---|---|
|
|
||||||
| Drilling | Excellon `.drl` | PCB holes + fixture alignment pins |
|
|
||||||
| Routing | `Edge.Cuts` Gerber | Board outlines and mousebite tabs |
|
|
||||||
| UV exposure | Copper Gerbers | Soldermask/alignment registration |
|
|
||||||
|
|
||||||
Because all outputs share:
|
|
||||||
|
|
||||||
- identical `(0,0)` origin
|
|
||||||
- identical alignment pin locations
|
|
||||||
- identical fixture geometry
|
|
||||||
|
|
||||||
the PCB can remain mounted in the same physical fixture for the complete process.
|
|
||||||
|
|
||||||
No re-alignment or re-fixturing is required between operations.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Alignment Pins
|
|
||||||
|
|
||||||
The script inserts four non-plated alignment holes:
|
|
||||||
|
|
||||||
- Diameter: `Ø 3.172 mm NPTH`
|
|
||||||
- Naming: `PIN1`–`PIN4`
|
|
||||||
|
|
||||||
Users may override any coordinate manually.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Default Pin Placement Calculation
|
|
||||||
|
|
||||||
For the default fixture dimensions:
|
|
||||||
|
|
||||||
```python
|
|
||||||
OUTER_W_MM = 200.0
|
|
||||||
OUTER_H_MM = 130.0
|
|
||||||
|
|
||||||
INNER_W_MM = 153.4
|
|
||||||
INNER_H_MM = 87.0
|
|
||||||
```
|
|
||||||
|
|
||||||
the resulting suggested coordinates are:
|
|
||||||
|
|
||||||
| Pin | X (mm) | Y (mm) |
|
|
||||||
|---|---|---|
|
|
||||||
| PIN1 (top) | 100.0 | 10.75 |
|
|
||||||
| PIN2 (right) | 188.35 | 65.0 |
|
|
||||||
| PIN3 (bottom) | 100.0 | 119.25 |
|
|
||||||
| PIN4 (left) | 11.65 | 65.0 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fixture Configuration
|
|
||||||
|
|
||||||
Edit the constants at the top of `fixture_postprocess.py`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ============================================================
|
|
||||||
# Fixture geometry
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
OUTER_W_MM = 200.0
|
|
||||||
OUTER_H_MM = 130.0
|
|
||||||
|
|
||||||
INNER_W_MM = 153.4
|
|
||||||
INNER_H_MM = 87.0
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# Alignment pins
|
|
||||||
# Absolute fixture-space coordinates in millimetres
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
PIN_DIAMETER_MM = 3.172
|
|
||||||
|
|
||||||
# Suggested defaults:
|
|
||||||
# top = centered in top rail
|
|
||||||
# right = centered in right rail
|
|
||||||
# bottom = centered in bottom rail
|
|
||||||
# left = centered in left rail
|
|
||||||
|
|
||||||
PIN1_X_MM = 100.0
|
|
||||||
PIN1_Y_MM = 10.75
|
|
||||||
|
|
||||||
PIN2_X_MM = 188.35
|
|
||||||
PIN2_Y_MM = 65.0
|
|
||||||
|
|
||||||
PIN3_X_MM = 100.0
|
|
||||||
PIN3_Y_MM = 119.25
|
|
||||||
|
|
||||||
PIN4_X_MM = 11.65
|
|
||||||
PIN4_Y_MM = 65.0
|
|
||||||
```
|
|
||||||
|
|
||||||
These values may be adjusted freely without changing the placement logic.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Design Constraints
|
|
||||||
|
|
||||||
The generated panel must fit completely inside the inner fixture opening.
|
|
||||||
|
|
||||||
If the panel exceeds the available space, the script emits:
|
|
||||||
|
|
||||||
```text
|
|
||||||
WARNING: panel … is larger than the inner opening
|
|
||||||
```
|
|
||||||
|
|
||||||
Possible solutions:
|
|
||||||
|
|
||||||
- reduce `rows`
|
|
||||||
- reduce `cols`
|
|
||||||
- reduce KiKit frame width
|
|
||||||
- reduce spacing
|
|
||||||
- use a smaller PCB design
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Intended Use Case
|
|
||||||
|
|
||||||
This workflow is intended for:
|
|
||||||
|
|
||||||
- CNC isolation milling
|
|
||||||
- UV mask alignment systems
|
|
||||||
- repeatable prototyping fixtures
|
|
||||||
- hybrid PCB manufacturing workflows
|
|
||||||
- automated or semi-automated PCB handling
|
|
||||||
|
|
||||||
The primary design goal is deterministic panel placement independent of PCB size.
|
|
||||||
|
|
||||||
## Exporting gcode files from KiCad
|
## Exporting gcode files from KiCad
|
||||||
|
|
||||||
Adapt milling and drilling parameters in `millproject`. Look up [pcb2gcode/wiki](https://github.com/pcb2gcode/pcb2gcode/wiki) for help.
|
Adapt milling and drilling parameters in `millproject`. Look up [pcb2gcode/wiki](https://github.com/pcb2gcode/pcb2gcode/wiki) for help.
|
||||||
```bash
|
```bash
|
||||||
nano millproject
|
nano millproject
|
||||||
```
|
```
|
||||||
|
*Make sure to set `mirror-axis` in the `millproject` to half of your board width!!!*
|
||||||
|
|
||||||
Run the export by providing the `.kicad_pcb` file as a first argument:
|
Run the export by providing the `.kicad_pcb` file as a first argument:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x export.sh
|
./export.sh -o gcode panel/Flow_Controller_Panel.kicad_pcb
|
||||||
./export.sh panel/Flow_Controller_Panel.kicad_pcb
|
|
||||||
```
|
```
|
||||||
The script will first generate gerber files in the `output` directory and then convert them into `ngc` format in the `gcode` directory.
|
The script will first generate gerber files in the `gerbers` directory and then generate gcode files in the `gcode` directory.
|
||||||
|
|
||||||
Launch the `gSender` program.
|
Launch the `gSender` program.
|
||||||
* Load the `gcode/drill.ngc` file for drilling holes.
|
* Load the `gcode/drill.ngc` file for drilling holes.
|
||||||
* Load the `gcode/outline.ngc` file for milling the board outlines.
|
* Load the `gcode/outline.ngc` file for milling the board outlines.
|
||||||
* Load the `gcode/back.ngc` file if you want to mill the isolation traces.
|
* Load the `gcode/back.ngc` file if you want to mill the isolation traces.
|
||||||
|
* Load the `gcode/front.ngc` file if you want to mill the isolation traces.
|
||||||
|
|
||||||
## Milling tip: Increase the thermal spoke and trace width
|
## Milling tip: Increase the thermal spoke and trace width
|
||||||
When routing for milling, use the widest traces possible. 1mm, 2mm and wider, the machine doesn't care, but later you won't be soldering leads to small fragile strips of copper. You can use copper pours for routing too.
|
When routing for milling, use the widest traces possible. 1mm, 2mm and wider, the machine doesn't care, but later you won't be soldering leads to small fragile strips of copper. You can use copper pours for routing too.
|
||||||
|
|||||||
96
scripts/cleanup.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import pcbnew
|
||||||
|
from shapely.geometry import MultiPolygon, Polygon
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# KiKit postprocess hook – cleanup.py
|
||||||
|
#
|
||||||
|
# 1. Copy all Edge.Cuts content (substrate rings) to Eco1_User as segments,
|
||||||
|
# EXCEPT the outermost panel rectangle.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TOLERANCE_NM = 1_000 # 1 µm
|
||||||
|
|
||||||
|
|
||||||
|
def _mm(nm_val):
|
||||||
|
return f"{pcbnew.ToMM(int(nm_val)):.4f} mm"
|
||||||
|
|
||||||
|
|
||||||
|
def _collect_rings(geom):
|
||||||
|
"""Return all rings as list of (shapely_ring, coord_list)."""
|
||||||
|
rings = []
|
||||||
|
if isinstance(geom, Polygon):
|
||||||
|
rings.append((geom.exterior, list(geom.exterior.coords)))
|
||||||
|
for interior in geom.interiors:
|
||||||
|
rings.append((interior, list(interior.coords)))
|
||||||
|
elif isinstance(geom, MultiPolygon):
|
||||||
|
for poly in geom.geoms:
|
||||||
|
rings.extend(_collect_rings(poly))
|
||||||
|
return rings
|
||||||
|
|
||||||
|
|
||||||
|
def _is_outer_frame(ring_geom, x0, y0, x1, y1, tol=TOLERANCE_NM):
|
||||||
|
"""True if the ring's bounding box equals the panel bounding box."""
|
||||||
|
b = ring_geom.bounds
|
||||||
|
return (abs(b[0] - x0) <= tol and abs(b[1] - y0) <= tol and
|
||||||
|
abs(b[2] - x1) <= tol and abs(b[3] - y1) <= tol)
|
||||||
|
|
||||||
|
|
||||||
|
def _shapely_to_segments(board, coords, layer, width_mm=0.05):
|
||||||
|
pts = list(coords)
|
||||||
|
if not pts:
|
||||||
|
return 0
|
||||||
|
if pts[0] != pts[-1]:
|
||||||
|
pts.append(pts[0])
|
||||||
|
count = 0
|
||||||
|
for i in range(len(pts) - 1):
|
||||||
|
seg = pcbnew.PCB_SHAPE(board)
|
||||||
|
seg.SetShape(pcbnew.SHAPE_T_SEGMENT)
|
||||||
|
seg.SetLayer(layer)
|
||||||
|
seg.SetWidth(pcbnew.FromMM(width_mm))
|
||||||
|
seg.SetStart(pcbnew.VECTOR2I(int(pts[i][0]), int(pts[i][1])))
|
||||||
|
seg.SetEnd (pcbnew.VECTOR2I(int(pts[i+1][0]), int(pts[i+1][1])))
|
||||||
|
board.Add(seg)
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def kikitPostprocess(panel, arg):
|
||||||
|
print("=" * 60)
|
||||||
|
print("[cleanup] START")
|
||||||
|
|
||||||
|
board = panel.board
|
||||||
|
substrate = panel.boardSubstrate
|
||||||
|
|
||||||
|
# outer panel bbox
|
||||||
|
b = substrate.bounds()
|
||||||
|
x0, y0, x1, y1 = int(b[0]), int(b[1]), int(b[2]), int(b[3])
|
||||||
|
print(f"[cleanup] Panel bbox: ({_mm(x0)},{_mm(y0)})–({_mm(x1)},{_mm(y1)})")
|
||||||
|
|
||||||
|
# get substrate geometry
|
||||||
|
geom = None
|
||||||
|
for attr in ("substrates", "substrate", "_substrate", "geometry"):
|
||||||
|
if hasattr(substrate, attr):
|
||||||
|
geom = getattr(substrate, attr)
|
||||||
|
break
|
||||||
|
if geom is None:
|
||||||
|
print("[cleanup] ERROR: cannot access substrate geometry")
|
||||||
|
return
|
||||||
|
|
||||||
|
rings = _collect_rings(geom)
|
||||||
|
print(f"[cleanup] Total rings in substrate: {len(rings)}")
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
for i, (ring_geom, coords) in enumerate(rings):
|
||||||
|
rb = ring_geom.bounds
|
||||||
|
if _is_outer_frame(ring_geom, x0, y0, x1, y1):
|
||||||
|
print(f"[cleanup] ring[{i}] pts={len(coords)-1} → OUTER FRAME, skipped")
|
||||||
|
continue
|
||||||
|
n = _shapely_to_segments(board, coords, pcbnew.Eco1_User)
|
||||||
|
total += n
|
||||||
|
print(f"[cleanup] ring[{i}] pts={len(coords)-1}"
|
||||||
|
f" bbox=({_mm(rb[0])},{_mm(rb[1])})–({_mm(rb[2])},{_mm(rb[3])})"
|
||||||
|
f" → {n} segments on Eco1_User")
|
||||||
|
|
||||||
|
print(f"[cleanup] Total Eco1_User segments added: {total}")
|
||||||
|
print("[cleanup] END")
|
||||||
|
print("=" * 60)
|
||||||
@@ -1,18 +1,32 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -euo pipefail
|
||||||
|
|
||||||
filename=$(basename -- "$1")
|
GERBERS_DIR="gerbers"
|
||||||
filename="${filename%.*}"
|
|
||||||
|
|
||||||
kicad-cli pcb export gerbers -o output -l Back $1
|
usage() {
|
||||||
kicad-cli pcb export gerbers -o output -l Edge.Cuts $1
|
echo "Usage: $0 <kicad_pcb_file>"
|
||||||
kicad-cli pcb export drill -o output $1
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
mkdir -p gcode
|
PCB_FILE="$1"
|
||||||
|
|
||||||
docker run --rm -i -t -u "$(id -u):$(id -g)" -v ".:/data" ptodorov/pcb2gcode \
|
mkdir -p "$GERBERS_DIR"
|
||||||
--back="output/$filename-Back.gbl" \
|
|
||||||
--drill="output/$filename.drl" \
|
|
||||||
--outline="output/$filename-Edge_Cuts.gm1"
|
|
||||||
|
|
||||||
|
# export drill, front and back layers as gerber files
|
||||||
|
kicad-cli pcb export drill -o "$GERBERS_DIR" "$PCB_FILE"
|
||||||
|
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Front "$PCB_FILE"
|
||||||
|
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Back "$PCB_FILE"
|
||||||
|
kicad-cli pcb export gerbers -o "$GERBERS_DIR" -l Edge.Cuts "$PCB_FILE"
|
||||||
|
|
||||||
|
# Export outlines of the penelized boards only; Use the layer 'User.Eco1'.
|
||||||
|
python3 export_panel_outlines_gerber.py \
|
||||||
|
--layers User.Eco1 \
|
||||||
|
--output "$GERBERS_DIR" \
|
||||||
|
"$PCB_FILE"
|
||||||
|
|
||||||
|
# set input filenames and all milling parameters in `millproject` config file
|
||||||
|
docker run --rm -i -t \
|
||||||
|
-u "$(id -u):$(id -g)" \
|
||||||
|
-v "$(pwd):/data" \
|
||||||
|
ptodorov/pcb2gcode
|
||||||
44
scripts/export_panel_outlines_gerber.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import pcbnew
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Export a single PCB layer to a Gerber file using pcbnew."
|
||||||
|
)
|
||||||
|
parser.add_argument("input", help="Input .kicad_pcb file")
|
||||||
|
parser.add_argument("--output", "-o", required=True, help="Output directory")
|
||||||
|
parser.add_argument("--layers", "-l", required=True,
|
||||||
|
help="Layer name to export (e.g. User.Eco1)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
board = pcbnew.LoadBoard(args.input)
|
||||||
|
|
||||||
|
# Resolve layer name to ID
|
||||||
|
layer_id = board.GetLayerID(args.layers)
|
||||||
|
if layer_id == -1:
|
||||||
|
parser.error(f"Unknown layer: {args.layers!r}. "
|
||||||
|
f"Run with a known layer name (e.g. User.Eco1, Edge.Cuts).")
|
||||||
|
|
||||||
|
# Resolve output directory to absolute path so pcbnew doesn't make it
|
||||||
|
# relative to the board file location
|
||||||
|
output_dir = os.path.abspath(args.output)
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
|
prefix = args.layers.replace(".", "-")
|
||||||
|
|
||||||
|
pc = pcbnew.PLOT_CONTROLLER(board)
|
||||||
|
po = pc.GetPlotOptions()
|
||||||
|
po.SetOutputDirectory(output_dir)
|
||||||
|
po.SetPlotFrameRef(False)
|
||||||
|
|
||||||
|
pc.SetLayer(layer_id)
|
||||||
|
pc.OpenPlotfile(prefix, pcbnew.PLOT_FORMAT_GERBER, args.layers)
|
||||||
|
print(f"Plotting layer {args.layers!r} (id={layer_id}) to {pc.GetPlotFileName()}")
|
||||||
|
pc.PlotLayer()
|
||||||
|
pc.ClosePlot()
|
||||||
|
print("Done.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
import math
|
|
||||||
import pcbnew
|
|
||||||
from shapely.affinity import translate
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# Fixture geometry
|
|
||||||
# ============================================================
|
|
||||||
OUTER_W_MM = 200.0
|
|
||||||
OUTER_H_MM = 130.0
|
|
||||||
|
|
||||||
INNER_W_MM = 153.4
|
|
||||||
INNER_H_MM = 87.0
|
|
||||||
|
|
||||||
INNER_X_MM = (OUTER_W_MM - INNER_W_MM) / 2 # 23.3
|
|
||||||
INNER_Y_MM = (OUTER_H_MM - INNER_H_MM) / 2 # 21.5
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# Alignment pins
|
|
||||||
# Absolute fixture-space coordinates in millimetres
|
|
||||||
# ============================================================
|
|
||||||
PIN_DIAMETER_MM = 3.172
|
|
||||||
|
|
||||||
# Suggested defaults:
|
|
||||||
# top = centered in top rail
|
|
||||||
# right = centered in right rail
|
|
||||||
# bottom = centered in bottom rail
|
|
||||||
# left = centered in left rail
|
|
||||||
|
|
||||||
PIN1_X_MM = 100.0
|
|
||||||
PIN1_Y_MM = 10.75
|
|
||||||
|
|
||||||
PIN2_X_MM = 188.35
|
|
||||||
PIN2_Y_MM = 65.0
|
|
||||||
|
|
||||||
PIN3_X_MM = 100.0
|
|
||||||
PIN3_Y_MM = 119.25
|
|
||||||
|
|
||||||
PIN4_X_MM = 11.65
|
|
||||||
PIN4_Y_MM = 65.0
|
|
||||||
|
|
||||||
# KiCad internal unit: 1 mm = 1 000 000 nm
|
|
||||||
MM = 1_000_000
|
|
||||||
|
|
||||||
|
|
||||||
def mm(v: float) -> int:
|
|
||||||
"""Convert mm float to KiCad internal units (nm)."""
|
|
||||||
return int(round(v * MM))
|
|
||||||
|
|
||||||
|
|
||||||
def _move_all(panel, dx_nm: int, dy_nm: int) -> None:
|
|
||||||
"""Translate every object on the board by (dx_nm, dy_nm)."""
|
|
||||||
vec = pcbnew.VECTOR2I(dx_nm, dy_nm)
|
|
||||||
for fp in panel.board.GetFootprints():
|
|
||||||
fp.Move(vec)
|
|
||||||
for track in panel.board.GetTracks():
|
|
||||||
track.Move(vec)
|
|
||||||
for drawing in panel.board.GetDrawings():
|
|
||||||
drawing.Move(vec)
|
|
||||||
for zone in panel.board.Zones():
|
|
||||||
zone.Move(vec)
|
|
||||||
# Keep the Shapely substrate in sync
|
|
||||||
panel.boardSubstrate.substrates = translate(
|
|
||||||
panel.boardSubstrate.substrates,
|
|
||||||
xoff=dx_nm,
|
|
||||||
yoff=dy_nm,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _edge_cuts_bbox(panel):
|
|
||||||
"""Return (minx, miny, maxx, maxy) in nm from the Shapely substrate."""
|
|
||||||
return panel.boardSubstrate.substrates.bounds # already in nm
|
|
||||||
|
|
||||||
|
|
||||||
def _draw_rect(board, layer, x0_nm, y0_nm, x1_nm, y1_nm, width_nm=None):
|
|
||||||
"""Draw an axis-aligned rectangle on *layer* using four PCB_SHAPE lines."""
|
|
||||||
if width_nm is None:
|
|
||||||
width_nm = mm(0.1) # 0.1 mm line width – thin reference line
|
|
||||||
corners = [
|
|
||||||
(x0_nm, y0_nm), (x1_nm, y0_nm),
|
|
||||||
(x1_nm, y1_nm), (x0_nm, y1_nm),
|
|
||||||
]
|
|
||||||
for i in range(4):
|
|
||||||
seg = pcbnew.PCB_SHAPE(board)
|
|
||||||
seg.SetShape(pcbnew.SHAPE_T_SEGMENT)
|
|
||||||
seg.SetLayer(layer)
|
|
||||||
seg.SetWidth(width_nm)
|
|
||||||
x_a, y_a = corners[i]
|
|
||||||
x_b, y_b = corners[(i + 1) % 4]
|
|
||||||
seg.SetStart(pcbnew.VECTOR2I(x_a, y_a))
|
|
||||||
seg.SetEnd(pcbnew.VECTOR2I(x_b, y_b))
|
|
||||||
board.Add(seg)
|
|
||||||
|
|
||||||
|
|
||||||
def _draw_circle(board, layer, cx_nm, cy_nm, r_nm, width_nm=None):
|
|
||||||
"""Draw a circle on *layer*."""
|
|
||||||
if width_nm is None:
|
|
||||||
width_nm = mm(0.1)
|
|
||||||
circ = pcbnew.PCB_SHAPE(board)
|
|
||||||
circ.SetShape(pcbnew.SHAPE_T_CIRCLE)
|
|
||||||
circ.SetLayer(layer)
|
|
||||||
circ.SetWidth(width_nm)
|
|
||||||
circ.SetCenter(pcbnew.VECTOR2I(cx_nm, cy_nm))
|
|
||||||
circ.SetEnd(pcbnew.VECTOR2I(cx_nm + r_nm, cy_nm))
|
|
||||||
board.Add(circ)
|
|
||||||
|
|
||||||
|
|
||||||
def _add_pin_footprint(board, x_nm, y_nm, diameter_mm, index):
|
|
||||||
"""
|
|
||||||
Add a non-plated through-hole (NPTH) mounting hole footprint at (x_nm, y_nm).
|
|
||||||
|
|
||||||
We create a minimal footprint with a single NPTH pad so that:
|
|
||||||
• The drill appears in the Excellon output → used for physical alignment pins.
|
|
||||||
• No copper ring is added.
|
|
||||||
"""
|
|
||||||
fp = pcbnew.FOOTPRINT(board)
|
|
||||||
fp.SetReference(f"PIN{index}")
|
|
||||||
fp.Reference().SetVisible(False)
|
|
||||||
fp.SetValue(f"Ø{diameter_mm:.3f}mm NPTH")
|
|
||||||
fp.Value().SetVisible(False)
|
|
||||||
fp.SetPosition(pcbnew.VECTOR2I(x_nm, y_nm))
|
|
||||||
|
|
||||||
pad = pcbnew.PAD(fp)
|
|
||||||
pad.SetAttribute(pcbnew.PAD_ATTRIB_NPTH)
|
|
||||||
pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
|
|
||||||
pad.SetDrillShape(pcbnew.PAD_DRILL_SHAPE_CIRCLE)
|
|
||||||
|
|
||||||
d_nm = mm(diameter_mm)
|
|
||||||
pad.SetSize(pcbnew.VECTOR2I(d_nm, d_nm))
|
|
||||||
pad.SetDrillSize(pcbnew.VECTOR2I(d_nm, d_nm))
|
|
||||||
pad.SetLayerSet(pcbnew.LSET.AllCuMask()) # NPTH pads span all Cu layers
|
|
||||||
pad.SetNumber("")
|
|
||||||
|
|
||||||
fp.Add(pad)
|
|
||||||
board.Add(fp)
|
|
||||||
|
|
||||||
# Also draw a circle on Dwgs_User so the pin is visible even without
|
|
||||||
# the fab/courtyard layers being turned on.
|
|
||||||
_draw_circle(
|
|
||||||
board,
|
|
||||||
pcbnew.Dwgs_User,
|
|
||||||
x_nm, y_nm,
|
|
||||||
mm(diameter_mm / 2),
|
|
||||||
mm(0.1),
|
|
||||||
)
|
|
||||||
|
|
||||||
return fp
|
|
||||||
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────
|
|
||||||
# MAIN ENTRY POINT
|
|
||||||
# ──────────────────────────────────────────────────────────────
|
|
||||||
def kikitPostprocess(panel, args):
|
|
||||||
board = panel.board
|
|
||||||
|
|
||||||
# ── Step 1: get current Edge.Cuts bounding box ────────────────────────────
|
|
||||||
bounds = _edge_cuts_bbox(panel) # (minx, miny, maxx, maxy) in nm
|
|
||||||
panel_w_nm = bounds[2] - bounds[0]
|
|
||||||
panel_h_nm = bounds[3] - bounds[1]
|
|
||||||
|
|
||||||
panel_w_mm = panel_w_nm / MM
|
|
||||||
panel_h_mm = panel_h_nm / MM
|
|
||||||
|
|
||||||
print(f"[fixture] Panel size: {panel_w_mm:.3f} x {panel_h_mm:.3f} mm")
|
|
||||||
|
|
||||||
# ── Step 2: compute where panel top-left should land ─────────────────────
|
|
||||||
# We want the panel centred inside the inner opening of the fixture.
|
|
||||||
# Inner opening: top-left is at (INNER_X_MM, INNER_Y_MM) relative to
|
|
||||||
# the fixture outer top-left.
|
|
||||||
panel_target_x_mm = INNER_X_MM + (INNER_W_MM - panel_w_mm) / 2
|
|
||||||
panel_target_y_mm = INNER_Y_MM + (INNER_H_MM - panel_h_mm) / 2
|
|
||||||
|
|
||||||
print(f"[fixture] Panel will be placed at ({panel_target_x_mm:.3f}, {panel_target_y_mm:.3f}) mm")
|
|
||||||
|
|
||||||
# Warn if the panel is larger than the inner opening (it will still be
|
|
||||||
# centred but will overlap the frame rails).
|
|
||||||
if panel_w_mm > INNER_W_MM or panel_h_mm > INNER_H_MM:
|
|
||||||
print(
|
|
||||||
f"[fixture] WARNING: panel ({panel_w_mm:.1f}×{panel_h_mm:.1f} mm) "
|
|
||||||
f"is larger than the inner opening ({INNER_W_MM}×{INNER_H_MM} mm)!"
|
|
||||||
)
|
|
||||||
|
|
||||||
# ── Step 3: move everything so that the panel lands at the target ─────────
|
|
||||||
# Current panel TL is at (bounds[0], bounds[1]).
|
|
||||||
# We need to shift by (target - current).
|
|
||||||
dx_nm = mm(panel_target_x_mm) - bounds[0]
|
|
||||||
dy_nm = mm(panel_target_y_mm) - bounds[1]
|
|
||||||
_move_all(panel, int(dx_nm), int(dy_nm))
|
|
||||||
|
|
||||||
# ── Step 4: verify final position ────────────────────────────────────────
|
|
||||||
new_bounds = _edge_cuts_bbox(panel)
|
|
||||||
print(
|
|
||||||
f"[fixture] Panel TL after move: "
|
|
||||||
f"({new_bounds[0]/MM:.3f}, {new_bounds[1]/MM:.3f}) mm"
|
|
||||||
)
|
|
||||||
|
|
||||||
# ── Step 5: draw fixture frame on Dwgs_User ───────────────────────────
|
|
||||||
# Outer rectangle: (0,0) → (200, 130) mm
|
|
||||||
_draw_rect(
|
|
||||||
board, pcbnew.Dwgs_User,
|
|
||||||
mm(0), mm(0),
|
|
||||||
mm(OUTER_W_MM), mm(OUTER_H_MM),
|
|
||||||
mm(0.15),
|
|
||||||
)
|
|
||||||
# Inner rectangle: (23.3, 21.5) → (176.7, 108.5) mm
|
|
||||||
_draw_rect(
|
|
||||||
board, pcbnew.Dwgs_User,
|
|
||||||
mm(INNER_X_MM), mm(INNER_Y_MM),
|
|
||||||
mm(INNER_X_MM + INNER_W_MM), mm(INNER_Y_MM + INNER_H_MM),
|
|
||||||
mm(0.15),
|
|
||||||
)
|
|
||||||
|
|
||||||
print("[fixture] Fixture frame drawn on Dwgs_User layer.")
|
|
||||||
|
|
||||||
# ── Step 6: add alignment pin footprints ──────────────────────────────────
|
|
||||||
# Place pins at the absolute coordinates defined in the configuration block above
|
|
||||||
pin_positions_mm = [
|
|
||||||
(PIN1_X_MM, PIN1_Y_MM, "PIN1 (Top)"),
|
|
||||||
(PIN2_X_MM, PIN2_Y_MM, "PIN2 (Right)"),
|
|
||||||
(PIN3_X_MM, PIN3_Y_MM, "PIN3 (Bottom)"),
|
|
||||||
(PIN4_X_MM, PIN4_Y_MM, "PIN4 (Left)"),
|
|
||||||
]
|
|
||||||
|
|
||||||
for idx, (px_mm, py_mm, label) in enumerate(pin_positions_mm, start=1):
|
|
||||||
_add_pin_footprint(board, mm(px_mm), mm(py_mm), PIN_DIAMETER_MM, idx)
|
|
||||||
print(
|
|
||||||
f"[fixture] {label} placed at "
|
|
||||||
f"({px_mm:.3f}, {py_mm:.3f}) mm"
|
|
||||||
)
|
|
||||||
|
|
||||||
print("[fixture] Post-processing complete.")
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg width="418.014" height="221.1" viewBox="0 0 8708.63 4606.25" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<polyline points="1970.1,4028.53 1970.01,4028.52 1969.62,4028.52 1969.55,4028.53" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1970.1,4028.53 1970.01,4028.52 1969.62,4028.52 1969.55,4028.53" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1969.52,4028.53 1969.62,4028.52 1970.01,4028.52 1970.12,4028.53" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1969.52,4028.53 1969.62,4028.52 1970.01,4028.52 1970.12,4028.53" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="6072.67,4028.57 6072.5,4028.56 6072.37,4028.54 6071.98,4028.53 6071.88,4028.53" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="6072.67,4028.57 6072.5,4028.56 6072.37,4028.54 6071.98,4028.53 6071.88,4028.53" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="6071.86,4028.54 6071.98,4028.53 6072.37,4028.54 6072.5,4028.56 6072.7,4028.57" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="6071.86,4028.54 6071.98,4028.53 6072.37,4028.54 6072.5,4028.56 6072.7,4028.57" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg width="418.014" height="221.1" viewBox="0 0 8708.63 4606.25" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<polyline points="1969.56,4028.53 1970.06,4028.53" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1969.56,4028.53 1970.06,4028.53" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1970.06,4028.53 1969.56,4028.53" style="stroke:rgb(255,0,0);stroke-width:3.937008;fill:none;stroke-opacity:0.5;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
<polyline points="1970.06,4028.53 1969.56,4028.53" style="stroke:rgb(0,0,0);stroke-width:1px;fill:none;stroke-opacity:1;stroke-linecap:round;stroke-linejoin:round;;fill:none"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,372 +0,0 @@
|
|||||||
( pcb2gcode 2.5.0 )
|
|
||||||
( Software-independent Gcode )
|
|
||||||
|
|
||||||
( This file uses only one drill bit. Forced by 'onedrill' option )
|
|
||||||
|
|
||||||
G94 (Millimeters per minute feed rate.)
|
|
||||||
G21 (Units == Millimeters.)
|
|
||||||
G91.1 (Incremental arc distance mode.)
|
|
||||||
G90 (Absolute coordinates.)
|
|
||||||
G00 S24000 (RPM spindle speed.)
|
|
||||||
|
|
||||||
G00 Z35.00000 (Retract)
|
|
||||||
T1
|
|
||||||
M5 (Spindle stop.)
|
|
||||||
G04 P1.00000
|
|
||||||
(MSG, Change tool bit to drill size 0.95mm)
|
|
||||||
M0 (Temporary machine stop.)
|
|
||||||
M3 (Spindle on clockwise.)
|
|
||||||
G0 Z2.00000
|
|
||||||
G04 P1.00000
|
|
||||||
|
|
||||||
G1 F500.00000
|
|
||||||
G0 X0.00000 Y-10.75000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X29.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X28.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X27.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X26.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X25.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X24.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X23.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X20.36700 Y-45.14700
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X14.13000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X11.59000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X9.05000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X4.05000 Y-43.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-4.05000 Y-43.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.84800 Y-45.17900
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-56.12000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-58.66000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-61.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-63.74000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-66.28000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-68.82000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-71.36000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-62.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-63.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-64.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-66.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-67.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.41600 Y-73.90000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-18.90000 Y-69.42500
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-18.80000 Y-65.67500
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-31.73300 Y-45.14700
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-23.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-24.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-25.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-26.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-27.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-28.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-29.05000 Y-40.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-37.97000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-40.51000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.60000 Y-53.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.60000 Y-55.50000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-43.05000 Y-45.55000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-48.05000 Y-43.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-88.35000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-62.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.60000 Y-58.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-63.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-64.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-66.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-67.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-50.85000 Y-68.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.65000 Y-73.85000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.65000 Y-76.35000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-45.65000 Y-78.85000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-48.05000 Y-87.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-31.78400 Y-84.82200
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-29.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-28.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-27.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-26.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-25.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-24.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-23.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-8.92400 Y-84.84700
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-4.05000 Y-87.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X4.05000 Y-87.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.45000 Y-78.85000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.45000 Y-76.35000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.45000 Y-73.85000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-68.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X-1.25000 Y-68.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-67.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-66.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-64.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-63.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X1.25000 Y-62.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.50000 Y-58.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.50000 Y-55.50000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X6.50000 Y-53.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X33.30000 Y-65.67500
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X33.20000 Y-69.42500
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X20.31600 Y-84.82200
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X23.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X24.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X25.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X26.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X27.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X0.00000 Y-119.25000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X28.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X29.05000 Y-89.80000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.17600 Y-84.84700
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X48.05000 Y-87.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-73.90000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-71.36000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-68.82000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-66.28000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-63.74000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-68.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-67.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-66.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-64.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-63.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X50.85000 Y-62.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-61.20000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-58.66000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.68400 Y-56.12000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X43.25200 Y-45.17900
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X48.05000 Y-43.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
G0 X88.35000 Y-65.00000
|
|
||||||
G1 Z-2.20000
|
|
||||||
G1 Z2.00000
|
|
||||||
|
|
||||||
G00 Z35.000 ( All done -- retract )
|
|
||||||
|
|
||||||
M5 (Spindle off.)
|
|
||||||
G04 P1.000000
|
|
||||||
M9 (Coolant off.)
|
|
||||||
M2 (Program end.)
|
|
||||||
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg width="418.014" height="221.1" viewBox="0 0 8708.63 4606.25" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<circle cx="4354.33" cy="-1968.53" r="37.4016" style=""/>
|
|
||||||
<circle cx="2066.93" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2145.67" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2224.41" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2303.15" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2381.89" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2460.63" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2539.37" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="2750.63" cy="739.899" r="37.4016" style=""/>
|
|
||||||
<circle cx="3241.73" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="3441.73" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="3641.73" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="4035.43" cy="570.844" r="37.4016" style=""/>
|
|
||||||
<circle cx="4673.23" cy="570.844" r="37.4016" style=""/>
|
|
||||||
<circle cx="5051.02" cy="742.419" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="1603.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="1803.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="2003.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="2203.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="2403.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="2603.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="2803.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2066.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2145.65" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2224.39" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2381.87" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2460.61" r="37.4016" style=""/>
|
|
||||||
<circle cx="5017.01" cy="3003.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="5842.52" cy="2651.55" r="37.4016" style=""/>
|
|
||||||
<circle cx="5834.65" cy="2356.28" r="37.4016" style=""/>
|
|
||||||
<circle cx="6852.99" cy="739.899" r="37.4016" style=""/>
|
|
||||||
<circle cx="6169.29" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6248.03" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6326.77" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6405.51" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6484.25" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6562.99" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="6641.73" cy="350.371" r="37.4016" style=""/>
|
|
||||||
<circle cx="7344.09" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="7544.09" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="7944.88" cy="1358.25" r="37.4016" style=""/>
|
|
||||||
<circle cx="7944.88" cy="1555.1" r="37.4016" style=""/>
|
|
||||||
<circle cx="7744.09" cy="771.631" r="37.4016" style=""/>
|
|
||||||
<circle cx="8137.8" cy="570.844" r="37.4016" style=""/>
|
|
||||||
<circle cx="11311" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2066.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="7944.88" cy="1751.95" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2145.65" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2224.39" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2381.87" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2460.61" r="37.4016" style=""/>
|
|
||||||
<circle cx="8358.27" cy="2539.35" r="37.4016" style=""/>
|
|
||||||
<circle cx="7948.82" cy="2999.98" r="37.4016" style=""/>
|
|
||||||
<circle cx="7948.82" cy="3196.83" r="37.4016" style=""/>
|
|
||||||
<circle cx="7948.82" cy="3393.68" r="37.4016" style=""/>
|
|
||||||
<circle cx="8137.8" cy="4035.41" r="37.4016" style=""/>
|
|
||||||
<circle cx="6857.01" cy="3863.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="6641.73" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6562.99" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6484.25" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6405.51" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6326.77" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6248.03" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="6169.29" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="5057.01" cy="3865.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="4673.23" cy="4035.41" r="37.4016" style=""/>
|
|
||||||
<circle cx="4035.43" cy="4035.41" r="37.4016" style=""/>
|
|
||||||
<circle cx="3846.46" cy="3393.68" r="37.4016" style=""/>
|
|
||||||
<circle cx="3846.46" cy="3196.83" r="37.4016" style=""/>
|
|
||||||
<circle cx="3846.46" cy="2999.98" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2539.35" r="37.4016" style=""/>
|
|
||||||
<circle cx="4452.76" cy="2539.35" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2460.61" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2381.87" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2224.39" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2145.65" r="37.4016" style=""/>
|
|
||||||
<circle cx="4255.91" cy="2066.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="3842.52" cy="1751.95" r="37.4016" style=""/>
|
|
||||||
<circle cx="3842.52" cy="1555.1" r="37.4016" style=""/>
|
|
||||||
<circle cx="3842.52" cy="1358.25" r="37.4016" style=""/>
|
|
||||||
<circle cx="1732.28" cy="2356.28" r="37.4016" style=""/>
|
|
||||||
<circle cx="1740.16" cy="2651.55" r="37.4016" style=""/>
|
|
||||||
<circle cx="2754.65" cy="3863.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="2539.37" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="2460.63" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="2381.89" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="2303.15" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="2224.41" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="4354.33" cy="6574.78" r="37.4016" style=""/>
|
|
||||||
<circle cx="2145.67" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="2066.93" cy="4255.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="954.646" cy="3865.88" r="37.4016" style=""/>
|
|
||||||
<circle cx="570.866" cy="4035.41" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="3003.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="2803.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="2603.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="2403.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="2203.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2539.35" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2460.61" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2381.87" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2224.39" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2145.65" r="37.4016" style=""/>
|
|
||||||
<circle cx="350.394" cy="2066.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="2003.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="1803.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="914.646" cy="1603.91" r="37.4016" style=""/>
|
|
||||||
<circle cx="948.661" cy="742.419" r="37.4016" style=""/>
|
|
||||||
<circle cx="570.866" cy="570.844" r="37.4016" style=""/>
|
|
||||||
<circle cx="-2602.36" cy="2303.13" r="37.4016" style=""/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 6.6 KiB |
@@ -1,322 +0,0 @@
|
|||||||
( pcb2gcode 2.5.0 )
|
|
||||||
( Software-independent Gcode )
|
|
||||||
|
|
||||||
G94 ( Millimeters per minute feed rate. )
|
|
||||||
G21 ( Units == Millimeters. )
|
|
||||||
|
|
||||||
G90 ( Absolute coordinates. )
|
|
||||||
G00 S24000 ( RPM spindle speed. )
|
|
||||||
G01 F400.00000 ( Feedrate. )
|
|
||||||
|
|
||||||
|
|
||||||
G00 Z35.00000 (Retract to tool change height)
|
|
||||||
T1
|
|
||||||
M5 (Spindle stop.)
|
|
||||||
G04 P1.00000 (Wait for spindle to stop)
|
|
||||||
(MSG, Change tool bit to cutter diameter 2.10000mm)
|
|
||||||
M0 (Temporary machine stop.)
|
|
||||||
M3 ( Spindle on clockwise. )
|
|
||||||
G04 P1.00000 (Wait for spindle to get up to speed)
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X52.00002 Y-90.92517 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X51.99966 Y-90.71861
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X51.99938 Y-90.55170
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X51.99922 Y-90.45729
|
|
||||||
G01 X51.99921 Y-90.45212
|
|
||||||
G01 X51.94965 Y-90.54069
|
|
||||||
G01 X51.90472 Y-90.60924
|
|
||||||
G01 X51.86050 Y-90.66640
|
|
||||||
G01 X51.85455 Y-90.67409
|
|
||||||
G01 X51.79225 Y-90.74211
|
|
||||||
G01 X51.72425 Y-90.80442
|
|
||||||
G01 X51.65941 Y-90.85458
|
|
||||||
G01 X51.64306 Y-90.86530
|
|
||||||
G01 X51.59085 Y-90.89954
|
|
||||||
G01 X51.50215 Y-90.94917
|
|
||||||
G01 X51.57808 Y-90.94930
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X51.59941 Y-90.94934
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X51.86031 Y-90.94979
|
|
||||||
G01 X51.97523 Y-90.94998
|
|
||||||
G01 X51.99885 Y-90.94881
|
|
||||||
G01 X52.00002 Y-90.92517
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X-51.49954 Y-90.94907 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-51.50760 Y-90.94906
|
|
||||||
G01 X-51.83861 Y-90.94890
|
|
||||||
G01 X-51.99881 Y-90.94881
|
|
||||||
G01 X-51.99881 Y-90.81165
|
|
||||||
G01 X-51.99881 Y-90.78886
|
|
||||||
G01 X-51.99881 Y-90.54960
|
|
||||||
G01 X-51.99881 Y-90.45003
|
|
||||||
G01 X-51.94631 Y-90.53032
|
|
||||||
G01 X-51.90694 Y-90.58112
|
|
||||||
G01 X-51.88938 Y-90.60378
|
|
||||||
G01 X-51.72091 Y-90.77792
|
|
||||||
G01 X-51.70116 Y-90.79542
|
|
||||||
G01 X-51.63076 Y-90.85778
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-51.62078 Y-90.86662
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-51.49954 Y-90.94907
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X52.00002 Y-39.53165 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X51.99904 Y-39.12963
|
|
||||||
G01 X51.99885 Y-39.05113
|
|
||||||
G01 X51.86234 Y-39.05103
|
|
||||||
G01 X51.82895 Y-39.05101
|
|
||||||
G01 X51.61072 Y-39.05085
|
|
||||||
G01 X51.50154 Y-39.05077
|
|
||||||
G01 X51.58783 Y-39.09875
|
|
||||||
G01 X51.65565 Y-39.14285
|
|
||||||
G01 X51.71988 Y-39.19205
|
|
||||||
G01 X51.75973 Y-39.22776
|
|
||||||
G01 X51.78013 Y-39.24605
|
|
||||||
G01 X51.84272 Y-39.31214
|
|
||||||
G01 X51.85955 Y-39.33333
|
|
||||||
G01 X51.89933 Y-39.38341
|
|
||||||
G01 X51.92100 Y-39.41578
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X51.94434 Y-39.45064
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X51.99679 Y-39.54362
|
|
||||||
G01 X51.99921 Y-39.54790
|
|
||||||
G01 X52.00002 Y-39.53165
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X-51.49954 Y-39.05087 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-51.83765 Y-39.05105
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-51.86302 Y-39.05106
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-51.99881 Y-39.05113
|
|
||||||
G01 X-51.99890 Y-39.21225
|
|
||||||
G01 X-51.99890 Y-39.21325
|
|
||||||
G01 X-51.99909 Y-39.55031
|
|
||||||
G01 X-51.91676 Y-39.42809
|
|
||||||
G01 X-51.90766 Y-39.41773
|
|
||||||
G01 X-51.84620 Y-39.34777
|
|
||||||
G01 X-51.82799 Y-39.32705
|
|
||||||
G01 X-51.68163 Y-39.18700
|
|
||||||
G01 X-51.65139 Y-39.15806
|
|
||||||
G01 X-51.63164 Y-39.14290
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-51.57884 Y-39.10236
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-51.49954 Y-39.05087
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X0.59796 Y-90.94917 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.38604 Y-90.94915
|
|
||||||
G01 X-0.59840 Y-90.94914
|
|
||||||
G01 X-0.57576 Y-90.93378
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-0.43737 Y-90.83987
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.34275 Y-90.76319
|
|
||||||
G01 X-0.24445 Y-90.66063
|
|
||||||
G01 X-0.16635 Y-90.55430
|
|
||||||
G01 X-0.09787 Y-90.42982
|
|
||||||
G01 X-0.04682 Y-90.29723
|
|
||||||
G01 X-0.01413 Y-90.15898
|
|
||||||
G01 X-0.00041 Y-90.01757
|
|
||||||
G01 X-0.00040 Y-89.77894
|
|
||||||
G01 X-0.00038 Y-88.78861
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-0.00022 Y-80.67196
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.00017 Y-78.07196
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X0.00002 Y-68.72635
|
|
||||||
G01 X0.00095 Y-89.80499
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X0.00096 Y-90.03035
|
|
||||||
G01 X0.01481 Y-90.17231
|
|
||||||
G01 X0.04775 Y-90.31107
|
|
||||||
G01 X0.09918 Y-90.44409
|
|
||||||
G01 X0.16817 Y-90.56893
|
|
||||||
G01 X0.25344 Y-90.68323
|
|
||||||
G01 X0.35341 Y-90.78496
|
|
||||||
G01 X0.46626 Y-90.87218
|
|
||||||
G01 X0.59250 Y-90.94598
|
|
||||||
G01 X0.59796 Y-90.94917
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X0.59796 Y-39.05077 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.38717 Y-39.05079
|
|
||||||
G01 X-0.59916 Y-39.05080
|
|
||||||
G01 X-0.57714 Y-39.06571
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-0.43132 Y-39.16444
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.34450 Y-39.23515
|
|
||||||
G01 X-0.25230 Y-39.33002
|
|
||||||
G01 X-0.16724 Y-39.44427
|
|
||||||
G01 X-0.09840 Y-39.56901
|
|
||||||
G01 X-0.04707 Y-39.70190
|
|
||||||
G01 X-0.01420 Y-39.84051
|
|
||||||
G01 X-0.00041 Y-39.98229
|
|
||||||
G01 X-0.00040 Y-40.22440
|
|
||||||
G01 X-0.00038 Y-41.21107
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-0.00022 Y-49.32795
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-0.00017 Y-51.92795
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X0.00002 Y-61.27361
|
|
||||||
G01 X0.00095 Y-40.19495
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X0.00096 Y-39.96959
|
|
||||||
G01 X0.01481 Y-39.82763
|
|
||||||
G01 X0.04775 Y-39.68887
|
|
||||||
G01 X0.09918 Y-39.55585
|
|
||||||
G01 X0.16817 Y-39.43101
|
|
||||||
G01 X0.25344 Y-39.31671
|
|
||||||
G01 X0.35341 Y-39.21498
|
|
||||||
G01 X0.46626 Y-39.12776
|
|
||||||
G01 X0.59665 Y-39.05154
|
|
||||||
G01 X0.59796 Y-39.05077
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z2.00000 ( retract )
|
|
||||||
|
|
||||||
G00 X54.20002 Y-37.91288 ( rapid move to begin. )
|
|
||||||
G01 Z-4.00000 F50.00000 ( plunge. )
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X54.19509 Y-37.81123
|
|
||||||
G01 X54.18033 Y-37.71054
|
|
||||||
G01 X54.15592 Y-37.61176
|
|
||||||
G01 X54.12204 Y-37.51580
|
|
||||||
G01 X54.07904 Y-37.42357
|
|
||||||
G01 X54.02732 Y-37.33592
|
|
||||||
G01 X53.96735 Y-37.25372
|
|
||||||
G01 X53.89969 Y-37.17768
|
|
||||||
G01 X53.82501 Y-37.10856
|
|
||||||
G01 X53.74398 Y-37.04699
|
|
||||||
G01 X53.65737 Y-36.99358
|
|
||||||
G01 X53.55663 Y-36.94478
|
|
||||||
G01 X53.46100 Y-36.90998
|
|
||||||
G01 X53.36245 Y-36.88458
|
|
||||||
G01 X53.26192 Y-36.86884
|
|
||||||
G01 X53.16032 Y-36.86292
|
|
||||||
G01 X1.30565 Y-36.85680
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-1.29435 Y-36.85649
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-53.14902 Y-36.85037
|
|
||||||
G01 X-53.27092 Y-36.85746
|
|
||||||
G01 X-53.39118 Y-36.87864
|
|
||||||
G01 X-53.50818 Y-36.91367
|
|
||||||
G01 X-53.62029 Y-36.96200
|
|
||||||
G01 X-53.74295 Y-37.03442
|
|
||||||
G01 X-53.85468 Y-37.12276
|
|
||||||
G01 X-53.95344 Y-37.22540
|
|
||||||
G01 X-54.03739 Y-37.34046
|
|
||||||
G01 X-54.10500 Y-37.46584
|
|
||||||
G01 X-54.15501 Y-37.59919
|
|
||||||
G01 X-54.17533 Y-37.67806
|
|
||||||
G01 X-54.18806 Y-37.74816
|
|
||||||
G01 X-54.19908 Y-37.89017
|
|
||||||
G01 X-54.19932 Y-63.69465
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X-54.19935 Y-66.29465
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X-54.19959 Y-92.09913
|
|
||||||
G01 X-54.19250 Y-92.22102
|
|
||||||
G01 X-54.17129 Y-92.34129
|
|
||||||
G01 X-54.13627 Y-92.45826
|
|
||||||
G01 X-54.08791 Y-92.57038
|
|
||||||
G01 X-54.01552 Y-92.69303
|
|
||||||
G01 X-53.97323 Y-92.75039
|
|
||||||
G01 X-53.92029 Y-92.81226
|
|
||||||
G01 X-53.81668 Y-92.91000
|
|
||||||
G01 X-53.70081 Y-92.99280
|
|
||||||
G01 X-53.57480 Y-93.05920
|
|
||||||
G01 X-53.50871 Y-93.08582
|
|
||||||
G01 X-53.43119 Y-93.11068
|
|
||||||
G01 X-53.29169 Y-93.13949
|
|
||||||
G01 X-53.14960 Y-93.14914
|
|
||||||
G01 X-1.30022 Y-93.14935
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X1.29978 Y-93.14936
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X53.14917 Y-93.14957
|
|
||||||
G01 X53.27106 Y-93.14249
|
|
||||||
G01 X53.39133 Y-93.12128
|
|
||||||
G01 X53.50830 Y-93.08625
|
|
||||||
G01 X53.62041 Y-93.03789
|
|
||||||
G01 X53.74307 Y-92.96550
|
|
||||||
G01 X53.85478 Y-92.87716
|
|
||||||
G01 X53.95351 Y-92.77452
|
|
||||||
G01 X54.03746 Y-92.65945
|
|
||||||
G01 X54.07340 Y-92.59791
|
|
||||||
G01 X54.10924 Y-92.52481
|
|
||||||
G01 X54.15793 Y-92.39098
|
|
||||||
G01 X54.18810 Y-92.25176
|
|
||||||
G01 X54.19913 Y-92.10977
|
|
||||||
G01 X54.19955 Y-66.31133
|
|
||||||
G00 Z0.00000
|
|
||||||
G01 X54.19959 Y-63.71133
|
|
||||||
G01 Z-4.00000 F50.00000
|
|
||||||
G01 F400.00000
|
|
||||||
G01 X54.20002 Y-37.91288
|
|
||||||
|
|
||||||
G04 P0 ( dwell for no time -- G64 should not smooth over this point )
|
|
||||||
G00 Z35.000000 ( retract )
|
|
||||||
|
|
||||||
M5 ( Spindle off. )
|
|
||||||
G04 P1.000000
|
|
||||||
M9 ( Coolant off. )
|
|
||||||
M2 ( Program end. )
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 982 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 1006 KiB |
|
Before Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 44 KiB |
376
scripts/macro/SlotCenterlines.FCMacro
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
"""
|
||||||
|
=============================================================================
|
||||||
|
MACRO: CNC Slot Skeletonizer (Centerlines Only)
|
||||||
|
=============================================================================
|
||||||
|
DESCRIPTION:
|
||||||
|
This macro is specifically designed for CAM/CNC routing where the router bit
|
||||||
|
diameter matches the slot width. It reads a DXF-style slot sketch, calculates
|
||||||
|
the mathematical centerlines, and produces a sketch containing ONLY the
|
||||||
|
toolpaths (centerlines).
|
||||||
|
|
||||||
|
WHAT IT DOES:
|
||||||
|
1. Safely duplicates the selected sketch.
|
||||||
|
2. Mathematically calculates true Arcs from faceted DXF micro-segments.
|
||||||
|
3. Calculates intersections for Straight, L-shape, and T-shape junctions.
|
||||||
|
4. Merges collinear centerline segments.
|
||||||
|
5. ADVANCED CAM OPTIMIZATION: Groups connected lines into continuous chains so
|
||||||
|
the tool doesn't lift unnecessarily. Starts the job at the origin (0,0) and
|
||||||
|
takes the shortest rapid paths between cut groups.
|
||||||
|
6. WIPES THE SKETCH COMPLETELY CLEAN of all original geometry.
|
||||||
|
7. Draws ONLY the pure skeleton centerlines.
|
||||||
|
=============================================================================
|
||||||
|
"""
|
||||||
|
|
||||||
|
import FreeCAD as App
|
||||||
|
import FreeCADGui as Gui
|
||||||
|
import Part
|
||||||
|
import math
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PySide6.QtWidgets import QMessageBox
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
from PySide2.QtWidgets import QMessageBox
|
||||||
|
except ImportError:
|
||||||
|
from PySide.QtGui import QMessageBox
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# CONFIGURATION
|
||||||
|
MAX_SEGMENT_LENGTH = 0.5
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
def get_circumcenter(p1, p2, p3):
|
||||||
|
temp = p2.x**2 + p2.y**2
|
||||||
|
bc = (p1.x**2 + p1.y**2 - temp) / 2.0
|
||||||
|
cd = (temp - p3.x**2 - p3.y**2) / 2.0
|
||||||
|
det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y)
|
||||||
|
|
||||||
|
if abs(det) < 1e-6: return None, None
|
||||||
|
|
||||||
|
cx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) / det
|
||||||
|
cy = ((p1.x - p2.x) * cd - (p2.x - p3.x) * bc) / det
|
||||||
|
center = App.Vector(cx, cy, 0)
|
||||||
|
radius = (p1 - center).Length
|
||||||
|
return center, radius
|
||||||
|
|
||||||
|
def prepare_working_sketch():
|
||||||
|
doc = App.ActiveDocument
|
||||||
|
if not doc: return None
|
||||||
|
|
||||||
|
target = None
|
||||||
|
edit_view = Gui.ActiveDocument.getInEdit()
|
||||||
|
if edit_view and edit_view.Object.isDerivedFrom("Sketcher::SketchObject"):
|
||||||
|
target = edit_view.Object
|
||||||
|
Gui.ActiveDocument.resetEdit()
|
||||||
|
|
||||||
|
if not target:
|
||||||
|
sel = Gui.Selection.getSelection()
|
||||||
|
if sel and sel[0].isDerivedFrom("Sketcher::SketchObject"):
|
||||||
|
target = sel[0]
|
||||||
|
|
||||||
|
if not target: return None
|
||||||
|
|
||||||
|
new_sketch = doc.copyObject(target, False)
|
||||||
|
new_sketch.Label = target.Label + "_Toolpath"
|
||||||
|
|
||||||
|
if hasattr(target, "ViewObject") and target.ViewObject:
|
||||||
|
target.ViewObject.Visibility = False
|
||||||
|
if hasattr(new_sketch, "ViewObject") and new_sketch.ViewObject:
|
||||||
|
new_sketch.ViewObject.Visibility = True
|
||||||
|
|
||||||
|
doc.recompute()
|
||||||
|
return new_sketch
|
||||||
|
|
||||||
|
def merge_collinear_lines(lines):
|
||||||
|
merged = True
|
||||||
|
while merged:
|
||||||
|
merged = False
|
||||||
|
for i in range(len(lines)):
|
||||||
|
for j in range(i + 1, len(lines)):
|
||||||
|
l1 = lines[i]
|
||||||
|
l2 = lines[j]
|
||||||
|
|
||||||
|
shared_pt, other1, other2 = None, None, None
|
||||||
|
tol = 1e-3
|
||||||
|
|
||||||
|
if (l1[0] - l2[0]).Length < tol: shared_pt, other1, other2 = l1[0], l1[1], l2[1]
|
||||||
|
elif (l1[0] - l2[1]).Length < tol: shared_pt, other1, other2 = l1[0], l1[1], l2[0]
|
||||||
|
elif (l1[1] - l2[0]).Length < tol: shared_pt, other1, other2 = l1[1], l1[0], l2[1]
|
||||||
|
elif (l1[1] - l2[1]).Length < tol: shared_pt, other1, other2 = l1[1], l1[0], l2[0]
|
||||||
|
|
||||||
|
if shared_pt:
|
||||||
|
v1 = (other1 - shared_pt)
|
||||||
|
v2 = (other2 - shared_pt)
|
||||||
|
if v1.Length > tol and v2.Length > tol:
|
||||||
|
v1.normalize()
|
||||||
|
v2.normalize()
|
||||||
|
if abs(v1.dot(v2) + 1.0) < 1e-4:
|
||||||
|
lines.pop(j)
|
||||||
|
lines.pop(i)
|
||||||
|
lines.append((other1, other2))
|
||||||
|
merged = True
|
||||||
|
break
|
||||||
|
if merged: break
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def optimize_toolpath_order(lines):
|
||||||
|
if not lines: return []
|
||||||
|
|
||||||
|
# Phase 1: Build continuous chains (Polylines)
|
||||||
|
unvisited = lines.copy()
|
||||||
|
chains = []
|
||||||
|
tol = 1e-3
|
||||||
|
|
||||||
|
while unvisited:
|
||||||
|
current_chain = [unvisited.pop(0)]
|
||||||
|
growing = True
|
||||||
|
|
||||||
|
while growing:
|
||||||
|
growing = False
|
||||||
|
chain_start = current_chain[0][0]
|
||||||
|
chain_end = current_chain[-1][1]
|
||||||
|
|
||||||
|
for i, line in enumerate(unvisited):
|
||||||
|
l_start, l_end = line[0], line[1]
|
||||||
|
|
||||||
|
if (l_start - chain_end).Length < tol:
|
||||||
|
current_chain.append(unvisited.pop(i))
|
||||||
|
growing = True; break
|
||||||
|
elif (l_end - chain_end).Length < tol:
|
||||||
|
current_chain.append((l_end, l_start)) # Flip
|
||||||
|
unvisited.pop(i)
|
||||||
|
growing = True; break
|
||||||
|
elif (l_end - chain_start).Length < tol:
|
||||||
|
current_chain.insert(0, unvisited.pop(i))
|
||||||
|
growing = True; break
|
||||||
|
elif (l_start - chain_start).Length < tol:
|
||||||
|
current_chain.insert(0, (l_end, l_start)) # Flip
|
||||||
|
unvisited.pop(i)
|
||||||
|
growing = True; break
|
||||||
|
|
||||||
|
chains.append(current_chain)
|
||||||
|
|
||||||
|
# Phase 2: Traveling Salesperson between chains
|
||||||
|
unvisited_chains = chains.copy()
|
||||||
|
optimized_lines = []
|
||||||
|
|
||||||
|
# Start with the chain closest to global Origin (0,0,0)
|
||||||
|
start_idx = 0
|
||||||
|
best_origin_dist = float('inf')
|
||||||
|
for i, chain in enumerate(unvisited_chains):
|
||||||
|
d1 = chain[0][0].Length
|
||||||
|
d2 = chain[-1][1].Length
|
||||||
|
if min(d1, d2) < best_origin_dist:
|
||||||
|
best_origin_dist = min(d1, d2)
|
||||||
|
start_idx = i
|
||||||
|
|
||||||
|
current_chain = unvisited_chains.pop(start_idx)
|
||||||
|
# Ensure it starts at the point closer to origin
|
||||||
|
if current_chain[-1][1].Length < current_chain[0][0].Length:
|
||||||
|
current_chain.reverse()
|
||||||
|
current_chain = [(l[1], l[0]) for l in current_chain]
|
||||||
|
|
||||||
|
optimized_lines.extend(current_chain)
|
||||||
|
current_pos = current_chain[-1][1] # Position after cutting first chain
|
||||||
|
|
||||||
|
while unvisited_chains:
|
||||||
|
best_dist = float('inf')
|
||||||
|
best_idx = -1
|
||||||
|
reverse_chain = False
|
||||||
|
|
||||||
|
for i, chain in enumerate(unvisited_chains):
|
||||||
|
c_start = chain[0][0]
|
||||||
|
c_end = chain[-1][1]
|
||||||
|
|
||||||
|
dist_to_start = (c_start - current_pos).Length
|
||||||
|
dist_to_end = (c_end - current_pos).Length
|
||||||
|
|
||||||
|
if dist_to_start < best_dist:
|
||||||
|
best_dist = dist_to_start
|
||||||
|
best_idx = i
|
||||||
|
reverse_chain = False
|
||||||
|
|
||||||
|
if dist_to_end < best_dist:
|
||||||
|
best_dist = dist_to_end
|
||||||
|
best_idx = i
|
||||||
|
reverse_chain = True
|
||||||
|
|
||||||
|
next_chain = unvisited_chains.pop(best_idx)
|
||||||
|
|
||||||
|
if reverse_chain:
|
||||||
|
next_chain.reverse()
|
||||||
|
next_chain = [(l[1], l[0]) for l in next_chain]
|
||||||
|
|
||||||
|
optimized_lines.extend(next_chain)
|
||||||
|
current_pos = next_chain[-1][1]
|
||||||
|
|
||||||
|
return optimized_lines
|
||||||
|
|
||||||
|
def show_message(title, message):
|
||||||
|
msg = QMessageBox()
|
||||||
|
msg.setIcon(QMessageBox.Information)
|
||||||
|
msg.setWindowTitle(title)
|
||||||
|
msg.setText(message)
|
||||||
|
try:
|
||||||
|
msg.exec()
|
||||||
|
except AttributeError:
|
||||||
|
msg.exec_()
|
||||||
|
|
||||||
|
def process_sketch():
|
||||||
|
sketch = prepare_working_sketch()
|
||||||
|
if not sketch:
|
||||||
|
App.Console.PrintError("Could not find a sketch. Select one in the tree view and run.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
geo = sketch.Geometry
|
||||||
|
|
||||||
|
# --- STEP 1: IDENTIFY MICRO-SEGMENTS TO INFER ARC DATA ---
|
||||||
|
graph = {}
|
||||||
|
pt_dict = {}
|
||||||
|
def get_pt_key(pt): return (round(pt.x, 3), round(pt.y, 3))
|
||||||
|
|
||||||
|
for i, g in enumerate(geo):
|
||||||
|
if isinstance(g, Part.LineSegment) and not sketch.GeometryFacadeList[i].Construction:
|
||||||
|
if (g.EndPoint - g.StartPoint).Length < MAX_SEGMENT_LENGTH:
|
||||||
|
k1 = get_pt_key(g.StartPoint)
|
||||||
|
k2 = get_pt_key(g.EndPoint)
|
||||||
|
|
||||||
|
if k1 not in graph: graph[k1] = []
|
||||||
|
if k2 not in graph: graph[k2] = []
|
||||||
|
|
||||||
|
graph[k1].append((k2, i))
|
||||||
|
graph[k2].append((k1, i))
|
||||||
|
|
||||||
|
pt_dict[k1] = g.StartPoint
|
||||||
|
pt_dict[k2] = g.EndPoint
|
||||||
|
|
||||||
|
paths = []
|
||||||
|
visited_edges = set()
|
||||||
|
|
||||||
|
for node, edges in graph.items():
|
||||||
|
if len(edges) == 1:
|
||||||
|
first_edge = edges[0][1]
|
||||||
|
if first_edge in visited_edges: continue
|
||||||
|
|
||||||
|
path_nodes = [node]
|
||||||
|
curr = node; prev = None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
neighbors = graph[curr]
|
||||||
|
next_node = None; next_idx = None
|
||||||
|
for n, idx in neighbors:
|
||||||
|
if n != prev:
|
||||||
|
next_node = n; next_idx = idx
|
||||||
|
break
|
||||||
|
if next_node is None: break
|
||||||
|
path_nodes.append(next_node)
|
||||||
|
visited_edges.add(next_idx)
|
||||||
|
if len(graph[next_node]) > 2: break
|
||||||
|
prev = curr; curr = next_node
|
||||||
|
|
||||||
|
if len(path_nodes) >= 3:
|
||||||
|
paths.append(path_nodes)
|
||||||
|
|
||||||
|
# --- STEP 2: CALCULATE TRUE ARC CENTERS & DIRECTIONS ---
|
||||||
|
arc_data = []
|
||||||
|
|
||||||
|
for path_nodes in paths:
|
||||||
|
p1 = pt_dict[path_nodes[0]]
|
||||||
|
p2 = pt_dict[path_nodes[len(path_nodes)//2]]
|
||||||
|
p3 = pt_dict[path_nodes[-1]]
|
||||||
|
|
||||||
|
center, radius = get_circumcenter(p1, p2, p3)
|
||||||
|
if center:
|
||||||
|
v1 = p1 - center
|
||||||
|
v3 = p3 - center
|
||||||
|
if v1.Length > 1e-4 and v3.Length > 1e-4:
|
||||||
|
dot = max(-1.0, min(1.0, v1.dot(v3) / (v1.Length * v3.Length)))
|
||||||
|
angle = math.acos(dot)
|
||||||
|
if angle > 2.0:
|
||||||
|
chord = p3 - p1
|
||||||
|
perp = App.Vector(-chord.y, chord.x, 0)
|
||||||
|
if perp.Length > 1e-6:
|
||||||
|
perp.normalize()
|
||||||
|
if perp.dot(center - p2) < 0: perp = -perp
|
||||||
|
arc_data.append((center, perp))
|
||||||
|
|
||||||
|
# Existing native Arcs
|
||||||
|
for i, g in enumerate(geo):
|
||||||
|
if isinstance(g, Part.ArcOfCircle) and not sketch.GeometryFacadeList[i].Construction:
|
||||||
|
p1 = g.StartPoint
|
||||||
|
p3 = g.EndPoint
|
||||||
|
center = g.Center
|
||||||
|
v1 = p1 - center
|
||||||
|
v3 = p3 - center
|
||||||
|
if v1.Length > 1e-4 and v3.Length > 1e-4:
|
||||||
|
dot = max(-1.0, min(1.0, v1.dot(v3) / (v1.Length * v3.Length)))
|
||||||
|
angle = math.acos(dot)
|
||||||
|
if angle > 2.0:
|
||||||
|
chord = p3 - p1
|
||||||
|
perp = App.Vector(-chord.y, chord.x, 0)
|
||||||
|
if perp.Length > 1e-6:
|
||||||
|
perp.normalize()
|
||||||
|
mid_u = (g.FirstParameter + g.LastParameter) / 2.0
|
||||||
|
p2 = g.value(mid_u)
|
||||||
|
if perp.dot(center - p2) < 0: perp = -perp
|
||||||
|
arc_data.append((center, perp))
|
||||||
|
|
||||||
|
# --- STEP 3: WIPE THE SKETCH CLEAN ---
|
||||||
|
for i in range(sketch.ConstraintCount - 1, -1, -1):
|
||||||
|
sketch.delConstraint(i)
|
||||||
|
for i in range(sketch.GeometryCount - 1, -1, -1):
|
||||||
|
sketch.delGeometry(i)
|
||||||
|
|
||||||
|
# --- STEP 4: CALCULATE TOOLPATHS ---
|
||||||
|
raw_lines = []
|
||||||
|
|
||||||
|
for i, (c1, dir1) in enumerate(arc_data):
|
||||||
|
min_t = float('inf')
|
||||||
|
best_stop = None
|
||||||
|
|
||||||
|
for j, (c2, dir2) in enumerate(arc_data):
|
||||||
|
if i == j: continue
|
||||||
|
cross = dir1.x * dir2.y - dir1.y * dir2.x
|
||||||
|
|
||||||
|
if abs(cross) < 1e-4:
|
||||||
|
vec = c2 - c1
|
||||||
|
dist_cross = vec.x * dir1.y - vec.y * dir1.x
|
||||||
|
if abs(dist_cross) < 1e-2:
|
||||||
|
t1 = vec.dot(dir1)
|
||||||
|
t2 = (-vec).dot(dir2)
|
||||||
|
if t1 > 1e-2 and t2 > 1e-2:
|
||||||
|
if t1 < min_t:
|
||||||
|
min_t = t1
|
||||||
|
best_stop = c2
|
||||||
|
else:
|
||||||
|
dx = c2.x - c1.x
|
||||||
|
dy = c2.y - c1.y
|
||||||
|
t1 = (dx * dir2.y - dy * dir2.x) / cross
|
||||||
|
t2 = (dx * dir1.y - dy * dir1.x) / cross
|
||||||
|
if t1 > 1e-2 and t2 > -1e-2:
|
||||||
|
if t1 < min_t:
|
||||||
|
min_t = t1
|
||||||
|
best_stop = c1 + dir1 * t1
|
||||||
|
|
||||||
|
if best_stop is not None:
|
||||||
|
if (c1 - best_stop).Length > 1e-3:
|
||||||
|
pts = sorted([(round(c1.x, 3), round(c1.y, 3)), (round(best_stop.x, 3), round(best_stop.y, 3))])
|
||||||
|
pA = App.Vector(pts[0][0], pts[0][1], 0)
|
||||||
|
pB = App.Vector(pts[1][0], pts[1][1], 0)
|
||||||
|
if not any((l[0]-pA).Length < 1e-3 and (l[1]-pB).Length < 1e-3 for l in raw_lines):
|
||||||
|
raw_lines.append((pA, pB))
|
||||||
|
|
||||||
|
# --- STEP 5: MERGE AND OPTIMIZE PATHS FOR CNC ---
|
||||||
|
merged_lines = merge_collinear_lines(raw_lines)
|
||||||
|
optimized_lines = optimize_toolpath_order(merged_lines)
|
||||||
|
|
||||||
|
# Draw the final optimized lines sequentially
|
||||||
|
for pA, pB in optimized_lines:
|
||||||
|
sketch.addGeometry(Part.LineSegment(pA, pB), False)
|
||||||
|
|
||||||
|
App.ActiveDocument.recompute()
|
||||||
|
App.Console.PrintMessage(f"Skeletonizer successful: Created '{sketch.Label}'.\n")
|
||||||
|
show_message("CAM Toolpath Complete", f"Successfully generated continuous, optimized CNC toolpaths in:\n\n{sketch.Label}")
|
||||||
|
|
||||||
|
# Run it
|
||||||
|
process_sketch()
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
#back=gerbers/<Project Name>-B_Cu.gbr
|
front=gerbers/Flow_Controller_Panel-Front.gtl
|
||||||
#drill=gerbers/<Project Name>.drl
|
back=gerbers/Flow_Controller_Panel-Back.gbl
|
||||||
#outline=gerbers/<Project Name>-Edge_Cuts.gm1
|
drill=gerbers/Flow_Controller_Panel.drl
|
||||||
|
# Use the 'User-Eco1' layer instead as it contains panelized boards outlines only.
|
||||||
|
outline=gerbers/Flow_Controller_Panel-User-Eco1.gbr
|
||||||
|
# Do not use the 'Edge_Cuts' layer as it contains also the panel outline.
|
||||||
|
#outline=gerbers/Flow_Controller_Panel-Edge_Cuts.gm1
|
||||||
|
|
||||||
# Generic
|
# Generic
|
||||||
metric=true # use metric units for parameters
|
metric=true # use metric units for parameters
|
||||||
@@ -15,14 +19,15 @@ output-dir=gcode
|
|||||||
# This will allow you to probe the fixed jaw of the vise for (0,0) on the CNC.
|
# This will allow you to probe the fixed jaw of the vise for (0,0) on the CNC.
|
||||||
|
|
||||||
# For two-sided boards, the PCB needs to be flipped along the axis x=VALUE
|
# For two-sided boards, the PCB needs to be flipped along the axis x=VALUE
|
||||||
mirror-axis=50 # set this to half of your board width
|
mirror-axis=80 # set this to half of your board width
|
||||||
|
|
||||||
# Drilling
|
# Drilling
|
||||||
zdrill=-2.2 # drilling depth
|
zdrill=-2.2 # drilling depth
|
||||||
drill-feed=500 # Vertical mm/min feed
|
drill-feed=500 # Vertical mm/min feed
|
||||||
drill-speed=24000 # Spindle RPM
|
drill-speed=24000 # Spindle RPM
|
||||||
onedrill=true # Use a single drill for all holes
|
#onedrill=true # Use a single drill for all holes
|
||||||
nog81=true # replace G81 with G0+G1 (no G81 in GRBL)
|
nog81=true # replace G81 with G0+G1 (no G81 in GRBL)
|
||||||
|
drill-side=back
|
||||||
|
|
||||||
# Milling
|
# Milling
|
||||||
zwork=-0.1 # V-bit plunge depth
|
zwork=-0.1 # V-bit plunge depth
|
||||||
@@ -45,6 +50,6 @@ cut-speed=24000
|
|||||||
cut-side=back
|
cut-side=back
|
||||||
|
|
||||||
# Tabs
|
# Tabs
|
||||||
bridgesnum=4 # Total 4 tabs
|
#bridgesnum=4 # Total 4 tabs
|
||||||
bridges=0.5 # Tab width 0.5 mm
|
#bridges=0.5 # Tab width 0.5 mm
|
||||||
zbridges=0 # bridges height (default to zsafe)
|
#zbridges=0 # bridges height (default to zsafe)
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
# move_to_origin.py
|
|
||||||
from shapely.affinity import translate
|
|
||||||
|
|
||||||
def kikitPostprocess(panel, args):
|
|
||||||
import pcbnew
|
|
||||||
|
|
||||||
# Get bounds from the substrate (Shapely polygon, units in nm)
|
|
||||||
bounds = panel.boardSubstrate.substrates.bounds # (minx, miny, maxx, maxy)
|
|
||||||
minx = bounds[0]
|
|
||||||
miny = bounds[1]
|
|
||||||
|
|
||||||
dx = int(-minx)
|
|
||||||
dy = int(-miny)
|
|
||||||
offset = pcbnew.VECTOR2I(dx, dy)
|
|
||||||
|
|
||||||
# Move all board items (footprints, tracks, drawings, zones)
|
|
||||||
for fp in panel.board.GetFootprints():
|
|
||||||
fp.Move(offset)
|
|
||||||
for track in panel.board.GetTracks():
|
|
||||||
track.Move(offset)
|
|
||||||
for drawing in panel.board.GetDrawings():
|
|
||||||
drawing.Move(offset)
|
|
||||||
for zone in panel.board.Zones():
|
|
||||||
zone.Move(offset)
|
|
||||||
|
|
||||||
# Translate the substrate geometry (this becomes the Edge.Cuts on save)
|
|
||||||
dx_nm = -bounds[0]
|
|
||||||
dy_nm = -bounds[1]
|
|
||||||
panel.boardSubstrate.substrates = translate(
|
|
||||||
panel.boardSubstrate.substrates,
|
|
||||||
xoff=dx_nm,
|
|
||||||
yoff=dy_nm
|
|
||||||
)
|
|
||||||
@@ -60,11 +60,11 @@
|
|||||||
"reconstructarcs": false,
|
"reconstructarcs": false,
|
||||||
"millradius": "1mm",
|
"millradius": "1mm",
|
||||||
"millradiusouter": "0mm",
|
"millradiusouter": "0mm",
|
||||||
"script": "",
|
"script": "cleanup.py",
|
||||||
"scriptarg": "",
|
"scriptarg": "",
|
||||||
"origin": "tl",
|
"origin": "tl",
|
||||||
"refillzones": false,
|
"refillzones": false,
|
||||||
"dimensions": false,
|
"dimensions": true,
|
||||||
"edgewidth": "0.1mm"
|
"edgewidth": "0.1mm"
|
||||||
},
|
},
|
||||||
"page": {
|
"page": {
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
"width": "1000mm",
|
"width": "1000mm",
|
||||||
"height": "1000mm"
|
"height": "1000mm"
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"type": "none",
|
"type": "none",
|
||||||
"drawPartitionLines": false,
|
"drawPartitionLines": false,
|
||||||
"drawBackboneLines": false,
|
"drawBackboneLines": false,
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
%TF.GenerationSoftware,KiCad,Pcbnew,9.0.9-9.0.9~ubuntu24.04.1*%
|
|
||||||
%TF.CreationDate,2026-05-16T13:37:08+02:00*%
|
|
||||||
%TF.ProjectId,Flow_Controller,466c6f77-5f43-46f6-9e74-726f6c6c6572,rev?*%
|
|
||||||
%TF.SameCoordinates,Original*%
|
|
||||||
%TF.FileFunction,Copper,L2,Bot*%
|
|
||||||
%TF.FilePolarity,Positive*%
|
|
||||||
%FSLAX46Y46*%
|
|
||||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
|
||||||
G04 Created by KiCad (PCBNEW 9.0.9-9.0.9~ubuntu24.04.1) date 2026-05-16 13:37:08*
|
|
||||||
%MOMM*%
|
|
||||||
%LPD*%
|
|
||||||
G01*
|
|
||||||
G04 APERTURE LIST*
|
|
||||||
G04 Aperture macros list*
|
|
||||||
%AMRoundRect*
|
|
||||||
0 Rectangle with rounded corners*
|
|
||||||
0 $1 Rounding radius*
|
|
||||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
|
||||||
0 Add a 4 corners polygon primitive as box body*
|
|
||||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
|
||||||
0 Add four circle primitives for the rounded corners*
|
|
||||||
1,1,$1+$1,$2,$3*
|
|
||||||
1,1,$1+$1,$4,$5*
|
|
||||||
1,1,$1+$1,$6,$7*
|
|
||||||
1,1,$1+$1,$8,$9*
|
|
||||||
0 Add four rect primitives between the rounded corners*
|
|
||||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
|
||||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
|
||||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
|
||||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
|
||||||
G04 Aperture macros list end*
|
|
||||||
%TA.AperFunction,ComponentPad*%
|
|
||||||
%ADD10RoundRect,0.250000X0.725000X-0.600000X0.725000X0.600000X-0.725000X0.600000X-0.725000X-0.600000X0*%
|
|
||||||
%TD*%
|
|
||||||
%TA.AperFunction,ComponentPad*%
|
|
||||||
%ADD11O,1.950000X1.700000*%
|
|
||||||
%TD*%
|
|
||||||
%TA.AperFunction,ComponentPad*%
|
|
||||||
%ADD12R,1.700000X1.700000*%
|
|
||||||
%TD*%
|
|
||||||
%TA.AperFunction,ComponentPad*%
|
|
||||||
%ADD13C,1.700000*%
|
|
||||||
%TD*%
|
|
||||||
%TA.AperFunction,ViaPad*%
|
|
||||||
%ADD14C,1.700000*%
|
|
||||||
%TD*%
|
|
||||||
%TA.AperFunction,Conductor*%
|
|
||||||
%ADD15C,0.400000*%
|
|
||||||
%TD*%
|
|
||||||
G04 APERTURE END LIST*
|
|
||||||
D10*
|
|
||||||
%TO.P,J4,1,Pin_1*%
|
|
||||||
%TO.N,+5V*%
|
|
||||||
X46000000Y-17526000D03*
|
|
||||||
D11*
|
|
||||||
%TO.P,J4,2,Pin_2*%
|
|
||||||
%TO.N,GND*%
|
|
||||||
X46000000Y-15026000D03*
|
|
||||||
%TO.P,J4,3,Pin_3*%
|
|
||||||
%TO.N,/ALARM _CNC*%
|
|
||||||
X46000000Y-12526000D03*
|
|
||||||
%TD*%
|
|
||||||
D12*
|
|
||||||
%TO.P,J1,1,Pin_1*%
|
|
||||||
%TO.N,GND*%
|
|
||||||
X18415000Y-45000000D03*
|
|
||||||
D13*
|
|
||||||
%TO.P,J1,2,Pin_2*%
|
|
||||||
%TO.N,+5V*%
|
|
||||||
X18415000Y-42460000D03*
|
|
||||||
%TO.P,J1,3,Pin_3*%
|
|
||||||
%TO.N,/SWIO*%
|
|
||||||
X18415000Y-39920000D03*
|
|
||||||
%TD*%
|
|
||||||
D12*
|
|
||||||
%TO.P,J3,1,BUTTON_UP*%
|
|
||||||
%TO.N,Net-(J3-BUTTON_UP)*%
|
|
||||||
X7366000Y-33900000D03*
|
|
||||||
D13*
|
|
||||||
%TO.P,J3,2,BUTTON_DOWN*%
|
|
||||||
%TO.N,/BUTTON_ADC*%
|
|
||||||
X7366000Y-31360000D03*
|
|
||||||
%TO.P,J3,3,BUTTON_#*%
|
|
||||||
%TO.N,unconnected-(J3-BUTTON_#-Pad3)*%
|
|
||||||
X7366000Y-28820000D03*
|
|
||||||
%TO.P,J3,4,BUTTON_\u002A*%
|
|
||||||
%TO.N,unconnected-(J3-BUTTON_\u002A-Pad4)*%
|
|
||||||
X7366000Y-26280000D03*
|
|
||||||
%TO.P,J3,5,I2C_SDA*%
|
|
||||||
%TO.N,/I2C_SDA*%
|
|
||||||
X7366000Y-23740000D03*
|
|
||||||
%TO.P,J3,6,I2C_SCL*%
|
|
||||||
%TO.N,/I2C_SCL*%
|
|
||||||
X7366000Y-21200000D03*
|
|
||||||
%TO.P,J3,7,VCC*%
|
|
||||||
%TO.N,+5V*%
|
|
||||||
X7366000Y-18660000D03*
|
|
||||||
%TO.P,J3,8,GND*%
|
|
||||||
%TO.N,GND*%
|
|
||||||
X7366000Y-16120000D03*
|
|
||||||
%TD*%
|
|
||||||
D10*
|
|
||||||
%TO.P,J2,1,Pin_1*%
|
|
||||||
%TO.N,+5V*%
|
|
||||||
X30000000Y-44918000D03*
|
|
||||||
D11*
|
|
||||||
%TO.P,J2,2,Pin_2*%
|
|
||||||
%TO.N,GND*%
|
|
||||||
X30000000Y-42418000D03*
|
|
||||||
%TO.P,J2,3,Pin_3*%
|
|
||||||
%TO.N,/RAW_SENSOR*%
|
|
||||||
X30000000Y-39918000D03*
|
|
||||||
%TD*%
|
|
||||||
D14*
|
|
||||||
%TO.N,/I2C_SCL*%
|
|
||||||
X14605000Y-21590000D03*
|
|
||||||
X14732000Y-25400000D03*
|
|
||||||
%TD*%
|
|
||||||
D15*
|
|
||||||
%TO.N,/I2C_SCL*%
|
|
||||||
X14605000Y-21082000D02*
|
|
||||||
X14605000Y-25019000D01*
|
|
||||||
%TD*%
|
|
||||||
M02*
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
%TF.GenerationSoftware,KiCad,Pcbnew,9.0.9-9.0.9~ubuntu24.04.1*%
|
|
||||||
%TF.CreationDate,2026-05-16T13:37:09+02:00*%
|
|
||||||
%TF.ProjectId,Flow_Controller,466c6f77-5f43-46f6-9e74-726f6c6c6572,rev?*%
|
|
||||||
%TF.SameCoordinates,Original*%
|
|
||||||
%TF.FileFunction,Profile,NP*%
|
|
||||||
%FSLAX46Y46*%
|
|
||||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
|
||||||
G04 Created by KiCad (PCBNEW 9.0.9-9.0.9~ubuntu24.04.1) date 2026-05-16 13:37:09*
|
|
||||||
%MOMM*%
|
|
||||||
%LPD*%
|
|
||||||
G01*
|
|
||||||
G04 APERTURE LIST*
|
|
||||||
%TA.AperFunction,Profile*%
|
|
||||||
%ADD10C,0.050000*%
|
|
||||||
%TD*%
|
|
||||||
G04 APERTURE END LIST*
|
|
||||||
D10*
|
|
||||||
X0Y0D02*
|
|
||||||
X50000000Y0D01*
|
|
||||||
X50000000Y-50000000D01*
|
|
||||||
X0Y-50000000D01*
|
|
||||||
X0Y0D01*
|
|
||||||
M02*
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
{
|
|
||||||
"Header": {
|
|
||||||
"GenerationSoftware": {
|
|
||||||
"Vendor": "KiCad",
|
|
||||||
"Application": "Pcbnew",
|
|
||||||
"Version": "9.0.9-9.0.9~ubuntu24.04.1"
|
|
||||||
},
|
|
||||||
"CreationDate": "2026-05-16T13:37:09+02:00"
|
|
||||||
},
|
|
||||||
"GeneralSpecs": {
|
|
||||||
"ProjectId": {
|
|
||||||
"Name": "Flow_Controller",
|
|
||||||
"GUID": "466c6f77-5f43-46f6-9e74-726f6c6c6572",
|
|
||||||
"Revision": "rev?"
|
|
||||||
},
|
|
||||||
"Size": {
|
|
||||||
"X": 50.05,
|
|
||||||
"Y": 50.05
|
|
||||||
},
|
|
||||||
"LayerNumber": 2,
|
|
||||||
"BoardThickness": 1.6002,
|
|
||||||
"Finish": "None"
|
|
||||||
},
|
|
||||||
"DesignRules": [
|
|
||||||
{
|
|
||||||
"Layers": "Outer",
|
|
||||||
"PadToPad": 0.127,
|
|
||||||
"PadToTrack": 0.127,
|
|
||||||
"TrackToTrack": 0.127,
|
|
||||||
"MinLineWidth": 0.4,
|
|
||||||
"TrackToRegion": 0.5,
|
|
||||||
"RegionToRegion": 0.5
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"FilesAttributes": [
|
|
||||||
{
|
|
||||||
"Path": "Flow_Controller-Edge_Cuts.gm1",
|
|
||||||
"FileFunction": "Profile",
|
|
||||||
"FilePolarity": "Positive"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"MaterialStackup": [
|
|
||||||
{
|
|
||||||
"Type": "Legend",
|
|
||||||
"Name": "Top Silk Screen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderPaste",
|
|
||||||
"Name": "Top Solder Paste"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderMask",
|
|
||||||
"Thickness": 0.01,
|
|
||||||
"Name": "Top Solder Mask"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Copper",
|
|
||||||
"Thickness": 0.035,
|
|
||||||
"Name": "Front"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Dielectric",
|
|
||||||
"Thickness": 1.5102,
|
|
||||||
"Material": "FR4",
|
|
||||||
"Name": "Front/Back",
|
|
||||||
"Notes": "Type: dielectric layer 1 (from Front to Back)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Copper",
|
|
||||||
"Thickness": 0.035,
|
|
||||||
"Name": "Back"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderMask",
|
|
||||||
"Thickness": 0.01,
|
|
||||||
"Name": "Bottom Solder Mask"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderPaste",
|
|
||||||
"Name": "Bottom Solder Paste"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Legend",
|
|
||||||
"Name": "Bottom Silk Screen"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
M48
|
|
||||||
; DRILL file {KiCad 9.0.9-9.0.9~ubuntu24.04.1} date 2026-05-16T13:37:09+0200
|
|
||||||
; FORMAT={-:-/ absolute / metric / decimal}
|
|
||||||
; #@! TF.CreationDate,2026-05-16T13:37:09+02:00
|
|
||||||
; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.9-9.0.9~ubuntu24.04.1
|
|
||||||
; #@! TF.FileFunction,MixedPlating,1,2
|
|
||||||
FMAT,2
|
|
||||||
METRIC
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
|
||||||
T1C0.950
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ViaDrill
|
|
||||||
T2C1.000
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
|
||||||
T3C1.000
|
|
||||||
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
|
||||||
T4C3.200
|
|
||||||
%
|
|
||||||
G90
|
|
||||||
G05
|
|
||||||
T1
|
|
||||||
X30.0Y-39.918
|
|
||||||
X30.0Y-42.418
|
|
||||||
X30.0Y-44.918
|
|
||||||
X46.0Y-12.526
|
|
||||||
X46.0Y-15.026
|
|
||||||
X46.0Y-17.526
|
|
||||||
T2
|
|
||||||
X14.605Y-21.59
|
|
||||||
X14.732Y-25.4
|
|
||||||
T3
|
|
||||||
X7.366Y-16.12
|
|
||||||
X7.366Y-18.66
|
|
||||||
X7.366Y-21.2
|
|
||||||
X7.366Y-23.74
|
|
||||||
X7.366Y-26.28
|
|
||||||
X7.366Y-28.82
|
|
||||||
X7.366Y-31.36
|
|
||||||
X7.366Y-33.9
|
|
||||||
X18.415Y-39.92
|
|
||||||
X18.415Y-42.46
|
|
||||||
X18.415Y-45.0
|
|
||||||
T4
|
|
||||||
X4.6Y-4.6
|
|
||||||
X4.6Y-45.4
|
|
||||||
X45.4Y-4.6
|
|
||||||
X45.4Y-45.4
|
|
||||||
M30
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
{
|
|
||||||
"Header": {
|
|
||||||
"GenerationSoftware": {
|
|
||||||
"Vendor": "KiCad",
|
|
||||||
"Application": "Pcbnew",
|
|
||||||
"Version": "9.0.9-9.0.9~ubuntu24.04.1"
|
|
||||||
},
|
|
||||||
"CreationDate": "2026-05-20T19:29:47+02:00"
|
|
||||||
},
|
|
||||||
"GeneralSpecs": {
|
|
||||||
"ProjectId": {
|
|
||||||
"Name": "Flow_Controller_Panel",
|
|
||||||
"GUID": "466c6f77-5f43-46f6-9e74-726f6c6c6572",
|
|
||||||
"Revision": "rev?"
|
|
||||||
},
|
|
||||||
"Size": {
|
|
||||||
"X": 106.3996,
|
|
||||||
"Y": 54.2993
|
|
||||||
},
|
|
||||||
"LayerNumber": 2,
|
|
||||||
"BoardThickness": 1.6002,
|
|
||||||
"Finish": "None"
|
|
||||||
},
|
|
||||||
"DesignRules": [
|
|
||||||
{
|
|
||||||
"Layers": "Outer",
|
|
||||||
"PadToPad": 0.127,
|
|
||||||
"PadToTrack": 0.127,
|
|
||||||
"TrackToTrack": 0.127,
|
|
||||||
"MinLineWidth": 0.4,
|
|
||||||
"TrackToRegion": 0.5,
|
|
||||||
"RegionToRegion": 0.5
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"FilesAttributes": [
|
|
||||||
{
|
|
||||||
"Path": "Flow_Controller_Panel-Edge_Cuts.gm1",
|
|
||||||
"FileFunction": "Profile",
|
|
||||||
"FilePolarity": "Positive"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"MaterialStackup": [
|
|
||||||
{
|
|
||||||
"Type": "Legend",
|
|
||||||
"Name": "Top Silk Screen"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderPaste",
|
|
||||||
"Name": "Top Solder Paste"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderMask",
|
|
||||||
"Thickness": 0.01,
|
|
||||||
"Name": "Top Solder Mask"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Copper",
|
|
||||||
"Thickness": 0.035,
|
|
||||||
"Name": "Front"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Dielectric",
|
|
||||||
"Thickness": 1.5102,
|
|
||||||
"Material": "FR4",
|
|
||||||
"Name": "Front/Back",
|
|
||||||
"Notes": "Type: dielectric layer 1 (from Front to Back)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Copper",
|
|
||||||
"Thickness": 0.035,
|
|
||||||
"Name": "Back"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderMask",
|
|
||||||
"Thickness": 0.01,
|
|
||||||
"Name": "Bottom Solder Mask"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "SolderPaste",
|
|
||||||
"Name": "Bottom Solder Paste"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Type": "Legend",
|
|
||||||
"Name": "Bottom Silk Screen"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
M48
|
|
||||||
; DRILL file {KiCad 9.0.9-9.0.9~ubuntu24.04.1} date 2026-05-20T19:29:47+0200
|
|
||||||
; FORMAT={-:-/ absolute / metric / decimal}
|
|
||||||
; #@! TF.CreationDate,2026-05-20T19:29:47+02:00
|
|
||||||
; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.9-9.0.9~ubuntu24.04.1
|
|
||||||
; #@! TF.FileFunction,MixedPlating,1,2
|
|
||||||
FMAT,2
|
|
||||||
METRIC
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
|
||||||
T1C0.950
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ViaDrill
|
|
||||||
T2C1.000
|
|
||||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
|
||||||
T3C1.000
|
|
||||||
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
|
||||||
T4C0.500
|
|
||||||
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
|
||||||
T5C2.150
|
|
||||||
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
|
||||||
T6C2.700
|
|
||||||
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
|
||||||
T7C3.172
|
|
||||||
%
|
|
||||||
G90
|
|
||||||
G05
|
|
||||||
T1
|
|
||||||
X93.5Y-53.0
|
|
||||||
X93.5Y-55.5
|
|
||||||
X93.5Y-58.0
|
|
||||||
X93.55Y-73.85
|
|
||||||
X93.55Y-76.35
|
|
||||||
X93.55Y-78.85
|
|
||||||
X145.6Y-53.0
|
|
||||||
X145.6Y-55.5
|
|
||||||
X145.6Y-58.0
|
|
||||||
X145.65Y-73.85
|
|
||||||
X145.65Y-76.35
|
|
||||||
X145.65Y-78.85
|
|
||||||
T2
|
|
||||||
X66.7Y-65.675
|
|
||||||
X66.8Y-69.425
|
|
||||||
X118.8Y-65.675
|
|
||||||
X118.9Y-69.425
|
|
||||||
T3
|
|
||||||
X56.316Y-56.12
|
|
||||||
X56.316Y-58.66
|
|
||||||
X56.316Y-61.2
|
|
||||||
X56.316Y-63.74
|
|
||||||
X56.316Y-66.28
|
|
||||||
X56.316Y-68.82
|
|
||||||
X56.316Y-71.36
|
|
||||||
X56.316Y-73.9
|
|
||||||
X85.87Y-45.55
|
|
||||||
X88.41Y-45.55
|
|
||||||
X90.95Y-45.55
|
|
||||||
X108.416Y-56.12
|
|
||||||
X108.416Y-58.66
|
|
||||||
X108.416Y-61.2
|
|
||||||
X108.416Y-63.74
|
|
||||||
X108.416Y-66.28
|
|
||||||
X108.416Y-68.82
|
|
||||||
X108.416Y-71.36
|
|
||||||
X108.416Y-73.9
|
|
||||||
X137.97Y-45.55
|
|
||||||
X140.51Y-45.55
|
|
||||||
X143.05Y-45.55
|
|
||||||
T4
|
|
||||||
X49.15Y-62.0
|
|
||||||
X49.15Y-63.0
|
|
||||||
X49.15Y-64.0
|
|
||||||
X49.15Y-65.0
|
|
||||||
X49.15Y-66.0
|
|
||||||
X49.15Y-67.0
|
|
||||||
X49.15Y-68.0
|
|
||||||
X70.95Y-40.2
|
|
||||||
X70.95Y-89.8
|
|
||||||
X71.95Y-40.2
|
|
||||||
X71.95Y-89.8
|
|
||||||
X72.95Y-40.2
|
|
||||||
X72.95Y-89.8
|
|
||||||
X73.95Y-40.2
|
|
||||||
X73.95Y-89.8
|
|
||||||
X74.95Y-40.2
|
|
||||||
X74.95Y-89.8
|
|
||||||
X75.95Y-40.2
|
|
||||||
X75.95Y-89.8
|
|
||||||
X76.95Y-40.2
|
|
||||||
X76.95Y-89.8
|
|
||||||
X98.75Y-62.0
|
|
||||||
X98.75Y-63.0
|
|
||||||
X98.75Y-64.0
|
|
||||||
X98.75Y-65.0
|
|
||||||
X98.75Y-66.0
|
|
||||||
X98.75Y-67.0
|
|
||||||
X98.75Y-68.0
|
|
||||||
X101.25Y-62.0
|
|
||||||
X101.25Y-63.0
|
|
||||||
X101.25Y-64.0
|
|
||||||
X101.25Y-65.0
|
|
||||||
X101.25Y-66.0
|
|
||||||
X101.25Y-67.0
|
|
||||||
X101.25Y-68.0
|
|
||||||
X123.05Y-40.2
|
|
||||||
X123.05Y-89.8
|
|
||||||
X124.05Y-40.2
|
|
||||||
X124.05Y-89.8
|
|
||||||
X125.05Y-40.2
|
|
||||||
X125.05Y-89.8
|
|
||||||
X126.05Y-40.2
|
|
||||||
X126.05Y-89.8
|
|
||||||
X127.05Y-40.2
|
|
||||||
X127.05Y-89.8
|
|
||||||
X128.05Y-40.2
|
|
||||||
X128.05Y-89.8
|
|
||||||
X129.05Y-40.2
|
|
||||||
X129.05Y-89.8
|
|
||||||
X150.85Y-62.0
|
|
||||||
X150.85Y-63.0
|
|
||||||
X150.85Y-64.0
|
|
||||||
X150.85Y-65.0
|
|
||||||
X150.85Y-66.0
|
|
||||||
X150.85Y-67.0
|
|
||||||
X150.85Y-68.0
|
|
||||||
T5
|
|
||||||
X56.748Y-45.179
|
|
||||||
X56.824Y-84.847
|
|
||||||
X79.633Y-45.147
|
|
||||||
X79.684Y-84.822
|
|
||||||
X108.848Y-45.179
|
|
||||||
X108.924Y-84.847
|
|
||||||
X131.733Y-45.147
|
|
||||||
X131.784Y-84.822
|
|
||||||
T6
|
|
||||||
X51.95Y-43.0
|
|
||||||
X51.95Y-87.0
|
|
||||||
X95.95Y-43.0
|
|
||||||
X95.95Y-87.0
|
|
||||||
X104.05Y-43.0
|
|
||||||
X104.05Y-87.0
|
|
||||||
X148.05Y-43.0
|
|
||||||
X148.05Y-87.0
|
|
||||||
T7
|
|
||||||
X11.65Y-65.0
|
|
||||||
X100.0Y-10.75
|
|
||||||
X100.0Y-119.25
|
|
||||||
X188.35Y-65.0
|
|
||||||
M30
|
|
||||||
|
Before Width: | Height: | Size: 166 KiB |
@@ -1,2 +0,0 @@
|
|||||||
(version 1)
|
|
||||||
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
{
|
|
||||||
"board": {
|
|
||||||
"active_layer": 0,
|
|
||||||
"active_layer_preset": "",
|
|
||||||
"auto_track_width": true,
|
|
||||||
"hidden_netclasses": [],
|
|
||||||
"hidden_nets": [],
|
|
||||||
"high_contrast_mode": 0,
|
|
||||||
"net_color_mode": 1,
|
|
||||||
"opacity": {
|
|
||||||
"images": 0.6,
|
|
||||||
"pads": 1.0,
|
|
||||||
"shapes": 1.0,
|
|
||||||
"tracks": 1.0,
|
|
||||||
"vias": 1.0,
|
|
||||||
"zones": 0.6
|
|
||||||
},
|
|
||||||
"selection_filter": {
|
|
||||||
"dimensions": true,
|
|
||||||
"footprints": true,
|
|
||||||
"graphics": true,
|
|
||||||
"keepouts": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pads": true,
|
|
||||||
"text": true,
|
|
||||||
"tracks": true,
|
|
||||||
"vias": true,
|
|
||||||
"zones": true
|
|
||||||
},
|
|
||||||
"visible_items": [
|
|
||||||
"vias",
|
|
||||||
"footprint_text",
|
|
||||||
"footprint_anchors",
|
|
||||||
"ratsnest",
|
|
||||||
"grid",
|
|
||||||
"footprints_front",
|
|
||||||
"footprints_back",
|
|
||||||
"footprint_values",
|
|
||||||
"footprint_references",
|
|
||||||
"tracks",
|
|
||||||
"drc_errors",
|
|
||||||
"bitmaps",
|
|
||||||
"pads",
|
|
||||||
"zones",
|
|
||||||
"drc_warnings",
|
|
||||||
"drc_exclusions",
|
|
||||||
"locked_item_shadows",
|
|
||||||
"conflict_shadows",
|
|
||||||
"shapes"
|
|
||||||
],
|
|
||||||
"visible_layers": "00000000_00000000_0fffffff_ffffffff",
|
|
||||||
"zone_display_mode": 0
|
|
||||||
},
|
|
||||||
"git": {
|
|
||||||
"integration_disabled": false,
|
|
||||||
"repo_type": "",
|
|
||||||
"repo_username": "",
|
|
||||||
"ssh_key": ""
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "Flow_Controller_Panel.kicad_prl",
|
|
||||||
"version": 5
|
|
||||||
},
|
|
||||||
"net_inspector_panel": {
|
|
||||||
"col_hidden": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"col_order": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
5,
|
|
||||||
6,
|
|
||||||
7,
|
|
||||||
8,
|
|
||||||
9
|
|
||||||
],
|
|
||||||
"col_widths": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"custom_group_rules": [],
|
|
||||||
"expanded_rows": [],
|
|
||||||
"filter_by_net_name": true,
|
|
||||||
"filter_by_netclass": true,
|
|
||||||
"filter_text": "",
|
|
||||||
"group_by_constraint": false,
|
|
||||||
"group_by_netclass": false,
|
|
||||||
"show_unconnected_nets": false,
|
|
||||||
"show_zero_pad_nets": false,
|
|
||||||
"sort_ascending": true,
|
|
||||||
"sorting_column": 0
|
|
||||||
},
|
|
||||||
"open_jobsets": [],
|
|
||||||
"project": {
|
|
||||||
"files": []
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"selection_filter": {
|
|
||||||
"graphics": true,
|
|
||||||
"images": true,
|
|
||||||
"labels": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pins": true,
|
|
||||||
"symbols": true,
|
|
||||||
"text": true,
|
|
||||||
"wires": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,466 +0,0 @@
|
|||||||
{
|
|
||||||
"board": {
|
|
||||||
"3dviewports": [],
|
|
||||||
"design_settings": {
|
|
||||||
"defaults": {
|
|
||||||
"apply_defaults_to_fp_fields": false,
|
|
||||||
"apply_defaults_to_fp_shapes": false,
|
|
||||||
"apply_defaults_to_fp_text": false,
|
|
||||||
"board_outline_line_width": 0.0381,
|
|
||||||
"copper_line_width": 0.254,
|
|
||||||
"copper_text_italic": false,
|
|
||||||
"copper_text_size_h": 1.524,
|
|
||||||
"copper_text_size_v": 1.524,
|
|
||||||
"copper_text_thickness": 0.3048,
|
|
||||||
"copper_text_upright": false,
|
|
||||||
"courtyard_line_width": 0.05,
|
|
||||||
"dimension_precision": 4,
|
|
||||||
"dimension_units": 3,
|
|
||||||
"dimensions": {
|
|
||||||
"arrow_length": 1270000,
|
|
||||||
"extension_offset": 500000,
|
|
||||||
"keep_text_aligned": true,
|
|
||||||
"suppress_zeroes": true,
|
|
||||||
"text_position": 0,
|
|
||||||
"units_format": 0
|
|
||||||
},
|
|
||||||
"fab_line_width": 0.1,
|
|
||||||
"fab_text_italic": false,
|
|
||||||
"fab_text_size_h": 1.0,
|
|
||||||
"fab_text_size_v": 1.0,
|
|
||||||
"fab_text_thickness": 0.15,
|
|
||||||
"fab_text_upright": false,
|
|
||||||
"other_line_width": 0.1,
|
|
||||||
"other_text_italic": false,
|
|
||||||
"other_text_size_h": 1.0,
|
|
||||||
"other_text_size_v": 1.0,
|
|
||||||
"other_text_thickness": 0.15,
|
|
||||||
"other_text_upright": false,
|
|
||||||
"pads": {
|
|
||||||
"drill": 0.0,
|
|
||||||
"height": 0.4,
|
|
||||||
"width": 1.325
|
|
||||||
},
|
|
||||||
"silk_line_width": 0.1524,
|
|
||||||
"silk_text_italic": false,
|
|
||||||
"silk_text_size_h": 0.8128,
|
|
||||||
"silk_text_size_v": 0.8128,
|
|
||||||
"silk_text_thickness": 0.1524,
|
|
||||||
"silk_text_upright": false,
|
|
||||||
"zones": {
|
|
||||||
"min_clearance": 0.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"diff_pair_dimensions": [
|
|
||||||
{
|
|
||||||
"gap": 0.0,
|
|
||||||
"via_gap": 0.0,
|
|
||||||
"width": 0.0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"drc_exclusions": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 2
|
|
||||||
},
|
|
||||||
"rule_severities": {
|
|
||||||
"annular_width": "error",
|
|
||||||
"clearance": "error",
|
|
||||||
"connection_width": "warning",
|
|
||||||
"copper_edge_clearance": "error",
|
|
||||||
"copper_sliver": "warning",
|
|
||||||
"courtyards_overlap": "error",
|
|
||||||
"creepage": "error",
|
|
||||||
"diff_pair_gap_out_of_range": "error",
|
|
||||||
"diff_pair_uncoupled_length_too_long": "error",
|
|
||||||
"drill_out_of_range": "error",
|
|
||||||
"duplicate_footprints": "warning",
|
|
||||||
"extra_footprint": "warning",
|
|
||||||
"footprint": "error",
|
|
||||||
"footprint_filters_mismatch": "ignore",
|
|
||||||
"footprint_symbol_mismatch": "warning",
|
|
||||||
"footprint_type_mismatch": "ignore",
|
|
||||||
"hole_clearance": "error",
|
|
||||||
"hole_to_hole": "warning",
|
|
||||||
"holes_co_located": "warning",
|
|
||||||
"invalid_outline": "error",
|
|
||||||
"isolated_copper": "warning",
|
|
||||||
"item_on_disabled_layer": "error",
|
|
||||||
"items_not_allowed": "error",
|
|
||||||
"length_out_of_range": "error",
|
|
||||||
"lib_footprint_issues": "warning",
|
|
||||||
"lib_footprint_mismatch": "warning",
|
|
||||||
"malformed_courtyard": "error",
|
|
||||||
"microvia_drill_out_of_range": "error",
|
|
||||||
"mirrored_text_on_front_layer": "warning",
|
|
||||||
"missing_courtyard": "ignore",
|
|
||||||
"missing_footprint": "warning",
|
|
||||||
"net_conflict": "warning",
|
|
||||||
"nonmirrored_text_on_back_layer": "warning",
|
|
||||||
"npth_inside_courtyard": "ignore",
|
|
||||||
"padstack": "warning",
|
|
||||||
"pth_inside_courtyard": "ignore",
|
|
||||||
"shorting_items": "error",
|
|
||||||
"silk_edge_clearance": "warning",
|
|
||||||
"silk_over_copper": "warning",
|
|
||||||
"silk_overlap": "warning",
|
|
||||||
"skew_out_of_range": "error",
|
|
||||||
"solder_mask_bridge": "error",
|
|
||||||
"starved_thermal": "error",
|
|
||||||
"text_height": "warning",
|
|
||||||
"text_on_edge_cuts": "error",
|
|
||||||
"text_thickness": "warning",
|
|
||||||
"through_hole_pad_without_hole": "error",
|
|
||||||
"too_many_vias": "error",
|
|
||||||
"track_angle": "error",
|
|
||||||
"track_dangling": "warning",
|
|
||||||
"track_segment_length": "error",
|
|
||||||
"track_width": "error",
|
|
||||||
"tracks_crossing": "error",
|
|
||||||
"unconnected_items": "error",
|
|
||||||
"unresolved_variable": "error",
|
|
||||||
"via_dangling": "warning",
|
|
||||||
"zones_intersect": "error"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"max_error": 0.005,
|
|
||||||
"min_clearance": 0.25,
|
|
||||||
"min_connection": 0.0,
|
|
||||||
"min_copper_edge_clearance": 0.5,
|
|
||||||
"min_groove_width": 0.0,
|
|
||||||
"min_hole_clearance": 0.25,
|
|
||||||
"min_hole_to_hole": 0.25,
|
|
||||||
"min_microvia_diameter": 0.0,
|
|
||||||
"min_microvia_drill": 0.0,
|
|
||||||
"min_resolved_spokes": 2,
|
|
||||||
"min_silk_clearance": 0.0,
|
|
||||||
"min_text_height": 0.8,
|
|
||||||
"min_text_thickness": 0.08,
|
|
||||||
"min_through_hole_diameter": 0.3,
|
|
||||||
"min_track_width": 0.127,
|
|
||||||
"min_via_annular_width": 0.1,
|
|
||||||
"min_via_diameter": 0.6,
|
|
||||||
"solder_mask_to_copper_clearance": 0.0,
|
|
||||||
"use_height_for_length_calcs": true
|
|
||||||
},
|
|
||||||
"teardrop_options": [
|
|
||||||
{
|
|
||||||
"td_onpthpad": true,
|
|
||||||
"td_onroundshapesonly": false,
|
|
||||||
"td_onsmdpad": true,
|
|
||||||
"td_ontrackend": false,
|
|
||||||
"td_onvia": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"teardrop_parameters": [
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_round_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_rect_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_track_end",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"track_widths": [
|
|
||||||
0.0,
|
|
||||||
0.15,
|
|
||||||
0.2,
|
|
||||||
0.4,
|
|
||||||
0.6
|
|
||||||
],
|
|
||||||
"tuning_pattern_settings": {
|
|
||||||
"diff_pair_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 1.0
|
|
||||||
},
|
|
||||||
"diff_pair_skew_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
},
|
|
||||||
"single_track_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"via_dimensions": [
|
|
||||||
{
|
|
||||||
"diameter": 0.0,
|
|
||||||
"drill": 0.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"diameter": 0.6,
|
|
||||||
"drill": 0.3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"diameter": 0.9,
|
|
||||||
"drill": 0.4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"zones_allow_external_fillets": false
|
|
||||||
},
|
|
||||||
"ipc2581": {
|
|
||||||
"dist": "",
|
|
||||||
"distpn": "",
|
|
||||||
"internal_id": "",
|
|
||||||
"mfg": "",
|
|
||||||
"mpn": ""
|
|
||||||
},
|
|
||||||
"layer_pairs": [],
|
|
||||||
"layer_presets": [],
|
|
||||||
"viewports": []
|
|
||||||
},
|
|
||||||
"boards": [],
|
|
||||||
"cvpcb": {
|
|
||||||
"equivalence_files": []
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"pinned_footprint_libs": [],
|
|
||||||
"pinned_symbol_libs": []
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "Flow_Controller_Panel.kicad_pro",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"net_settings": {
|
|
||||||
"classes": [
|
|
||||||
{
|
|
||||||
"bus_width": 12,
|
|
||||||
"clearance": 0.127,
|
|
||||||
"diff_pair_gap": 0.254,
|
|
||||||
"diff_pair_via_gap": 0.25,
|
|
||||||
"diff_pair_width": 0.1524,
|
|
||||||
"line_style": 0,
|
|
||||||
"microvia_diameter": 0.6858,
|
|
||||||
"microvia_drill": 0.3302,
|
|
||||||
"name": "Default",
|
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"priority": 2147483647,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.127,
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3,
|
|
||||||
"wire_width": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bus_width": 12,
|
|
||||||
"clearance": 0.127,
|
|
||||||
"diff_pair_gap": 0.254,
|
|
||||||
"diff_pair_via_gap": 0.25,
|
|
||||||
"diff_pair_width": 0.1524,
|
|
||||||
"line_style": 0,
|
|
||||||
"microvia_diameter": 0.6858,
|
|
||||||
"microvia_drill": 0.3302,
|
|
||||||
"name": "Board_0-Default",
|
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"priority": 2147483647,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.127,
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3,
|
|
||||||
"wire_width": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bus_width": 12,
|
|
||||||
"clearance": 0.127,
|
|
||||||
"diff_pair_gap": 0.254,
|
|
||||||
"diff_pair_via_gap": 0.25,
|
|
||||||
"diff_pair_width": 0.1524,
|
|
||||||
"line_style": 0,
|
|
||||||
"microvia_diameter": 0.6858,
|
|
||||||
"microvia_drill": 0.3302,
|
|
||||||
"name": "Board_1-Default",
|
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"priority": 2147483647,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.127,
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3,
|
|
||||||
"wire_width": 6
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"version": 4
|
|
||||||
},
|
|
||||||
"net_colors": null,
|
|
||||||
"netclass_assignments": null,
|
|
||||||
"netclass_patterns": [
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-GND"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/RAW_SENSOR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-Net-(Q1-G)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/ALARM_TRIGGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/SWIO"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-Net-(J3-UP)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-unconnected-(J3-*-Pad5)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/I2C_SDA"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-unconnected-(J3-#-Pad6)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-+3.3V"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-+5V"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/ALARM _CNC"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/BUTTON_ADC"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/I2C_SCL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_0-Default",
|
|
||||||
"pattern": "Board_0-/FLOW_PULSE_MCU"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/I2C_SCL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/RAW_SENSOR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/SWIO"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-Net-(Q1-G)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-GND"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-unconnected-(J3-#-Pad6)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-+5V"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/I2C_SDA"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-unconnected-(J3-*-Pad5)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/ALARM_TRIGGER"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/BUTTON_ADC"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-+3.3V"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-Net-(J3-UP)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/ALARM _CNC"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netclass": "Board_1-Default",
|
|
||||||
"pattern": "Board_1-/FLOW_PULSE_MCU"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"pcbnew": {
|
|
||||||
"last_paths": {
|
|
||||||
"gencad": "",
|
|
||||||
"idf": "",
|
|
||||||
"netlist": "",
|
|
||||||
"plot": "",
|
|
||||||
"pos_files": "",
|
|
||||||
"specctra_dsn": "",
|
|
||||||
"step": "",
|
|
||||||
"svg": "",
|
|
||||||
"vrml": ""
|
|
||||||
},
|
|
||||||
"page_layout_descr_file": ""
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"legacy_lib_dir": "",
|
|
||||||
"legacy_lib_list": []
|
|
||||||
},
|
|
||||||
"sheets": [],
|
|
||||||
"text_variables": {}
|
|
||||||
}
|
|
||||||
@@ -127,4 +127,5 @@ class CustomTooling(ToolingPlugin):
|
|||||||
|
|
||||||
fixture.SetWidth(pcbnew.FromMM(0.2))
|
fixture.SetWidth(pcbnew.FromMM(0.2))
|
||||||
|
|
||||||
board.Add(fixture)
|
board.Add(fixture)
|
||||||
|
|
||||||
|
|||||||