Add rotation DB

This commit is contained in:
Hildo Guillardi Júnior
2022-10-21 23:17:14 -03:00
parent c53997c639
commit 17b3c10d16
3 changed files with 123 additions and 9 deletions
+7 -4
View File
@@ -39,8 +39,8 @@ Add an 'LCSC Part #'* field with the LCSC component part number to the symbol's
_The fields will be query in the order denoted above._
#### Fallback Fields*:
| 'LCSC' | 'JLC' | 'MPN' | 'Mpn' | 'mpn' |
| --- | --- | --- | --- | --- |
| 'lcsc#' | 'LCSC' | 'JLC' | 'MPN' | 'Mpn' | 'mpn' |
| --- | --- | --- | --- | --- | --- |
_The fields will be query in the order denoted above._
@@ -54,8 +54,7 @@ Select 'Exclude from position files' or 'Exclude from BOM' in the footprint's fa
<img src="https://github.com/bennymeg/JLC-Plugin-for-KiCad/blob/master/assets/fabrication.png?raw=true" height=505>
### Rotate a Component
The rotation of components in KiCad Footprints does not always match the orientation in the JLC library.
Add an 'JLC Rotation Offset' field with an counter-clockwise orientation offset in degrees to correct this.
The rotation of components in KiCad Footprints does not always match the orientation in the JLC library because KiCad and JLCPB used different variation of the same standard. Most of the rotations may be corrected by the `rotations.cf` definitions. To the exception cases: add an 'JLC Rotation Offset' field with an counter-clockwise orientation offset in degrees to correct this.
<img src="https://github.com/bennymeg/JLC-Plugin-for-KiCad/blob/master/assets/rotation-jlc.png?raw=true" height=164>
@@ -78,3 +77,7 @@ _The fields will be queried in the order denoted above._
## Author
Benny Megidish
## Contributors
Hildo Guillardi Júnior
+55 -5
View File
@@ -1,8 +1,17 @@
# For better annotation.
from __future__ import annotations
# System base libraries
import os
import csv
import shutil
import pcbnew
from collections import defaultdict
import re
# Interaction with KiCad.
import pcbnew
# Application definitions.
from .config import *
@@ -11,8 +20,40 @@ class ProcessManager:
self.board = pcbnew.GetBoard()
self.bom = []
self.components = []
self.__rotation_db = self.__read_rotation_db()
@staticmethod
def __read_rotation_db(filename: str = os.path.join(os.path.dirname(__file__), 'rotations.cf')) -> dict[str, float]:
'''Read the rotations.cf config file so we know what rotations
to apply later.
'''
db = {}
with open(filename, 'r') as fh:
for line in fh:
line = line.rstrip()
line = re.sub('#.*$', '', line) # remove anything after a comment
line = re.sub('\s*$', '', line) # remove all trailing space
if (line == ""):
continue
m = re.match('^([^\s]+)\s+(\d+)$', line)
if m:
db.update({m.group(1): int(m.group(2))})
return db
def _get_rotation_from_db(self, footprint: str) -> float:
'''Get the rotation to be added from the database file.'''
# Lookfor regular expression math of the footprint name and not its root library.
fpshort = footprint.split(':')[-1]
for expression, delta in self.db.items():
fp = fpshort
if (re.search(':', expression)):
fp = footprint
if(re.search(expression, fp)):
return delta
return 0.0
def generate_gerber(self, temp_dir):
'''Generate the Gerber files.'''
settings = self.board.GetDesignSettings()
settings.m_SolderMaskMargin = 0
settings.m_SolderMaskMinWidth = 0
@@ -47,6 +88,7 @@ class ProcessManager:
plot_controller.ClosePlot()
def generate_drills(self, temp_dir):
'''Generate the drill file.'''
drill_writer = pcbnew.EXCELLON_WRITER(self.board)
drill_writer.SetOptions(
@@ -58,10 +100,12 @@ class ProcessManager:
drill_writer.CreateDrillandMapFilesSet(temp_dir, True, False)
def generate_netlist(self, temp_dir):
'''Generate the conenction netlist.'''
netlist_writer = pcbnew.IPC356D_WRITER(self.board)
netlist_writer.Write(os.path.join(temp_dir, netlistFileName))
def generate_positions(self, temp_dir):
'''Generate the position files.'''
if hasattr(self.board, 'GetModules'):
footprints = list(self.board.GetModules())
else:
@@ -110,7 +154,10 @@ class ProcessManager:
mid_x = (footprint.GetPosition()[0] - self.board.GetDesignSettings().GetAuxOrigin()[0]) / 1000000.0
mid_y = (footprint.GetPosition()[1] - self.board.GetDesignSettings().GetAuxOrigin()[1]) * -1.0 / 1000000.0
rotation = footprint.GetOrientation().AsDegrees() if hasattr(footprint.GetOrientation(), 'AsDegrees') else footprint.GetOrientation() / 10.0
rotation = (rotation + self._getRotOffsetFromFootprint(footprint)) % 360.0
# Get the rotation offset to be added to the actual rotation prioritazing the explicited by the
# designer at the standards symbol fields. If not speficied use the internal database.
rotation_offset = self._get_rotation_offset_from_footprint(footprint) #or self._get_rotation_from_db(footprint)
rotation = (rotation + rotation_offset) % 360.0
self.components.append({
'Designator': designator,
@@ -143,7 +190,7 @@ class ProcessManager:
'Quantity': 1,
'Value': footprint.GetValue(),
# 'Mount': mount_type,
'LCSC Part #': self._getMpnFromFootprint(footprint),
'LCSC Part #': self._get_mpn_from_footprint(footprint),
})
if len(self.components) > 0:
@@ -171,6 +218,7 @@ class ProcessManager:
csv_writer.writerow(component.values())
def generate_archive(self, temp_dir, temp_file):
'''Generate the files.'''
temp_file = shutil.make_archive(temp_file, 'zip', temp_dir)
temp_file = shutil.move(temp_file, temp_dir)
@@ -181,7 +229,8 @@ class ProcessManager:
return temp_file
def _getMpnFromFootprint(self, footprint):
def _get_mpn_from_footprint(self, footprint: str):
''''Get the MPN/LCSS stock code from standard sylbol fields.'''
keys = ['LCSC Part #', 'JLCPCB Part #']
fallback_keys = ['LCSC', 'JLC', 'MPN', 'Mpn', 'mpn']
@@ -193,7 +242,8 @@ class ProcessManager:
if footprint.HasProperty(key):
return footprint.GetProperty(key)
def _getRotOffsetFromFootprint(self, footprint):
def _get_rotation_offset_from_footprint(self, footprint: str) -> float:
'''Get the rotation from standard symbol fileds.'''
keys = ['JLCPCB Rotation Offset']
fallback_keys = ['JlcRotOffset', 'JLCRotOffset']
+61
View File
@@ -0,0 +1,61 @@
#
# Rotations for jlcpcba
#
# This defines additional rotations we need to apply to ensure the
# footprints are correctly orientated to work with the JLCPCB PBCA
# service
#
# These are regular expressions that are matched by default against
# the short footprint name (without the library name), however if there
# is a colon in the regex then the full name (with the library name) is
# used.
#
# The matches are checked against one by one, and the first match
# is used
#
# The regex and the rotation value is separated by any amount of
# whitespace, blank lines and comments are ignored
#
#
# Normal short-name matches
#
^SOT-223 180
^SOT-23 180
^D_SOT-23 180
^TSOT-23 180
^SOT-353 180
^QFN- 90
^qfn- 90
^LQFP- 270
^TQFP- 270
^MSOP- 270
^TSSOP- 270
^DFN- 270
^SOIC-8_ 270
^SOIC-16_ 270
^VSSOP-10_- 270
#
# Polarised caps are 180 out
#
^CP_Elec_ 180
^C_Elec_ 180
^CP_EIA- 180
#
# Long name matches
#
#^Lees_Footprints: 270
^LED_WS2812B_PLCC4 180
# More rotation from https://github.com/matthewlai/JLCKicadTools/tree/master/jlc_kicad_tools
^R_Array_Convex_ 90
^R_Array_Concave_ 90
^SOP-4_ 0
^SOP-(?!18_) 270
^SOP-18_ 0
^VSSOP-8_ 270
^Bosch_LGA- 90
^PowerPAK_SO-8_Single 270
^HTSSOP- 270