Esempio n. 1
0
def createPrinted(inputboard, outputdir, pcbthickness, thickness, framewidth,
                  ignore, cutout, frameclearance, enlargeholes):
    """
    Create a 3D printed self-registering stencil.
    """
    board = pcbnew.LoadBoard(inputboard)
    refs = parseReferences(ignore)
    cutoutComponents = getComponents(board, parseReferences(cutout))
    removeComponents(board, refs)
    Path(outputdir).mkdir(parents=True, exist_ok=True)

    # We create the stencil based on DXF export. Using it avoids the necessity
    # to interpret KiCAD PAD shapes which constantly change with newer and newer
    # versions.
    height = min(pcbthickness, max(0.5, pcbthickness - 0.3))
    bottomPaste, topPaste, outline = pasteDxfExport(board, outputdir)
    topCutout = extractComponentPolygons(cutoutComponents, "F.CrtYd")
    bottomCutout = extractComponentPolygons(cutoutComponents, "B.CrtYd")
    topStencil = printedStencil(outline, topPaste, topCutout, thickness, height,
        framewidth, frameclearance, enlargeholes, True)
    bottomStencil = printedStencil(outline, bottomPaste, bottomCutout, thickness,
        height, framewidth, frameclearance, enlargeholes, False)

    bottomStencilFile = os.path.join(outputdir, "bottomStencil.scad")
    solid.scad_render_to_file(bottomStencil, bottomStencilFile,
        file_header=f'$fa = 0.4; $fs = 0.4;', include_orig_code=True)
    renderScad(bottomStencilFile, os.path.join(outputdir, "bottomStencil.stl"))

    topStencilFile = os.path.join(outputdir, "topStencil.scad")
    solid.scad_render_to_file(topStencil, topStencilFile,
        file_header=f'$fa = 0.4; $fs = 0.4;', include_orig_code=True)
    renderScad(topStencilFile, os.path.join(outputdir, "topStencil.stl"))
Esempio n. 2
0
def runImpl(boardfile, useMm, strict):
    try:
        if not isV6(getVersion()):
            raise RuntimeError("This feature is available only with KiCAD 6.")
        units = pcbnew.EDA_UNITS_MILLIMETRES if useMm else EDA_UNITS_INCHES
        b = pcbnew.LoadBoard(boardfile)
        with tempfile.NamedTemporaryFile(mode="w+") as tmpFile:
            result = pcbnew.WriteDRCReport(b, tmpFile.name, units, strict)
            assert result

            tmpFile.seek(0)
            report = readReport(tmpFile)

            failed = False
            errorName = {
                "drc": "DRC violations",
                "unconnected": "unconnected pads",
                "footprint": "footprints errors"
            }
            for k, v in report.items():
                if len(v) == 0:
                    continue
                failed = True
                print(f"** Found {len(v)} {errorName[k]}: **")
                for x in v:
                    print(x)
                print("\n")
            if not failed:
                print("No DRC errors found.")
            else:
                print("Found some DRC violations. See the report above.")
            sys.exit(failed)
    except Exception as e:
        sys.stderr.write("An error occurred: " + str(e) + "\n")
        sys.exit(1)
Esempio n. 3
0
def exportPcbway(board, outputdir, assembly, schematic, ignore, manufacturer,
                 partnumber, description, notes, soldertype, footprint,
                 corrections, missingerror, nboards):
    """
    Prepare fabrication files for PCBWay including their assembly service
    """
    loadedBoard = pcbnew.LoadBoard(board)
    refsToIgnore = parseReferences(ignore)
    removeComponents(loadedBoard, refsToIgnore)
    Path(outputdir).mkdir(parents=True, exist_ok=True)

    gerberdir = os.path.join(outputdir, "gerber")
    shutil.rmtree(gerberdir, ignore_errors=True)
    gerberImpl(board, gerberdir, settings=exportSettingsPcbway)
    shutil.make_archive(os.path.join(outputdir, "gerbers"), "zip", outputdir,
                        "gerber")

    if not assembly:
        return
    if schematic is None:
        raise RuntimeError(
            "When outputing assembly data, schematic is required")
    components = extractComponents(schematic)
    correctionFields = [x.strip() for x in corrections.split(",")]
    manufacturerFields = [x.strip() for x in manufacturer.split(",")]
    partNumberFields = [x.strip() for x in partnumber.split(",")]
    descriptionFields = [x.strip() for x in description.split(",")]
    notesFields = [x.strip() for x in notes.split(",")]
    typeFields = [x.strip() for x in soldertype.split(",")]
    footprintFields = [x.strip() for x in footprint.split(",")]
    addVirtualToRefsToIgnore(refsToIgnore, loadedBoard)
    bom = collectBom(components, manufacturerFields, partNumberFields,
                     descriptionFields, notesFields, typeFields,
                     footprintFields, refsToIgnore)

    missingFields = False
    for type, references in bom.items():
        _, _, manu, partno, _, _ = type
        if not manu or not partno:
            missingFields = True
            for r in references:
                print(
                    f"WARNING: Component {r} is missing manufacturer and/or part number"
                )
    if missingFields and missingerror:
        sys.exit("There are components with missing ordercode, aborting")

    posData = collectPosData(loadedBoard, correctionFields, bom=components)
    posDataToFile(posData, os.path.join(outputdir, "pos.csv"))
    types = collectSolderTypes(loadedBoard)
    bomToCsv(bom, os.path.join(outputdir, "bom.csv"), nboards, types)
Esempio n. 4
0
def create(inputboard, outputdir, jigsize, jigthickness, pcbthickness,
           registerborder, tolerance, ignore, cutout):
    board = pcbnew.LoadBoard(inputboard)
    refs = parseReferences(ignore)
    removeComponents(board, refs)

    Path(outputdir).mkdir(parents=True, exist_ok=True)

    jigsize = (fromMm(jigsize[0]), fromMm(jigsize[1]))
    addJigFrame(board, jigsize)
    cutoutComponents(board, getComponents(board, parseReferences(cutout)))

    stencilFile = os.path.join(outputdir, "stencil.kicad_pcb")
    board.Save(stencilFile)

    plotPlan = [
        # name, id, comment
        ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"),
        ("PasteTop", pcbnew.F_Paste, "Paste top"),
    ]
    # get a copy of exportSettingsJlcpcb dictionary and
    # exclude the Edge.Cuts layer for creation of stencil gerber files
    exportSettings = exportSettingsJlcpcb.copy()
    exportSettings["ExcludeEdgeLayer"] = True
    gerberDir = os.path.join(outputdir, "gerber")
    gerberImpl(stencilFile, gerberDir, plotPlan, False, exportSettings)
    gerbers = [os.path.join(gerberDir, x) for x in os.listdir(gerberDir)]
    subprocess.check_call(
        ["zip", "-j", os.path.join(outputdir, "gerbers.zip")] + gerbers)

    jigthickness = fromMm(jigthickness)
    pcbthickness = fromMm(pcbthickness)
    outerBorder, innerBorder = fromMm(registerborder[0]), fromMm(
        registerborder[1])
    tolerance = fromMm(tolerance)
    topRegister = makeTopRegister(board, jigsize, jigthickness, pcbthickness,
                                  outerBorder, innerBorder, tolerance)
    bottomRegister = makeBottomRegister(board, jigsize, jigthickness,
                                        pcbthickness, outerBorder, innerBorder,
                                        tolerance)

    topRegisterFile = os.path.join(outputdir, "topRegister.scad")
    solid.scad_render_to_file(topRegister, topRegisterFile)
    renderScad(topRegisterFile, os.path.join(outputdir, "topRegister.stl"))

    bottomRegisterFile = os.path.join(outputdir, "bottomRegister.scad")
    solid.scad_render_to_file(bottomRegister, bottomRegisterFile)
    renderScad(bottomRegisterFile, os.path.join(outputdir,
                                                "bottomRegister.stl"))
Esempio n. 5
0
def exportJlcpcb(board, outputdir, assembly, schematic, forcesmd, ignore,
                 field, corrections, missingerror):
    """
    Prepare fabrication files for JLCPCB including their assembly service
    """
    loadedBoard = pcbnew.LoadBoard(board)
    refsToIgnore = parseReferences(ignore)
    removeComponents(loadedBoard, refsToIgnore)
    Path(outputdir).mkdir(parents=True, exist_ok=True)

    gerberdir = os.path.join(outputdir, "gerber")
    shutil.rmtree(gerberdir, ignore_errors=True)
    gerberImpl(board, gerberdir)
    shutil.make_archive(os.path.join(outputdir, "gerbers"), "zip", outputdir,
                        "gerber")

    if not assembly:
        return
    if schematic is None:
        raise RuntimeError(
            "When outputing assembly data, schematic is required")
    correctionFields = [x.strip() for x in corrections.split(",")]
    components = extractComponents(schematic)
    ordercodeFields = [x.strip() for x in field.split(",")]
    bom = collectBom(components, ordercodeFields, refsToIgnore)

    missingFields = False
    for type, references in bom.items():
        _, _, lcsc = type
        if not lcsc:
            missingFields = True
            for r in references:
                print(f"WARNING: Component {r} is missing ordercode")
    if missingFields and missingerror:
        sys.exit("There are components with missing ordercode, aborting")

    posData = collectPosData(loadedBoard,
                             correctionFields,
                             posFilter=genPosFilter(forcesmd),
                             bom=components)
    posDataToFile(posData, os.path.join(outputdir, "pos.csv"))
    bomToCsv(bom, os.path.join(outputdir, "bom.csv"))
Esempio n. 6
0
 def inheritProperties(self, boardFilename):
     """
     Inherit text properties from a board specified by a properties
     """
     b = pcbnew.LoadBoard(boardFilename)
     self.setDesignSettings(b.GetDesignSettings())
Esempio n. 7
0
 def inheritDesignSettings(self, boardFilename):
     """
     Inherit design settings from the given board specified by a filename
     """
     b = pcbnew.LoadBoard(boardFilename)
     self.setDesignSettings(b.GetDesignSettings())