About me


Parkour gym clock



Orientation Aware Camera

LED Life

OpenGL Experiments

3D Modeling



This is a story of feature creep spiraling wildly out of control, but in a good way. This project started off when my old strobe controller broke. It was just a little box that I could plug into a microphone and a strobe light, and it would trigger a flash when it heard a noise. It had a couple little knobs to adjust sensitivity and delay, but that was really about all there was to it. Though simple, it did its job well enough. It allowed me to take some wonderful pictures of balloons popping, glass breaking, and water splashing. When it broke, I took it apart to see what was wrong, and I was rather surprised to see the kind of old-fashioned engineering that went into it. It was a complex and mostly analog circuit built around a bunch of 555 timers, one of which my testing revealed had been zapped.

It occurred to me that I could rip out half the components in the board, stick a microcontroller in their place, and program it to be even better than before in an afternoon. So I did just that, and it really did just take an afternoon. Then I started thinking it would be nice to be able to use different kinds of sensors with it. And to have more outputs. And to be able to do intelligent things with those extra outputs. And to be able to program it on the fly to do those interesting things. And so on.

Eventually, I ended up designing and building a whole new strobe controller from the ground up. It has a USB interface to program it with, five outputs, two inputs with digitally controlled amplifiers, and even a rechargeable Li-ion battery. I used components I either had on hand or could buy locally as I went along, building it up piece by piece to see where it took me. I designed a very simple little programming language for it, wrote a compiler to run on the PC side, and wrote a virtual machine to run on the device side.

It worked beautifully. My software interacted seamlessly with the hardware, and the hardware let me do tricks no other device could. Already I was an order of magnitude beyond where I started.

I even started experimenting with the new sensor and output options the device supported. I made an exquisitely sensitive contact microphone, found an electric water valve I could use to dispense individual droplets, and started making adapters to connect the device to my camera and flashes.

But then I started seeing limitations. There would still be certain kinds of sensors I could never connect to it, certain elaborate scenarios it wouldn't support. I started looking into more powerful microcontrollers. I noticed there were already similar products on the market. And I realized that I could make mine better than all of them, with some time and good engineering. And not just incrementally better, but hugely more powerful than anything else you can buy. So I started over again, this time designing from the ground up for custom-made circuit boards and much more carefully chosen components. I was determined to squeeze out every last feature I could fit.

So I learned to use Eagle to design my new device, spent weeks trying to think out every detail of the circuit and each component that goes into it, and spent more weeks obsessing over making a beautiful board layout for it.

At this point, though, starting to see what could actually become a sellable product, the software was simply no longer up to the new standard I was setting. I had to start that over, as well. First, I needed to rethink the programming language I designed, and implement a better compiler for it. Rather than limping by with a simple hand-written compiler, I decided it was time to learn to use a proper metacompiler. I settled on Coco/R for its clean syntax, excellent documentation, and surprisingly friendly compiler.

Act II

It's been some months since I wrote the text above. Since then, I've done some good work on the project and got it in a pretty good working state, but I never got it quite to totally polished or 'finished', and certainly not sellable. I did my best to design it to be manufacturable, and I think I did a pretty good job. As it turns out, though, the hard part in trying to manufacture and sell something like this isn't the circuit- it's the case, accessories, and the final polish. To be honest, I lost interest in going that far, let alone figuring out how to sell it.

The PCB came out pretty well. In the center, you can see an MSP430F2274, driven by a 16MHz crystal. Top left are two analog inputs, top center are two buttons, and top right a pair of solid-state relays that connect the two port together. On the left you have an FTDI FT232RL USB-to-serial converter, bottom left a power switch and USB port, and bottom right four output jacks, each with two output pins. Oh, and lots and lots of LEDs; 23 in all.

Unfortunately, this design had a few flaws:

  • Anchoring pads for the switch were soldermasked.
  • Battery connector pins were reversed.
  • I forgot to put a pullup resistor on the micro's #RST pin.
  • When switched off and plugged into USB, the micro is improperly powered through its GPIO pins.
  • One of the analog inputs is connected to a pin that can't be amplified.
  • Output labels are reversed.

I've reworked the worst problems, though, and I was able to make good progress on the software. I rewrote the virtual machine that runs on the micro, and spent an absurd length of time learning Coco/R and developing a fairly robust programming language and compiler.

Yay for structured programming languages! There's a number of nice compiler features here- automatic variable allocation, scoping, variable initialization checking, literal expression reduction, reduction of constant control-flow operations, and more.

Now, what can you do with all this complexity, you ask? Well, the program you see above is what captured this:

This video is actually around 200 separate drops of water, each captured with a slightly different delay between drip and photograph. With a press of button 1, the program coordinates an electronic water valve, a flash, and a camera to take the entire series of pictures over a few minutes.

This is a somewhat more simple example, but one in which being able to tweak timing on the fly was crucial. This is produced by releasing two drops, timed so that the second impacts the splash from the first, and the picture taken at the crucial instant. It took about 45 lines of code.

So where now? There is a lot that could still be done, but I think I'm unlikely to invest much more time into development, at the expense of other projects. I would be happy to see someone else pick up where I've left off, though. To that end, I invite you to download my source code, schematics, and so on, and get hacking.

Download source (.zip, 453K)