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
    upper_left_corner 20.291667 25.617116
    lower_right_corner 129.437381 102.387857
    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?
1 Like

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.

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:
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%

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) 
	within LISTOFLISTS formatted according to FORMAT in Pythons
	{} string format

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:


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…