Giter VIP home page Giter VIP logo

Comments (14)

pointhi avatar pointhi commented on September 24, 2024

I created such footprints before: https://github.com/pointhi/kicad-footprint-generator/tree/master/scripts/Multicomp

we can improve the script to use the new argparse interface, and then we would only need to create csv files specifying the different variations. (Which could be generated)

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

Thanks @pointhi!

Yes, this is similar to what I was thinking. Albeit older and using kicad_mod. And not meeting the current KLC. And without latches. And THT only. And using a separate launcher shell script. Hmmm...

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

@pointhi @SchrodingersGat
Why is the argparse interface used and encouraged? It allows sending arguments, such as the Molex 52991 script, to generate the different footprints instead of having it all self-contained where executing the script generates all footprints directly.

I can see that having argparse allows new footprints to be created simply by running the script with new arguments. The script doesn't need to be touched. This is handy if a series of parts gets updated to add new varieties.

On the other hand, it means an external script or manual work (defeating the purpose of automation) is needed to generate all footprints.

What was the reason? I'm just asking since I see good and bad on both sides.

Perhaps the script could support parameters, but if none are provided it will use an internal hard-coded list to generate the footprints? That way the script can be written to generate the whole family of parts automatically, but if the user wants to supply arguments the script will also build footprints in a one-off fashion? Sound good?

Relatedly, looking at the Molex 52991 script it doesn't guard against improper pin counts (odd counts, no bounds on range, etc.) nor improper Molex PN suffix (must only be 40 digits, etc.). In fact, the suffix could be used to derive the pin count by stripping off the first 2 digits. These seem like nice enhancements to me; any thoughts or pushback against that?

from kicad-footprint-generator.

SchrodingersGat avatar SchrodingersGat commented on September 24, 2024

I think it is a matter of preference. My scripts always included the model data hard-coded into the .py file itself, so that's always an option.

from kicad-footprint-generator.

pointhi avatar pointhi commented on September 24, 2024

Well, I see various points why the argparse interface should be used:

  • it gives users a general interface which is used for all scripts
  • it allows users to modify parameters without diving into the source code (at the moment, everyone has it's own schema to store data, including problems like position depending arguments (which are not self describing)
  • for this part for example, many variants exists (from various vendors). Having a definition file for every series is way cleaner than writing python scripts for them or extending existing ones
  • those files can be used in other tools (like 3d-model-generators) as well
  • it helps non-programmer to use existing scripts
  • when we have a general interface, we can build tools like a graphical footprint-wizard later without changing the scripts

the point with the slightly more comlicated execution is true. But that's only adding one argument.
We could for example use Makefiles in the future to hardcode such steps, so you could for example run make molex_straight. This would also allow us to build all libraries with a single command, to adjust them for other courtjard distances for example (When we implement overrides into the parser).

Look into #55 for more discussion about that

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

To finish off PRs which never got completed and would be ideal for scripting, I'm working on KiCad/Connectors_Molex.pretty#35. Molex 502430 is the first one I started on.

Using the 72991 script as a seed (https://github.com/pointhi/kicad-footprint-generator/blob/master/scripts/Connectors_Molex/slimstack-52991.py), I developed the following script which accepts one optional parameter for the PN suffix. If no argument is given, all footprints currently listed in the Molex datasheets are generated.

A few other changes which aren't specific to the part:

  • Only one parameter is used (pincount is derived from the PN suffix)
  • PN suffixes are validated (this could be generalized to accept only 4 digits with an even number for the first two digits, only 1 or 2 or 3 for the third digit, and a 0 as the last digit).

Could I get some feedback on this implementation? Edge cases I haven't considered? Improvements?

Here is the script

#!/usr/bin/env python

# KicadModTree is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# KicadModTree is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >.
#
# (C) 2016 by Thomas Pointhuber, <[email protected]>

import sys
import os
import argparse

sys.path.append(os.path.join(sys.path[0], "../.."))  # enable package import from parent directory

from KicadModTree import *  # NOQA


def round_to(n, precision):
    correction = 0.5 if n >= 0 else -0.5
    return int( n/precision+correction ) * precision


if __name__ == '__main__':

    # handle arguments
    parser = argparse.ArgumentParser()
    #parser.add_argument('pincount', help='number of pins of the connector', type=int, nargs=1)
    parser.add_argument('gen_pn', help='suffix to 502430 series number (e.g. 0820)', type=str, nargs='*')
    parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true')
    args = parser.parse_args()
    gen_pn = args.gen_pn

    # list of valid partnumber suffixes in all family datasheets
    valid_pns = ["1410","2010","2210","2410","2610","3010","3210","3410","4010","4410","5010","6010","6410","8010","0820","1430","2030","2230","2430","2630","3230","4030","5030","6030","7030","8030","9030"]
    partnumbers = valid_pns

    if len(gen_pn) == 1:
        partnumbers = gen_pn
    
    for partnumber in partnumbers:
        
        # do not proceed if pin count or partnumber are not valid
        if partnumber not in valid_pns:
            sys.exit("Partnumber is not valid!")
        
        # the first two digits of the PN suffix are the pin count
        pincount = int(partnumber[:2])
        
        footprint_name = 'Molex_SlimStack_Receptacle_2x{pc:02g}_Pitch0.5mm_502430-{pn:s}'.format(pc=pincount/2, pn=partnumber)
        
        print('Building {:s} '.format(footprint_name))
        
        # calculate working values
        pad_x_spacing = 0.4
        pad_y_spacing = 1.05 + 0.66
        pad_width = 0.22
        pad_height = 0.66
        pad_x_span = pad_x_spacing * ((pincount / 2) - 1)
        
        nail_x = pad_x_span / 2.0 + 0.95

        h_body_width = 1.54 / 2.0
        h_body_length = (pad_x_span / 2.0) + 1.33

        fab_width = 0.1

        outline_x = h_body_length - (pad_x_span / 2.0) - 0.3
        marker_y = 0.4
        silk_width = 0.12
        nudge = 0.12

        courtyard_width = 0.05
        courtyard_precision = 0.01
        courtyard_clearance = 0.5
        courtyard_x = round_to(h_body_length + courtyard_clearance, courtyard_precision)
        courtyard_y = round_to((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision)

        label_x_offset = 0
        label_y_offset = courtyard_y + 0.7

        # select correct datasheet URL depending on part number
        if str(partnumber)[:2] == "08":
            datasheet = "http://www.molex.com/pdm_docs/sd/5024300820_sd.pdf" # 0820 (8 pin)
        elif str(partnumber)[2:3] == "1":
            datasheet = "http://www.molex.com/pdm_docs/sd/5024301410_sd.pdf" # xx10 (14-80 pin)
        elif str(partnumber)[2:3] == "3":
            datasheet = "http://www.molex.com/pdm_docs/sd/5024307030_sd.pdf" # xx30 (14-90 pin)
        
        # initialise footprint
        kicad_mod = Footprint(footprint_name)
        kicad_mod.setDescription('Molex SlimStack receptacle, 02x{pc:02g} contacts 0.5mm pitch 4mm height, {ds}'.format(pc=pincount/2, ds=datasheet))
        kicad_mod.setTags('connector molex slimstack 502430-{:s}'.format(partnumber))
        kicad_mod.setAttribute('smd')

        # set general values
        kicad_mod.append(Text(type='reference', text='REF**', size=[1,1], at=[label_x_offset, -label_y_offset], layer='F.SilkS'))
        kicad_mod.append(Text(type='user', text='%R', size=[1,1], at=[0, 0], layer='F.Fab'))
        kicad_mod.append(Text(type='value', text=footprint_name, at=[label_x_offset, label_y_offset], layer='F.Fab'))

        # create pads
        kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,center=[0,-pad_y_spacing/2.0],\
            initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT))
        kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,center=[0,pad_y_spacing/2.0],\
            initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT))
        
        # create "fitting nails" (npth mounting holes)
        #kicad_mod.append(Pad(at=[-nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask']))
        #kicad_mod.append(Pad(at=[nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask']))
        kicad_mod.append(RectLine(start=[-nail_x - 0.35 / 2.0, -0.22], end=[-nail_x + 0.35 / 2.0, 0.22], layer='Edge.Cuts', width=fab_width))
        kicad_mod.append(RectLine(start=[nail_x - 0.35 / 2.0, -0.22], end=[nail_x + 0.35 / 2.0, 0.22], layer='Edge.Cuts', width=fab_width))

        # create fab outline and pin 1 marker
        kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width))
        kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width))

        # create silkscreen outline and pin 1 marker
        left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\
                        [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]]
        right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\
                         [h_body_length-outline_x, -h_body_width-nudge]]
        kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width))
        kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width))

        # create courtyard
        kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width))

        # add model
        kicad_mod.append(Model(filename="${{KISYS3DMOD}}/Connectors_Molex.3dshapes/{:s}.wrl".format(footprint_name), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0]))

        # print render tree
        if args.verbose:
            print(kicad_mod.getRenderTree())

        # write file
        file_handler = KicadFileHandler(kicad_mod)
        file_handler.writeFile('{:s}.kicad_mod'.format(footprint_name))

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

@pointhi @SchrodingersGat
Would you mind taking a look at the script above and seeing if that works for you? How can it be improved before I start using this method to submit footprints and scripts?

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

@pointhi @SchrodingersGat Thoughts or comments on my script above?

from kicad-footprint-generator.

SchrodingersGat avatar SchrodingersGat commented on September 24, 2024

Looks sensible to me :)

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

Here is a simplified and improved version of the above (only the section below has changed). I believe all requirements are met, in that all current PNs are hard-coded and can be generated at once but an argument is also allowed to generate PNs one-by-one. I'm satisfied now and will leave this Issue open for a few days to gather feedback before submitting the script.

if __name__ == '__main__':

    # handle arguments
    parser = argparse.ArgumentParser()
    #parser.add_argument('pincount', help='number of pins of the connector', type=int, nargs=1)
    parser.add_argument('gen_pn', help='suffix of 502430 series number (e.g. 0820)', type=str, nargs='*')
    parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true')
    args = parser.parse_args()
    gen_pn = args.gen_pn # input argument in a list

    # list of valid partnumber suffixes from all datasheets
    valid_pns = ["1410","2010","2210","2410","2610","3010","3210","3410","4010","4410","5010","6010","6410","8010","0820","1430","2030","2230","2430","2630","3230","4030","5030","6030","7030","8030","9030"]
    
    # if user did not supply an argument we will get an empty list and generate all footprints (PN validation is later)
    if gen_pn:
        partnumbers = gen_pn
    else:
        partnumbers = valid_pns
    
    for partnumber in partnumbers:
        
        # do not proceed if pin count or PN are not valid
        #if not ((partnumber.isdigit()) and (len(partnumber) == 4) and (int(partnumber[:2]) % 2.0 == 0) and (partnumber[2:3] in ["1","2","3"]) and (partnumber[3:4] == "0")):
        if partnumber not in valid_pns:
            sys.exit("Partnumber is not valid!")
        
        # the first two digits of the PN suffix are the pin count
        pincount = int(partnumber[:2])
        
        footprint_name = 'Molex_SlimStack_Receptacle_2x{pc:02g}_Pitch0.5mm_502430-{pn:s}'.format(pc=pincount/2, pn=partnumber)

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

I think the above demonstrates the use of optional arguments nicely, along with other small improvements. However, other comments on the script are welcome.

Are there objections or suggestions to the scope of footprints I mentioned in the initial comment? If not, I'll add scripts for these footprints to my todo list.

from kicad-footprint-generator.

matthijskooijman avatar matthijskooijman commented on September 24, 2024

@evanshultz, did you ever get around to generating the footprints listed in the original comment? I've been looking for an 1.27mm and 2.0mm shrouded pin header footprint, but I can only find 2.54mm versions in Connector_IDC and Connector_Multicomp.

from kicad-footprint-generator.

evanshultz avatar evanshultz commented on September 24, 2024

I started on it and made some comments at KiCad/kicad-footprints#41, but then got side-tracked with other things. It is on my list unless somebody beats me to it, but I wouldn't expect to get to this for another month.

from kicad-footprint-generator.

matthijskooijman avatar matthijskooijman commented on September 24, 2024

Thanks for the update. I also found #134 which seems to track the progress of such a generator script for shrouded headers.

from kicad-footprint-generator.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.