Glowforge Aluminum Instrument Panel

I spent some time with the glowforge to test settings for engraving our instrument panels. This is powder-coated aluminum from Hammond. The cases are used in a variety of our projects, but despite cutting holes on the CNC, we haven’t ventured into CNC routing labels and have relied on our tape-based label-maker. It does ok, but laser-engraved labels really up the look. With some time to kill, I ran a few tests on the inside of one panel. The end result is to run with 1000 speed, 50% power, 340 lines-per-inch, and 0.15″ focus height. Continue reading

Pluto SDR (ADALM-PLUTO from Analog Devices)

I picked up an ADALM PLUTO from Analog Devices; a very powerful Software Defined Radio (SDR) for only $99. The cost is low as is the documentation. Many links on Analog site are broken, and to their credit, there are a few comments that “people found these instructions hard to follow, so we are revising them.”

That’s good, but in the meantime, here are the instructions that finally worked for me: at John’s Musings

Bio-Rad Ciphergen PBS-II back to life

That’s a mouthful, but it’s an instrument, for science and stuff. I got a used one from eBay last week, and finally have it set up to where I can actually talk to it over the crude computer interface, it’s been a fun process. I’ll back up: this thing is an analytical instrument from the early 2000s. It is designed to measure the distribution of mass in a sample (such as as a sample of proteins from tissue cells). It does this by blasting the sample with a pulsed UV laser (337 nm, nitrogen), accelerating the charged particles (ions) across a high voltage, and measuring the time it takes them to reach an ion detector a few feet away. The distribution of arrival times is therefore a distribution of charge-mass ratios (a spectrum).

Long story short, it has a whole lot of good physics equipment in it, even if it doesn’t do it’s biology thing very well anymore (though it might…  I don’t have a good sample to test it on). I bought it for the parts, and want to see what it can do. This is an outline of the steps I took to get it working. While it may not apply to anyone else, the tricks are generally useful for hacking on vintage instruments.

This machine originally came with a PC for control, and it communicates via GPIB port. This is not always my favorite platform to work with, but it is here to stay (at least it was in 2000).

I have a prologix USB-GPIB so my first try was to set that up with the machine. It took a while (and a few passes through the manuals) to find the note that the PBSii defaults to address 8. Once that was set correctly, it responded to *idn? with Stanford Research Systems,TOF200,ver045 which was a bit surprising. It turns out SRS was working on a time-of-flight mass spectrometer (similar to this) at that time, and must have been selling time-of-flight boards for OEM use. I pulled out the TOF board to take a look, and noticed that it connects to the master box via a cable labeled “SPI”. Despite being an actual protocol, I think this refers to “Serial Port Interface” as the manual has that phrase in a few locations (but no real information beyond the name). There are a few GPIB commands listed in the service manual, things like how to read and set various registers, but nothing very high-level (the design relies on the software for all of that). I didn’t try those commands right away because without knowing what they did… I’d risk setting the machine into some odd state or enabling a subsystem that I shouldn’t.


The SRS time-of-flight controller embedded in this instrument. GPIB chip (NAT9914) hiding under the top left ribbon cable.

Talking over GPIB was encouraging, but I still had no control over the vacuum system (or any readings from the gauges and various system status indicators). When it powers on, I could hear valves snapping open (or shut) and the pumps would start up; it clearly had a turn-on sequence and everything at least appeared to be working at this point.

After a few emails to the company, including an initial response to the effect of “that machine has been unsupported for over a decade,” I was sent a zip of the original software utilities. Lesson 1: the sooner you can get to an engineer in the company, the better. Find someone like you who enjoys diving in and isn’t afraid of the hardware-software boundary. Unfortunately, the software didn’t see my USB interface as a GPIB (why would it, its just a serial port). I couldn’t yet use the utility software. Sure, there may be some way to trick it into sending GPIB to the serial port, but a more direct route would be to revive some appropriate-era hardware.

The next step was to track down a PC with a GPIB card capable of running the windows utilities. They were written for Win2000 so I figured anything from NT to XP should work… and maybe even later. I borrowed a dusty XP machine from a colleague’s lab for some debugging. In that era of windows, there is an option for “Remote Desktop” which is nice, so I can check on things from outside the lab. Lesson 2: if you don’t want to be stuck in the same room as the machine for a week, set up VNC, remote desktop, or some other way to remotely check in on it

Fortunately everything fired up without a hitch, and the utility software started reporting status and accepting commands. At first, it reported the MAG gauge (high-vacuum gauge) at 0 volts, and turbo pump speed as LOW. Additionally, the backing valve was showing OPEN even though all valves were listed as commanded CLOSED. This was concerning, but not surprising given that it’s probably been sitting for at least a couple years. I cycled the power and the next time around both gauges were alive, and the turbo pump spun up to report OK. In retrospect, I should have followed the shutdown routine to make sure valves were properly closed and the turbopump was allowed to spin down before anything was vented. It seems to have defaulted ok, and the turbopump took a long (quiet) time to spin down. A good sign given the fact that turbos can be seriously damaged if vented too quickly.

Screen Shot 2018-10-21 at 12.18.58 PM

A screenshot of the utility software reporting the current status.

Now I’m at the hurry-up-and-wait stage of pumping down to 1e-6 Torr at which point I can fire up the high voltage and laser systems. I’ve only worked with a handful of vacuum systems (back in grad school) but I did remember that it’s useful to have a reference pumpdown curve… so I started charting away. This is where Remote Desktop really helps. I’d log in every so often to peek at the reported pressure. After 12 hours, it’s gone from roughing to 5e-6 Torr. The operating target is 1e-6, so we still have a ways to go. The flight tube had been open to atmosphere for who knows how long, so I suspect a bake-out is in order, and likely a replacement seal or two (rubber o-rings have a limited lifespan, especially in surplus storage warehouses).

Overall, it’s pretty cool to have something like this come to life even just to this level. At the very least, I got an operational high-vacuum system for $750 plus freight. Lesson 3: a lot of instrumentation is built from generally-useful parts. Such instruments become useless to the intended users even if only one tiny part stops working. Even worse, they become obsolete only through lack of software support. eBay is your friend, but you may have to battle your business office… mine requires personal payment and will only reimburse after equipment arrives on campus.

I owe a shout-out to Erik Sanchez from PSU who tipped me off on this amazing used-equipment find and sent me many helpful documents. Also thanks to Windell Oskay for a helpful conversation as I was starting out. He spent time as a hardware engineer at SRS, and gave me some insight on their hardware implementation of GPIB (using the NAT9914 chip).

Update: After about 48 hours, it wasn’t going below 3e-6 Torr so I started through the various seals and valves. There are several, all too specific to worry about here, but I cleaned the main sample seal o-ring with isopropyl alcohol, and cleaned out the two valves that vent the flight tube to higher pressures (one to atmosphere, one to the backing pressure). At this point, 12-hours later, it’s down to 1.2e-6 (closer!). I’ll give it a day, and see how it looks. Bottom line, the turbopump seems to be in working order (knock on wood) despite me absent-mindedly venting to atmosphere for a few seconds (doh!).

Projects I’d Love to Do

I’ve neglected this site for a bit, and will try to revive it by dumping the contents of my growing list of things I’d love to do if I could make 24 more hours in the day. Why share this? Because if someone else out there wants to work on one of these too, then that serves as extra motivation for me. Also, putting it out in the universe makes it a bit more real than if it sits in my head all the time. I’ll probably revise and will hopefully provide updates as warranted. These are not things that have to be done for the sake of humanity, or things that would even merit a paper or other substantial scholarship (which is probably why they keep getting pushed further down my list). That doesn’t mean they aren’t worth doing. Some lean toward personal projects, others are obviously aligned with my work. Here goes, in total random order:

  • Build a spatial light modulator from an old projector. Note: this has been done before, but I want one, and it sounds like a really fun project that touches on re-use, optics, electronics, and hacking (four of my favorite things!)
  • Directly image the output of a parametric down conversation crystal. Sure, we’ve seen pictures and this isn’t really new knowledge, but I think it really helps students understand what’s going on if you can watch it live. There are a lot of tricks to get this to work, but doing it on the cheap and easy would be sweet.
  • Demonstrate laser-to-RF mediated by at atomic medium. It’s all just E/M radiation, there has to be a fun demo in here somewhere. Are there four-wave mixing transitions that would generate RF that you could tune a radio to? I’ve yet to check this, but it would be cool if it worked.
  • Get my HAM license. I’ve studied up and everything, but just need to get to an exam session and do it.
  • 3D-print a working external cavity diode laser. I have some partial designs, just need to print and test the darn thing.
  • Part out an old argon laser system. I salvaged a laser slit lamp system from our college of optometry. It has all sorts of fun electronics, lasers, optics, and other parts. It doesn’t work anymore, but lots of it’s parts surely do.
  • Other stuff… to be added when I think of it, I’m sure it’s in my head somewhere.

In the meantime, feel free to comment on any of this. If you’d also like to work on something here, let me know.


This is a very cool visualization, and I will continue to play around and explore various parts of the country. One thing I noticed immediately, due to where I live, was an interesting consequence of the algorithm. According to the model, there are several very large buildings nearby (see the outskirts of Forest Grove in the picture).Screen Shot 2018-10-12 at 5.30.04 PM

There is one cluster in the lower left (near Ritchey Rd) and another in the upper right near Schefflin. These are not really buildings, they are hoop-houses. Structures made of only plastic sheets and a few metal pipes. You could argue this is nit-picking, and I’m fine with that characterization. But I’d love to press the issue and ask what would it take to train a neural network better… so it knows the difference between what you and I would call a building, and what merely looks like a building from space.

To be more clear, here is a picture of the Ritchey Rd area:

And a full-zoom of the satellite image, corresponding to the top left (northwest) portion of the nursery (the NYT article doesn’t zoom in from here):

Screen Shot 2018-10-12 at 5.37.37 PM

Clearly these are structures, but what would be the next step in developing the algorithm to know they aren’t actually buildings (or do you define them as such?). Certainly including some nurseries in the training set would be a first step.

Python with a Cocoa GUI on macOS

I finally had a chance to try writing a native Cocoa interface in python. My test project was based on a post by Adam Wisneiwski (though I had to use the cached google version due to a bad gateway error). In that post, Adam laid out the process to put together a basic python app that uses a native cocoa GUI created in Xcode. Given the updates to Xcode, and the fact that I’m using anaconda python, I figured I’d repost my process, with the modifications I made to get it to work in case it is useful for anyone else (and so I can remember how I got it to work).

First, some background: I have anaconda python installed in my home directory, so I had to add some packages so python can connect with the Mac Cocoa framework. If you are just running vanilla python that comes with your Mac, then you shouldn’t need to add anything. Test your setup by trying to import Cocoa in python. In my case, that didn’t work until I installed two packages:
pip install pyobjc-core
pip install pyobjc-framework-cocoa

I didn’t find these with conda on conda-forge so it was a job for pip. Once these are installed, you should be able to import Cocoa and import Foundation in python. Next, it’s time to check for py2app. This step was new to me (I haven’t used py2app before), but I figured it would work best to have this installed in the python environment I plan to use, so once again, let pip do the work: pip install py2app. After that, you should be able to run py2applet on the command line and it will return a default help message. We’ll use this utility to create a file for the application, and bundle it.

First, put the following application code into a file named

from Cocoa import *
from Foundation import NSObject

class SimpleXibDemoController(NSWindowController):
    counterTextField = objc.IBOutlet()

    def windowDidLoad(self):

        # Start the counter
        self.count = 0

    def increment_(self, sender):
        self.count += 1

    def decrement_(self, sender):
        self.count -= 1

    def updateDisplay(self):

if __name__ == "__main__":
    app = NSApplication.sharedApplication()

    # Initiate the contrller with a XIB
    viewController = SimpleXibDemoController.alloc().initWithWindowNibName_("SimpleXibDemo")

    # Show the window

    # Bring app to top

    from PyObjCTools import AppHelper

Next, we can start to package this app by creating a file using py2applet:

py2applet --make-setup

Notice that you call this with the name of the python application file. The file generated should look like:

This is a script generated by py2applet

    python py2app

from setuptools import setup

APP = ['']

    options={'py2app': OPTIONS},

You’ll want to associate the application with an xib file (i.e. the GUI side of things). Just add the filename (although we haven’t made the actual file yet):

DATA_FILES = ['SimpleXibDemo.xib']

Just be sure to name your XIB file accordingly when the time comes (that step is coming soon).

Now it’s time to fire up Xcode. I’m using Xcode 8, on macOS Sierra, things should be similar on earlier versions, but Xcode has evolved a bit over the years. I still have the Welcome widget enabled on Xcode, so the quickest way to get what I wanted was to “create a new Xcode project”, and choose “cross-platform” and “Empty”. We don’t need much in this project, but make sure to save it in the same folder where you created and

Next, create a new xib file for the app window. The menu path is File→New→File… and under macOS in the User Interface category pick Window. For a filename, type in SimpleXibDemo and it should add the .xib extension. Next, add your .py file to the listing for Xcode: File→Add files to “Project”… Select your file If you open this file in Xcode, you’ll see some decorators that let Xcode know how you will interface with it: @objc.IBAction indicates a function that you want to receive an action. You’ll also notice that the python script instantiates an outlet for the interface and calls it counterTextField: counterTextField = objc.IBOutlet() This will be the recipient of actions within the script.

To lay out the GUI, drag three buttons onto the window from the Object Library (lower right side by default). You can change the text that appears on the button by double clicking.

Next, we’ll associate the quit button with the terminate action. Ctrl-drag from the button over to the FirstResponder. In the pulldown, choose terminate, this will associate the quit button with ending the program.

Next, we have to associate the window with the python class that it represents, and link the buttons to the appropriate IBActions. Note that it is important the class specified in the File’s Owner matches the python class in the .py file. In the code above, that is SimpleXibDemoController so click on the top icon to the left of the workspace (File’s Owner) and then choose the Identity Inspector (likely the third-from-left in the right-side pane). Enter the class name in the top field (Class). This associates the window with the class that will handle actions. Finally, Ctrl-drag from the “-” button to the File’s Owner and select the decrement action. Do the same from the “+” button but pick the increment action. This connects the two buttons to the corresponding class functions.



Finally (as shown below), add a label to the center of the window and ctrl-drag from the File’s Owner to the label. In the pulldown, choose counterTextField (which should be the only option). This links the label in the GUI to the counterTextField in the python code.


Save the .xib file and we’re ready to build the app. From the command line, run:

python py2app -A

You can then run it from the command line as: ./dist/

Note: it may not work just yet. I had to change the file to point to the right python executable (this comes from using a local anaconda python instead of the built-in Framework python).

This is a script generated by py2applet

    python py2app

from setuptools import setup

APP = ['']
DATA_FILES = ['SimpleXibDemo.xib']

OPTIONS = {'argv_emulation': True,
           'plist': {
               'PyRuntimeLocations': [

    options={'py2app': OPTIONS},

Where I added the plist to the OPTIONS variable and made sure to provide the path to libpython3.6m.dylib (select the path to the dylib that matches your runtime python version). If you use anaconda, then it should be similar to the path above though your username is probably different.

With this change, run
python py2app -A
once more, and then try the app again:

I’m pretty new to all this, but feel free to let me know if you have trouble getting it to work and I’ll do my best to help.