[Position][Added] Experimental support for gerber position files

Closes #500
This commit is contained in:
Salvador E. Tropea 2023-10-02 12:36:16 -03:00
parent bd081609d5
commit d0c489e2cc
7 changed files with 75 additions and 16 deletions

View File

@ -38,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for CURRENT_DATE text variable
- Populate:
- Basic support for regular list items (#480)
- Position:
- Experimental support for gerber position files (#500)
- Help for the error levels
- Warnings:
- Explain about wrong dir/output separation (#493)

View File

@ -2769,15 +2769,19 @@ outputs:
# [string|list(string)='_none'] Name of the filter to mark components as not fitted.
# A short-cut to use for simple cases where a variant is an overkill
dnf_filter: '_none'
# [string='ASCII'] [ASCII,CSV] Format for the position file
# [string='ASCII'] [ASCII,CSV,GBR] Format for the position file.
# Note that the gerber format (GBR) needs KiCad 7+ and doesn't support most of the options.
# Only the options that explicitly say the format is supported
format: 'ASCII'
# [boolean=false] Include the board edge in the gerber output
gerber_board_edge: false
# [boolean=false] Include virtual components. For special purposes, not pick & place.
# Note that virtual components is a KiCad 5 concept.
# For KiCad 6+ we replace this concept by the option to exclude from position file
include_virtual: false
# [boolean=true] Only include the surface mount components
only_smd: true
# [string='%f-%i%I%v.%x'] Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv').
# [string='%f-%i%I%v.%x'] Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv'|'gbr').
# Important: when using separate files you must use `%i` to differentiate them. Affected by global options
output: '%f-%i%I%v.%x'
# [string|list(string)='_none'] Name of the filter to transform fields before applying other filters.
@ -2791,7 +2795,8 @@ outputs:
separate_files_for_front_and_back: true
# [string='millimeters'] [millimeters,inches,mils] Units used for the positions. Affected by global options
units: 'millimeters'
# [boolean=true] Use the auxiliary axis as origin for coordinates (KiCad default)
# [boolean=true] Use the auxiliary axis as origin for coordinates (KiCad default).
# Supported by the gerber format
use_aux_axis_as_origin: true
# [string=''] Board variant to apply
variant: ''
@ -2924,8 +2929,8 @@ outputs:
options:
# [string='QR'] Short name for the library
lib: 'QR'
# [string='%f-%i%I%v.%x'] Filename/dirname for the output (%i=qr, %x=lib/kicad_sym/pretty).
# You must use %x in the name to get a symbols lib and a footprint. Affected by global options
# [string='%f-%i%I%v.%x'] Filename/dirname for the output library (%i=qr, %x=lib/kicad_sym/pretty).
# You must use %x in the name to get a symbols lib and a footprints lib. Affected by global options
output: '%f-%i%I%v.%x'
# [list(dict)] QR codes to include in the library
qrs:

View File

@ -24,9 +24,11 @@ Parameters:
- Valid keys:
- **format** :index:`: <pair: output - position - options; format>` [string='ASCII'] [ASCII,CSV] Format for the position file.
- **format** :index:`: <pair: output - position - options; format>` [string='ASCII'] [ASCII,CSV,GBR] Format for the position file.
Note that the gerber format (GBR) needs KiCad 7+ and doesn't support most of the options.
Only the options that explicitly say the format is supported.
- **only_smd** :index:`: <pair: output - position - options; only_smd>` [boolean=true] Only include the surface mount components.
- **output** :index:`: <pair: output - position - options; output>` [string='%f-%i%I%v.%x'] Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv').
- **output** :index:`: <pair: output - position - options; output>` [string='%f-%i%I%v.%x'] Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv'|'gbr').
Important: when using separate files you must use `%i` to differentiate them. Affected by global options.
- **separate_files_for_front_and_back** :index:`: <pair: output - position - options; separate_files_for_front_and_back>` [boolean=true] Generate two separated files, one for the top and another for the bottom.
- **units** :index:`: <pair: output - position - options; units>` [string='millimeters'] [millimeters,inches,mils] Units used for the positions. Affected by global options.
@ -41,6 +43,7 @@ Parameters:
- ``dnf_filter`` :index:`: <pair: output - position - options; dnf_filter>` [string|list(string)='_none'] Name of the filter to mark components as not fitted.
A short-cut to use for simple cases where a variant is an overkill.
- ``gerber_board_edge`` :index:`: <pair: output - position - options; gerber_board_edge>` [boolean=false] Include the board edge in the gerber output.
- ``include_virtual`` :index:`: <pair: output - position - options; include_virtual>` [boolean=false] Include virtual components. For special purposes, not pick & place.
Note that virtual components is a KiCad 5 concept.
For KiCad 6+ we replace this concept by the option to exclude from position file.
@ -50,6 +53,7 @@ Parameters:
- ``quote_all`` :index:`: <pair: output - position - options; quote_all>` [boolean=false] When generating the CSV quote all values, even numbers.
- ``right_digits`` :index:`: <pair: output - position - options; right_digits>` [number=4] number of digits for mantissa part of coordinates (0 is auto).
- ``use_aux_axis_as_origin`` :index:`: <pair: output - position - options; use_aux_axis_as_origin>` [boolean=true] Use the auxiliary axis as origin for coordinates (KiCad default).
Supported by the gerber format.
- ``variant`` :index:`: <pair: output - position - options; variant>` [string=''] Board variant to apply.
- **type** :index:`: <pair: output - position; type>` [string=''] Type of output.

View File

@ -30,8 +30,8 @@ Parameters:
- Valid keys:
- **lib** :index:`: <pair: output - qr_lib - options; lib>` [string='QR'] Short name for the library.
- **output** :index:`: <pair: output - qr_lib - options; output>` [string='%f-%i%I%v.%x'] Filename/dirname for the output (%i=qr, %x=lib/kicad_sym/pretty).
You must use %x in the name to get a symbols lib and a footprint. Affected by global options.
- **output** :index:`: <pair: output - qr_lib - options; output>` [string='%f-%i%I%v.%x'] Filename/dirname for the output library (%i=qr, %x=lib/kicad_sym/pretty).
You must use %x in the name to get a symbols lib and a footprints lib. Affected by global options.
- **qrs** :index:`: <pair: output - qr_lib - options; qrs>` [list(dict)] QR codes to include in the library.
- Valid keys:

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2019 Romain Deterre (@rdeterre)
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
@ -10,6 +10,7 @@ from re import compile
from datetime import datetime
from collections import OrderedDict
from .gs import GS
from .kiplot import run_command
from .misc import UI_SMD, UI_VIRTUAL, MOD_THROUGH_HOLE, MOD_SMD, MOD_EXCLUDE_FROM_POS_FILES
from .optionable import Optionable
from .out_base import VariantOptions
@ -60,13 +61,15 @@ class PositionOptions(VariantOptions):
def __init__(self):
with document:
self.format = 'ASCII'
""" *[ASCII,CSV] Format for the position file """
""" *[ASCII,CSV,GBR] Format for the position file.
Note that the gerber format (GBR) needs KiCad 7+ and doesn't support most of the options.
Only the options that explicitly say the format is supported """
self.separate_files_for_front_and_back = True
""" *Generate two separated files, one for the top and another for the bottom """
self.only_smd = True
""" *Only include the surface mount components """
self.output = GS.def_global_output
""" *Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv').
""" *Output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv'|'gbr').
Important: when using separate files you must use `%i` to differentiate them """
self.units = 'millimeters'
""" *[millimeters,inches,mils] Units used for the positions. Affected by global options """
@ -78,13 +81,16 @@ class PositionOptions(VariantOptions):
self.bottom_negative_x = False
""" Use negative X coordinates for footprints on bottom layer """
self.use_aux_axis_as_origin = True
""" Use the auxiliary axis as origin for coordinates (KiCad default) """
""" Use the auxiliary axis as origin for coordinates (KiCad default).
Supported by the gerber format """
self.include_virtual = False
""" Include virtual components. For special purposes, not pick & place.
Note that virtual components is a KiCad 5 concept.
For KiCad 6+ we replace this concept by the option to exclude from position file """
self.quote_all = False
""" When generating the CSV quote all values, even numbers """
self.gerber_board_edge = False
""" Include the board edge in the gerber output """
super().__init__()
self._expand_id = 'position'
@ -105,7 +111,7 @@ class PositionOptions(VariantOptions):
new_name = col.name if col.name else new_col
new_columns[new_col] = new_name
self.columns = new_columns
self._expand_ext = 'pos' if self.format == 'ASCII' else 'csv'
self._expand_ext = 'pos' if self.format == 'ASCII' else self.format.lower()
def _do_position_plot_ascii(self, output_dir, columns, modulesStr, maxSizes, modules_side):
topf = None
@ -224,10 +230,31 @@ class PositionOptions(VariantOptions):
self.expand_filename(out_dir, self.output, 'bottom_pos', ext)]
return [self.expand_filename(out_dir, self.output, 'both_pos', ext)]
def run_gerber(self, output_dir):
if not GS.ki7:
raise KiPlotConfigurationError("Gerber position needs KiCad 7+")
pcb_name = self.save_tmp_board_if_variant()
cmd_base = ['kicad-cli', 'pcb', 'export', 'pos', '--format', 'gerber']
if self.use_aux_axis_as_origin:
cmd_base.append('--use-drill-file-origin')
if self.gerber_board_edge:
cmd_base.append('--gerber-board-edge')
cmd_base.append('--side')
fname = self.expand_filename(output_dir, self.output, 'top_pos', self._expand_ext)
run_command(cmd_base+['front', '-o', fname, pcb_name])
fname = self.expand_filename(output_dir, self.output, 'bottom_pos', self._expand_ext)
run_command(cmd_base+['back', '-o', fname, pcb_name])
def run(self, fname):
super().run(fname)
self.filter_pcb_components()
output_dir = os.path.dirname(fname)
if self.format == 'GBR':
self.run_gerber(output_dir)
return
self.filter_pcb_components()
columns = self.columns.values()
conv = GS.unit_name_to_scale_factor(self.units)
# Format all strings

View File

@ -339,3 +339,13 @@ def test_position_flags_3(test_dir):
ctx.run()
check_comp_list(ctx.load_csv(prj+'-both_pos.csv')[0], {'R1', 'R2', 'R3'})
ctx.clean_up()
@pytest.mark.skipif(not context.ki7(), reason="needs kicad-cli")
def test_position_gerber_1(test_dir):
prj = 'light_control'
ctx = context.TestContext(test_dir, prj, 'simple_position_gbr', POS_DIR)
ctx.run()
ctx.expect_out_file_d(prj+'-top_pos.gbr')
ctx.expect_out_file_d(prj+'-bottom_pos.gbr')
ctx.clean_up(keep_project=True)

View File

@ -0,0 +1,11 @@
# Example KiBot config file for a basic 2-layer board
kibot:
version: 1
outputs:
- name: 'position'
type: position
dir: positiondir
options:
format: GBR