Monday, May 13, 2013

Embedding python in Mac OS X

I have been trying to figure out how to embed Python on the Mac. Trying the simple example found at,

#include <Python.h>

main(int argc, char *argv[])
  Py_SetProgramName(argv[0]);  /* optional but recommended */
  PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
  return 0;

I got the error message that Python.h couldn't be found:

$ gcc test.c
test.c:1:20: error: Python.h: No such file or directory

Adding the header files to the search path then led to a linking problem:

$gcc -I /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Headers test.c 
Undefined symbols for architecture x86_64:
  "_PyRun_SimpleStringFlags", referenced from:
      _main in cch6pSfx.o
  "_Py_Finalize", referenced from:
      _main in cch6pSfx.o
  "_Py_Initialize", referenced from:
      _main in cch6pSfx.o
  "_Py_SetProgramName", referenced from:
      _main in cch6pSfx.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

The all knowing Google was of limited help-- I could not find an explanation for how to embed python on the Mac platform. After divining the error message tea leaves, and pouring over man pages, I have finally found out how to EMBED PYTHON ON THE MAC!! (cue 2001: A Space Odyssey theme!)

The magic incantation is

gcc -I /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Headers -L /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib -lpython2.7 foo.c

I have macports python installed, but if you don't, you will need to change the "/opt/local/Library..." to "/System/Library..."

The -I option adds a directory for finding header files. The -L adds a directory for finding lib files. The -lx option loads the library file named libx.dylib.

I then added a bash alias:
alias pygcc='gcc -I /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Headers -L /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib -lpython2.7'

I can now invoke the compiler using
pygcc foo.c

Another thing I found out is that the current directory is not in sys.path. You therefore can't load modules that are in the current directory. You can add the current directory by adding PySys_SetArgv(argc, argv); after the call to Py_Initialize(); so that it looks like:

PySys_SetArgv(argc, argv);    //adds current directory to sys.path

Update: It seems that there is a slightly easier way to add the proper include and library directories using the python-config command (which doesn't have a man page on Mac OS BTW). Calling python-config with --includes --ldflags returns the appropriate options for gcc:

$ python-config --includes --ldflags
-I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
-L/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -ldl -framework CoreFoundation -lpython2.7 -u _PyMac_Error /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python

So you can shorten the gcc incantation to:
gcc `python-config --includes --ldflags`
and shorten the alias to
alias pygcc='gcc `python-config --includes --ldflags`'

Sunday, May 5, 2013

Solder stencil using Shapeoko

I purchased two Sick of Beige Bus Pirate v4 from schazamp on the DangerousPrototypes forums a couple of months ago and have been dragging my feet assembling them. I used hand soldering for the SMD parts on my DIY Bus Pirate v3 but for v4, I wanted to try making a solder stencil and reflow using a hot air rework station. There have been several articles recently about etching copper and aluminum stencils and also a recent article about using a Cricut to cut a stencil out of overhead transparencies.

I recently built a Shapeoko and wondered whether it could be used to make solder stencils.

I used the Eagle CAM processor to output the tCream layer as a HPGL file. I then used a GNU hp2xx to convert the HPGL file into SVG. (It took a bit of tweaking to get hp2xx to compile on Mac OS X 10.7.)

The command

hp2xx -t -m svg tCream.pltd

will convert the .plt HPGL file into a SVG file which looks like this:
I then used Illustrator to make 0.039" circles to approximate the holes from a #61 size drill bit. I used a red fill and a small stroke to make things easy to see and keep track of but the color and even the size of the hole don't really matter-- only the center coordinates are extracted. I tried approximating the drill hole area to the area of the pad. Big pads were filled with several holes. The small pads on the TQFP chip in the middle were a bit of a challenge. I guess I could have put a drill hole in the center of each pad but ended up with a staggered line of drill holes. The end result looked like this:

Then came the task of turning the red dots into something I can send to the Shapeoko. I used the python svglib library to read in the modified SVG file and spit out all the circle coordinates. This part was surprisingly easy but kludgy. The SVG file is read into something called a ReportLab format and I had some difficulty figuring out the class/data structure-- if anyone knows of a better/cleaner/more robust way of evaluating/interrogating the report lab object, I would appreciate the help (my python introspection-fu not strong).

import svglib

dr = svglib.svg2rlg('tCream.svg')

print "G20 G17 G40 G49 G64 P0.005 G80 G90 G94"  ## magical gcode incantation to start
print "G1 Z0.15 F10"    ##lift before moving!!

for i in dr.contents[0].contents:
    if i.__class__.__name__ == 'Circle':
        #print "circle at %f, %f"%(,
        print "G0 X%f Y%f"%(,
        print "G1 Z-0.05 F15"
        print "G1 Z0.15 F15"
print "M5\nM2"  #magical gcode incantation to end

The result was a gcode program I could send to the Shapeoko:
G20 G17 G40 G49 G64 P0.005 G80 G90 G94
G1 Z0.15 F10
G0 X0.685014 Y0.568389
G1 Z-0.05 F10
G1 Z0.15 F10
G0 X0.708736 Y0.603111
G0 X1.160417 Y0.848500
G1 Z-0.05 F10
G1 Z0.15 F10

All told, 270 holes to drill-- took about 20 minutes (I ended up breaking two drill bits). Might be able to speed things up a bit using a traveling salesman algorithm but the order extracted from the SVG file is not too bad. Here is a link to a video of the Shapeoko in action. And a picture of the completed stencil.

The whole process is surprisingly quick and easy. Drawing the circles is slightly tedious but only took 5 minutes for this small board so not too bad. Some of the pads are a bit wonky-- after the drill bit(s) broke, I rezeroed the Z axis with a new drill bit and ran the gcode again. Some of the holes have actually been drilled three times. Overall the registration between the runs was very good-- the registration between the stencil and the board is quite good. I can't wait to try it out-- I am waiting for delivery of my Mouser order.