KiBot/kibot/out_stencil_3d.py

141 lines
5.7 KiB
Python

# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
Dependencies:
- from: KiKit
role: mandatory
- name: OpenSCAD
url: https://openscad.org/
url_down: https://openscad.org/downloads.html
command: openscad
debian: openscad
arch: openscad
role: mandatory
- from: Xvfbwrapper
role: mandatory
- from: Xvfb
role: mandatory
"""
from .gs import GS
from .macros import macros, document, output_class # noqa: F401
from .out_any_stencil import Stencil_Options
from . import log
logger = log.get_logger()
id_top = 'stencil_3d_top'
id_bottom = 'stencil_3d_bottom'
id_edge = 'stencil_3d_edge'
class Stencil_3D_Options(Stencil_Options):
def __init__(self):
with document:
self.output = GS.def_global_output
""" *Filename for the output (%i='stencil_3d_top'|'stencil_3d_bottom'|'stencil_3d_edge',
%x='stl'|'scad'|'dxf'|'png') """
self.thickness = 0.15
""" *Stencil thickness [mm]. Defines amount of paste dispensed """
self.framewidth = 1
""" Register frame width """
self.frame_width = None
""" {framewidth} """
self.frameclearance = 0
""" Clearance for the stencil register [mm] """
self.frame_clearance = None
""" {frameclearance} """
self.enlargeholes = 0
""" Enlarge pad holes by x mm """
self.enlarge_holes = None
""" {enlarge_holes} """
super().__init__()
self.add_to_doc('include_scad', 'Note that this also includes the DXF files')
def get_targets(self, out_dir):
do_top, do_bottom = self.solve_sides()
files = []
if self.create_preview:
if do_top:
files.append(self.expand_name(id_top, 'png', out_dir))
if do_bottom:
files.append(self.expand_name(id_bottom, 'png', out_dir))
# The edge is needed by any of the OpenSCAD files
if (do_top or do_bottom) and self.include_scad:
files.append(self.expand_name(id_edge, 'dxf', out_dir))
# Top side
if do_top:
files.append(self.expand_name(id_top, 'stl', out_dir))
if self.include_scad:
files.append(self.expand_name(id_top, 'dxf', out_dir))
files.append(self.expand_name(id_top, 'scad', out_dir))
# Bottom side
if do_bottom:
files.append(self.expand_name(id_bottom, 'stl', out_dir))
if self.include_scad:
files.append(self.expand_name(id_bottom, 'dxf', out_dir))
files.append(self.expand_name(id_bottom, 'scad', out_dir))
return files
def create_cmd(self, cmd_kikit):
cmd = [cmd_kikit, 'stencil', 'createprinted',
'--thickness', str(self.thickness),
'--framewidth', str(self.framewidth),
'--pcbthickness', str(self.pcbthickness)]
if self.cutout:
cmd.extend(['--coutout', self.cutout])
if self.frameclearance:
cmd.extend(['--frameclearance', str(self.frameclearance)])
if self.enlargeholes:
cmd.extend(['--enlargeholes', str(self.enlargeholes)])
return cmd
def move_outputs(self, tmp, prj_name, do_top, do_bottom):
replacements = {}
# Create the preview before we touch anything
if self.create_preview:
if do_top:
self.create_preview_png(tmp, 'topStencil.scad', id_top)
if do_bottom:
self.create_preview_png(tmp, 'bottomStencil.scad', id_bottom)
# The edge is needed by any of the OpenSCAD files
if (do_top or do_bottom) and self.include_scad:
self.move_output(tmp, prj_name+'-EdgeCuts.dxf', id_edge, 'dxf', replacements)
# Top side
if do_top:
self.move_output(tmp, 'topStencil.stl', id_top, 'stl')
if self.include_scad:
self.move_output(tmp, prj_name+'-PasteTop.dxf', id_top, 'dxf', replacements)
self.move_output(tmp, 'topStencil.scad', id_top, 'scad', replacements, patch=True)
# Bottom side
if do_bottom:
self.move_output(tmp, 'bottomStencil.stl', id_bottom, 'stl')
if self.include_scad:
self.move_output(tmp, prj_name+'-PasteBottom.dxf', id_bottom, 'dxf', replacements)
self.move_output(tmp, 'bottomStencil.scad', id_bottom, 'scad', replacements, patch=True)
@output_class
class Stencil_3D(BaseOutput): # noqa: F821
""" 3D Printed Stencils
Creates a 3D self-registering model of a stencil you can easily print on
SLA printer, you can use it to apply solder paste to your PCB.
These stencils are quick solution when you urgently need a stencil but probably
they don't last long and might come with imperfections.
It currently uses KiKit, so please read
[KiKit docs](https://github.com/yaqwsx/KiKit/blob/master/doc/stencil.md).
Note that we don't implement `--ignore` option, you should use a variant for this """
def __init__(self):
super().__init__()
with document:
self.options = Stencil_3D_Options
""" *[dict] Options for the `stencil_3d` output """
self._category = 'PCB/fabrication/assembly'
@staticmethod
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'KiKit') or not GS.check_tool(name, 'OpenSCAD'):
return None
return BaseOutput.simple_conf_examples(name, '3D self-registering stencil', 'Assembly') # noqa: F821