Can't get Silkscreen to draw properly when using python scripting [Solved]

Hi,

I’m trying to automate gerber generation of my kicad_pcb file. I’ve followed instructions and troubleshooting on this forum.

It kinda almost works, but I don’t get the same plot for some layers when using it from the KiCad software using File > Plot and python scripting.

Here is the python script I’m using:

   board = pcbnew.LoadBoard ('power.kicad_pcb')
   pctl = pcbnew.PLOT_CONTROLLER (board)
   popt = pctl.GetPlotOptions ()
   popt.SetOutputDirectory ('gerber_test'))
   popt.SetPlotFrameRef(False)
   popt.SetLineWidth(pcbnew.FromMM(0.1))

   popt.SetAutoScale(False)
   popt.SetScale(1)
   popt.SetMirror(False)

   popt.SetUseGerberAttributes(True)
   popt.SetUseGerberProtelExtensions(True)

   popt.SetExcludeEdgeLayer(True)
   popt.SetUseAuxOrigin(False)
   pctl.SetColorMode(True)

   popt.SetSubtractMaskFromSilk(False)
   popt.SetPlotReference(True)
   popt.SetPlotValue(False)

   layers = [
      ("F.Cu", pcbnew.F_Cu, "Top layer"),
      ("B.Cu", pcbnew.B_Cu, "Bottom layer"),
      ("F.Paste", pcbnew.F_Paste, "Paste top"),
      ("B.Paste", pcbnew.B_Paste, "Paste bottom"),
      ("F.SilkS", pcbnew.F_SilkS, "Silk top"),
      ("B.SilkS", pcbnew.B_SilkS, "Silk top"),
      ("F.Mask", pcbnew.F_Mask, "Mask top"),
      ("B.Mask", pcbnew.B_Mask, "Mask bottom"),
      ("Edge.Cuts", pcbnew.Edge_Cuts, "Edges"),
   ]

   for layer_info in layers:
      pctl.SetLayer (layer_info[1])
      pctl.OpenPlotfile (layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2])
      pctl.PlotLayer ()

   pctl.ClosePlot()

With this script, and apart from Edge.Cuts also, every over layer (F.CU, etc.) is fine.

But I get the following. On the left is what File > Plot gives, and on the right what the python script gives.

What’s happening? What’s wrong with my code?

I’m using KiCad Version 4.0.7 release build

Thanks,

Raphael

I don’t know that it will fix your problem, but you should upgrade to V5 stable.

You will likely get much quicker replies as 4.0.7 was released about a year ago and the members here are not likely to remember all the changes since then.

Hi Sprig,

Thanks a lot for your reply. I didn’t see that v5 was officially out and that seems to be the first thing to try.

Thanks,

Raphael

You have a typo here

popt.SetOutputDirectory ('gerber_test'))

Should be

popt.SetOutputDirectory ('gerber_test')

The image on the left looks like the Fab layer rather than the silkscreen. This is missing from your stackup. Try adding

("F_Fab", pcbnew.F_Fab, "Fab top"),

to your layers list.

The edge layer may not be showing as you have set

popt.SetExcludeEdgeLayer(True)

You might investigate the effects of altering these parameters - not sure if they actually do

   popt.SetSubtractMaskFromSilk(False)
   popt.SetPlotReference(True)
   popt.SetPlotValue(False)

Hi John,

The image on the left looks like the Fab layer rather than the silkscreen

Actually it is really the silkscreen. But the image on the right is definitely not the silkscreen.

The edge layer may not be showing as you have set

Yes, that’s on purpose. I wanted to have the edge in the *.gm1 file like when I use File > Plot.

All in all my main concern is that doing the plot manually and using a script to automate it (and being more consistent) proves to be less efficient for the moment. But as Sprig first noted, I’m going to upgrade to v5 first.

Thanks,

Raphael

I have tried your script in a fairly recent nightly (pre official 5.0) on macOS and it runs fine. I am getting the expected outputs from the SilkS layers (as well as the other layers). I agree with @sprig that it would be best to try updating to V5. I know there were some significant changes to the plotting routines API in v5 but I am surprised this didn’t return the correct plot for the silkscreen when everything else was OK.
55

Hi John,

That’s very good to know! Many thanks for trying it out.

I’m in the process of upgrading (reading how to upgrade, backing up, etc.), I’ll come back to this thread if I have still a problem with my script.

Thanks again,

Raphael

@John_Pateman Did you run my script from the Kicad scripting console or from MacOS X Terminal?

I’ve used the trick to copy python next to pcbnew to avoid the problem of relative paths when loading images through dlopen, but upgrading to Kicad 5 seems to break it:

raf$ cp /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python /Applications/Kicad/kicad.app/Contents/Applications/pcbnew.app/Contents/MacOS/python
raf$ cd /Applications/Kicad/kicad.app/Contents/Applications/pcbnew.app/Contents/MacOS
raf$ ./python 
Python 2.7.10 (default, Feb  7 2017, 00:08:15) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys  
>>> sys.path.insert(0, "/Applications/Kicad/kicad.app/Contents/Frameworks/python/site-packages/")
>>> import pcbnew
Fatal Python error: PyThreadState_Get: no current thread
Abort trap: 6

And the relevant lines in the crash log (so at least it’s apparently trying to load pcbnew bindings)

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fffbe26cd42 __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fffbe35a457 pthread_kill + 90
2   libsystem_c.dylib             	0x00007fffbe1d2420 abort + 129
3   org.python.python             	0x0000000110b65671 Py_FatalError + 49
4   org.python.python             	0x0000000110b64a2c PyThreadState_Get + 28
5   org.python.python             	0x0000000110b607fe Py_InitModule4_64 + 62
6   _pcbnew.so                    	0x000000010eaabc70 init_pcbnew + 800
7   org.python.python             	0x000000010e106130 _PyImport_LoadDynamicModule + 140

Ah so for what it is worth:

Fatal Python error: PyThreadState_Get: no current thread means that the version of python I’m using is not binary compatible to the library that was used to make the bindings (source: http://doc.aldebaran.com/2-1/dev/python/tips-and-tricks.html#fatal-python-error-pythreadstate-get-no-current-thread)

Cool thing is that the right version of python is here:

/Applications/KiCad/kicad.app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python2.7

And using this version, the problem with dlopen is solved.

So now I just need to add at the top of my script:

#!/Applications/KiCad/kicad.app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python2.7

To run with the correct python interpreter.

And if it was not all, the output of the script is now exactly what I was expecting!

Thanks much @Sprig and @John_Pateman for helping me solving this!

Raphael

That is exactly what I do with Python scripts that need access to pcbnew. Put the full path to the Kicad Python in the shebang line and the do a sys.path.insert to get to the Kicad site packages.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.