Creating 3D model of a PCB holder for soldering

I am working on a PCB that has a few pin headers. The PCB is made and assembled in JLCPCB however they do not offer soldering though-hole components or pin headers. The PCB looks like this when it arrives:

Sorry, new users can only put one image in a post.

so I had an idea, that as I have files for manufacturing and assembling the board, that I could 3D print a simple holder to make soldering of the headers easier. Something like this:


As I am using Openscad for 3D modeling and it is de facto programming your 3D model, it should be easy to convert manufacturing exports from KiCad to Openscad, for example like this:
kicad_module("LED_SMD","LED_0603_1608Metric","","",[9.5791,38.93566],180.00,"front");//D5 - Red
However it turned out that it is not that simple and I went down the rabbit hole of many formats, reference systems and it took me much more longer than I expected and it is still way far from something that could be published for general use…
First idea was to start with pick and place Pos file and convert it via some script to Openscad definition. However after some time I found out that:

  • Pos file does not contain all modules, especially pin headers, even if I check the “include non smd …” checkbox.
  • Pos file does not contain board edges or any other info about PCB dimensions (which is understandable).
  • But it also uses different reference system than PCBNEW so it is not that easy to just open the PCB in PCBNEW and write down four numbers…
    So I looked into different manufacturing exports available in KiCad and I found “report file” and it seemed to contain all information needed. Basically I need this information:
  • board dimensions
  • position, rotation, package type of all modules
  • it would be great to have i.e. courtyard dimensions so I could automate the process more but it can be hardcoded in the openscad
    So I made a simple parser and tried to read report file format. First thing I noticed is that it does not contain all information about package size, only pads. That is not so bad but I really would like to have some information about module boundary so that I could create a generic void for all packages and specific holes for a few known packages (pin headers).
    The second thing I noticed is that the file uses localized names for pad definitions:
    Shape Obdélník Layer both
    The third thing I noticed is that the
    $BOARD
    upper_left_corner 20.291667 25.617116
    lower_right_corner 129.437381 102.387857
    $EndBOARD
    are actually not board dimensions, but some arbitrary points…
    And the last thing I noticed (and it did really made me almost crazy) is that the position specified in the report references the center for all the modules, except for pin headers, where it is referencing pin 1…
    To make a long story short after a lot of fidgeting I did manage to produce working PCB holder but the process is not simple and automatic…
    What would be the best way how to get the required information out of KiCad if I would like to create universal and easy to use tool to create a PCB soldering holder from a KiCad file? Should I learn how to parse gerbers? Should I try to parse KiCad pcb files directly? Create a plugin?

Image of the PCB (I could paste only one image into my first post):

Export your PCB directly from Kicad as .step -> make it thicker so the headers do not come out on the other side -> print it with as less infill as possible -> done.
That’s the easiest way i can think of besides just soldering the headers on without a holder.

*EDIT:
Dough, you said you get it assembled, so you have to clear the smd’s. Above clearly does not work, sorry

Why not importing the pcb + models in FreeCAD and from there create your holder?
You can have a Sketch of the pcb plus all the TH header positions/holes.
That should be enough for your purpose.

1 Like

I could have created some sort of “generic” stand and be done but I decided to try to make it more pcb specific - just for fun. But I did not expect to encounter so many hurdles…

I have a very little experience with FreeCAD. I may try to look into it but I really do prefer Openscad as I like the “programming” aspect of it. I would also need to replace most 3D models with cubes as I would like to avoid damaging the PCB or soldering because of wrong 3D model…
The openscad part is really very simple. The core looks like this:
module package(package_family,package_type,arg1,arg2,rotation)
{
if (package_type==“R_0402_1005Metric”) xycentercube ([3,2,2]);
else if (package_type==“C_0402_1005Metric”) xycentercube([3,2,2]);
else if (package_type==“C_0603_1608Metric”) xycentercube( [3,2,2]);
else if (package_type==“LED_0603_1608Metric”) xycentercube( [3,2,2]);
else if (package_type==“LED-4_5050”) xycentercube( [6.8,5.5,10]);

The openscad part is working really nice and I think it is elegant solution but I need correct placement information from KiCad :slight_smile:

i don’t know much about open-scad but would it not be more elegant to create “stands” for the headers and making everything else a cutout than creating x cutouts and leaving the headers? That way you only have to fetch the headers, their dimension and the board outline.

Openscad is great tool for me as I have a programming background. You basically code your 3D model all the way. You can use variables as parameters, so for example you can make the stand really flexible. I.e. the basic shape of holder itself looks like this:
holder_height=15;
pcb_edges=[[0,60],[90,60],[90,0],[0,0]];
linear_extrude(holder_height) scale(1.01) polygon(pcb_edges);

And that is the problem. How would I fetch these information?

is there no way to interact with the surface of a .step? You can also plot you pcb to .dxf for example if thats easier.

I can import dxf or step but I can not interact with it. I mean I can move, rotate, scale, intersect, union, etc but I can not interact with the “content”.

The idea is to make the process as much automatic as possible. So I “waste” some time now by making it automatic but next time I need this for another PCB I just run a few scripts and it is done. This way I can also publish the whole thing on github and it may help others… So as few manual steps needed as possible…

mh~ in that case the only thing that comes to my mind is to use the positional data generated for the manufacturer.
It should be a text file and contain x, y and rotation data as well as an ID so you should be able to identify what is where and deduce the necessary steps from there.

And that is what I started with, see my first post:

Sorry i missed that :blush: skiped to your posts summary.
What’s with directly reading the kicad-pcb file, there are at least the positions in there as well as detailed information about the footprint. Also ther should be a lpath to the footprints .step so you can grab that, scale it and subtract it or whatever.

  (module Connector_USB:USB_Mini-B_Lumberg_2486_01_Horizontal (layer F.Cu) (tedit 5AC6B535) (tstamp 5DE2FE1E)
    (at 100.19 103.74)
...
    (model ${KISYS3DMOD}/Connector_USB.3dshapes/USB_Mini-B_Lumberg_2486_01_Horizontal.wrl

I briefly looked into it and it seems to be similar to the report export but more complex. And with () used for delimiting information :frowning: . And with omitting the default values. i.e. when there is no rotation, the at looks like this:
(at 48.00154 82.05426)
and when there is a rotation like this:
(at 103.0986 42.01668 270)
there are no board dimensions, only lines for edge cuts, so I would need to calculate the shape - which is an interesting exercise on its own :
(gr_line (start 36 100) (end 126 100) (layer Edge.Cuts) (width 0.05) (tstamp 5DD4A74E))
but again, all the modules reference the middle of the package, except for the pin headers. These inconsistencies drives me crazy… But at least it seems that the rotation center is always at 0,0…
So the benefit over the report export is that it does contain the edge cuts and courtyard lines and the downside is that it is more complex to parse… But maybe I will try to write the () parser and see how it will work… I really do not get why people create their own formats instead of using one of bazillion already existing formats like xml or json…

…some info…

FreeCad does have a Python input/programming panel and you can program there.

Loading KiCad’s PCB is as simple as selecting the StepUp Workbench and opening the PCB file (nothing to to do except open it).

Missing models… for a fixture, you probably care only about the outer shape and a few necessary details. So, making a reasonable representation/model isn’t a big deal.

Making the Fixture:
It can be as simple/similar as making a Mold in that, you have Three things to do:

  1. Create a shape (say a box) to represent your fixture.
  2. Load the PCB and Boolean Fuse the electronic parts you want (to get a single object).
  3. Boolean Subtract the fused part from the box.

Result: a Box (fixture) with pockets representing the part shape

Naturally, you’ll add/design other stuff but, that’s the basics of a starting point with this approach.

Below is a very Quick and Crude example. I did not video the steps of making the box and did not bother to position stuff for clean showNtell… Also (important): I have several 3D printers and various filament types - they all shrink just enough such that it will be important to scale-up the Box/fixture by (let’s say) 1.2%

480Out.mov

I would take another approach.
I would start by mating Male & Female connectors and then sandwitch them between 2 boards, and then solder the connectors to both boards.
One of the boards will then be re-used as a template only to solder more boards.

This has the added advantage that if you are less likely to deform the connectors if they are mated during soldering.

1 Like

Maybe this is one of those things that @HiGreg 's KiCommand is very good at ? AFAIK you can retrieve all the footprints in a board, all pads from the footprints, calculate centroids, etc, the only thing I do not know is if you somehow can send all this information to a CSV for working on it with another tool.

KiCommand may very well be able to do this.

For what it’s worth, KiCommand has an fprintf command:

fprintf (Category: Output) 
	[LISTOFLISTS FORMAT FILENAME] Output to FILENAME each list
	within LISTOFLISTS formatted according to FORMAT in Pythons
	{} string format
	(https://www.python.org/dev/peps/pep-3101/). 

I’m trying to work out the commands to print reference text, x, y, width, height to a CSV file.

Edit: I’ve worked out the following (and updated KiCommand on github to add the ‘escaped’ command):

  • clear modules copy referencetext list swap GetBoundingBox call copy GetCenter call zip swap copy GetWidth call list swap GetHeight call append extend extend zip “{},{},{},{},{}\n” escaped output.txt fprintf

This outputs each module with
reference, x, y, width, height

Outputs the following for the complex_hierarchy demo board:

P5,182012500,97526000,13570000,11250002
P6,96252500,87386000,13570000,11250002
P3,182012500,120386000,13570000,11250002
P4,94982500,114183000,13570000,11250002
P2,96252500,72146000,13570000,11250002
P1,96125500,59446000,13570000,11250002
D9,145482500,93711000,5890000,9800002
D4,141037500,119746000,5890000,9800002
D6,128890000,82363500,9800002,5890000
D7,141672500,93711000,5890000,9800002
D3,131460000,109033500,9800002,5890000
D2,131460000,105985500,9800002,5890000
D8,144847500,119746000,5890000,9800002
D5,128920000,78934500,9800002,5890000
D1,109728000,68393500,15450002,6590000
C3,116118000,109541500,7150002,6770000
C4,116165000,112843500,7150002,6770000
C14,116292000,78045500,7150002,6770000
C12,116165000,106112500,7150002,6770000
C5,140676000,130115500,7150002,6770000
C6,116245000,81474500,7150002,6770000
C7,116292000,84903500,7150002,6770000
C8,140549000,104207500,7150002,6770000
U3,111192500,120381000,13930000,10600002
U1,149292500,68311000,13930000,10600002
U4,111192500,92441000,13930000,10600002
R20,137780000,101413500,9600002,5370000
R22,156912500,93741000,5370000,9600002
R23,106030000,107128500,9600002,5370000
R24,106538000,78807500,9600002,5370000
R25,169530000,123003500,9600002,5370000
R26,160087500,120411000,5370000,9600002
R27,169530000,97603500,9600002,5370000
R28,161357500,93741000,5370000,9600002
R5,169530000,119193500,9600002,5370000
R4,122622500,119141000,5370000,9600002
R3,142860000,109033500,9600002,5370000
R21,102302500,98791000,5370000,9600002
R17,106822000,85030500,9600002,5370000
R7,106030000,112843500,9600002,5370000
R8,122540000,128083500,9600002,5370000
R9,130668000,120209500,9600002,5370000
R10,140574000,126940500,9600002,5370000
R11,102937500,122921000,5370000,9600002
R12,156277500,120538000,5370000,9600002
R13,141590000,86173500,9600002,5370000
R14,141620000,81093500,9600002,5370000
R15,169530000,91253500,9600002,5370000
R16,106792000,82363500,9600002,5370000
R18,121778000,101413500,9600002,5370000
R6,106030000,110303500,9600002,5370000
R19,122286000,95063500,9600002,5370000
C1,109855000,74676000,16637000,3198002
C2,133985000,60706000,16637000,3198002
C9,112395000,60706000,22098000,5230002
C10,147320000,77216000,16637000,3198002
C11,160020000,70866000,3198002,16637000
Q1,131129314,114681000,7293430,6654802
Q2,150179314,115951000,7293430,6654802
Q3,149540686,124856239,7293429,6685281
Q4,132399314,124841000,7293430,6654802
Q5,131129314,88011000,7293430,6654802
Q6,150179314,89281000,7293430,6654802
Q7,149540686,100091239,7293429,6685281
Q8,131129314,98171000,7293430,6654802
RV1,95885000,124337000,7262002,11937000
RV2,95885000,98937000,7262002,11937000
U2,124541280,70231000,10617200,6654802

You could select the appropriate modules with a regular expression (regex command) or another means. Let me know if you decide to go this way and need further input.

This is great idea how to simply solve the problem without using advanced technology :slight_smile: I may go with it but I will not abandon my 3D model thingie neither…

It seems that I need to take a look into FreeCAD and StepUp as it seems to be a really powerful tool. And KiCommand too, I’ve never heard of it…