MHV Space Probe
angusgr — Sat, 21/05/2011 - 12:51pm
Before we had the Space Probe, people would write to the mailing list - but it's easy to forget to email, especially if you came in to work on non-computer-centric projects or if you need to leave in a hurry.
The Space Probe is made out of a laboratory power supply that I spotted in a dumpster. It looks like this:
Update Dec 2012: Space probe is no longer wireless Bluetooth, it's now wired in and uses a Freetronics EtherTen as an HTTP server, for a simple web API. More info. The client is still a Lua program though. I (Angus) forgot to take any photos of it while it was apart, so I can't provide updated info on the internals. It looks a lot less bodgy than the revision documented here, though!
The server-side portion of the Space Probe configuration at MHV is documented on the space wiki.
Technical summary: inside the probe enclosure is an Arduino clone connected to a $9 Bluetooth serial module from ebay. The probe talks over Bluetooth to our wireless router running OpenWRT. On the router is a program written in Lua, which performs all of the probe's functions. Source code is all online here, usage information & rambly build details are below.
If you prefer, here is a video about using the Space Probe:
There is only one way to interact with the probe, the knob on the front:
- When you open the Hackerspace, set the knob to the number of hours that you think the Hackerspace is going to be open. The probe will tweet & email that the space is open:
The MHV space is now open for approximately 3 hours (~12:29)
- If the estimate changes (maybe someone else shows up), then you can move the knob again - this time to the number of hours (counting from that moment) that you now think the Hackerspace will be open. The Probe will send an updated message out.
- When you're closing the space, set the knob to zero. The Probe will send out a message that the space is now closed.
That's it for input!
The Probe also sometimes needs to tell you something. I considered a wide range of trendy interaction options such as an AMOLED capacitative touch screen, a speech synthesizer, nixie tubes, seven-segment displays, VFDs, LCDs or telekenesis. Based on a very rational selection process (convenience), I chose a somewhat inaccurate panel meter, a speaker that makes annoying buzzing sounds, and an RGB LED hidden underneath a red cover.
- The inaccurate panel meter counts down the number of hours left (masquerading as Volts.) Unfortunately it's extremely inaccurate (essentially random) below 2, which is the time when it would probably be most useful! Serves me right for reappropriating 1950s-era Swiss power supply technology.
- The speaker buzzes to remind you when you said you'd be leaving soon. It's not very loud, but if you can hear it then it's guaranteed to annoy you. Buzzes for increasingly longer periods as the time draws closer.
- The LED blinks red if it can't contact the probe controller base station. This implies something has gone horribly wrong.
- The LED blinks green (green LEDs under red covers look cool) if it's trying to send emails or tweets. If the internet is flaky then it can blink green for quite a while...
- The LED blinks blue (which looks purple through the red) when you said you'd be leaving soon. This coincides with the aforementioned annoying buzzing.
- The LED glows green when the space is open. I was thinking of implementing the nice soothing "breathing" glow that Apple uses on their products, but I never got around to it. Probably for the best, I hear Apple has a patent on that anyhow.
... that's all the communication modes! Unlike to win UX Design of the year, but it does the trick.
(The space probe was built by me, Angus, but I'm donating it to MHV so it can be further hacked on by members. Please let me know if you'd like any pointers on further hacking.)
The MHV Space Probe has three components - the Probe Hardware itself, the Probe Firmware (Arduino sketch), and the Controller software (written in Lua.)
The Space Probe started life as a power supply built by Wild Heerbrugg, Switzerland. I imagine it was brand new well before 1970. It appears to have lived a good life as a variable-voltage power supply in a laboratory, before eventually being declared obsolete and thrown out. I found it in a dumpster near my work. How could I resist such build quality, not to mention the gorgeous Hammerite finish?
(An interesting aside, the rotary switch on the back of the supply allows the operator to choose from 5(!) different mains input voltages! The switch selects which of 5 taps is connected on the primary coil of the transformer.)
Inside the supply is a brilliant piece of mid-20th-century engineering. I would feel guilty about misappropriating it, if it wasn't so clearly outmoded. As the operator dials in the output voltage on the faceplate knob, they are physically moving a wiper across the face of the variable transformer inside:
Brilliant! (I still have the variable transformer, I have some half-assed plans about building a PID feedback loop around it using a microcontroller and a servo - you tell it the desired output voltage and the control loop on the micro automatically adjusts the transformer to keep the output stable regardless of load!)
(OK, enough distracting asides. Nothing but Probe building from here on. Probably.)
After removing the transformer (which was literally the only component inside the box), I refit the power supply with a DC jack allowing it to be powered from a 12v DC adapter, and a Seeeduino (Arduino Duemilanove clone).
This Seeeduino has been modified with an ebay Bluetooth serial module connected to pins 2 & 3, and powered from the Seeeduino's onboard 3.3v regulator. This is the same Seeeduino+Bluetooth combo that I used in the Robosapien post.
Here's a schematic showing how the Seeeduino is wired up:
After breadboarding the functionality I needed, I fell into a terrible cognitive trap: "This is really simple, so few components, I'll just air-wire everything the quick and dirty way." Bad Angus! It would have much quicker, cleaner and simpler for me to use a piece of perfboard or a Protoshield, or even migrate the few components to the prototyping section on an MHVBoard.
First, I drilled out the bulb socket under the red light cover (it had been an AC mains incandescent bulb) and used polymorph to mount my RGB common-cathode LED, then attached the current limiting resistors:
Then I mounted a potentiometer to the back of the faceplate, and wired the 0-10v panel meter to the FET. Everything is wired directly to inline headers, to plug into the Seeeduino. Once again, this is not a wise course of action! Buying a cheap protoshield for components is much cleaner and easier!
Look upon my messy airwire soldering works o ye mighty, and despair!
The Seeeduino was then mounted to a sheet of plastic, which I tied into the enclosure using the old output bus bars (bottom-right in photo) as mounts. Hacky, but secure.
To my great relief, the Bluetooth signal was still clean even when working through a solid metal box!
Another thing to note is that the RX signal pin on the Bluetooth module is being driven with a 5v high level, not 3.3v, from the Seeeduino. So level shifting those signals may not be necessary.
The probe firmware is an Arduino sketch. (Source code link.) It is designed to be the "thinnest" firmware possible, all it does is exchange simple ASCII commands with its controller, over the Bluetooth serial link. All of the smarts, including things like lookup tables for hardware values, is implemented on the controller side. The command protocol is documented at the top of the sketch file (see link.)
Continuing the theme of "quick & easy", the code uses almost no features of the microcontroller at all. Apart from using PWM to dim LEDs and the Arduino NewSoftwareSerial library (which uses a timer interrupt), all the other features (including toggling the speaker output to produce a buzz) are called from a single synchronous main loop. While this might make a microcontroller enthusiast's hair stand on end due to the raging inefficiency and inaccuracy, it meets the Space Probe's simple requirements and it keeps the code simple, too.
If the Space Probe was ever going to add significantly more functionality on the firmware side, then more complicated programming techniques - maybe even a more efficient library like MHVLib - would be required.
The controller software is designed to monitor the probe's state (via Bluetooth) and send out tweets and emails when required. Fairly straightforward stuff.
Crucially, the controller has been designed to run on an embedded Linux system. Specifically, the space's wireless router - an Asus WL-500gP running the OpenWRT Linux distribution:
(Please excuse crappy photo. As you may have guessed from the bodgy second antenna, this is not the first time this router has been targeted by me for a hack!)
To allow the router to communicate with the probe, I attached a Bluetooth dongle to one of the USB 2.0 ports on the back. The router sees the probe as an rfcomm serial device.
Targeting a router put some limitations on software development. My favoured go-to languages for quick clean software development, Python & Erlang, wouldn't fit on the 8Mb flash memory of the router (which is already half full with router stuff.) I decided to try the scripting language Lua, as it is included with the OpenWRT distribution by default and its default installation package is a svelte 200kb.
I wrote the first controller version using only Lua's out-of-the-box library support. This was a mistake. Lua has "no batteries included" - it only depends on standard libc (no POSIX, no sockets, no nothing.) I was able to make the controller work this way by applying liberal os.cmd() shell script hacks. These were needed for such advanced language features as sleeps, I/O polling, and even network access (by invoking 'wget' & 'ssmtp'.) Needless to say, this was all really ugly. That revision is still in the git repository if you want to go and shudder at it.
Upon reaching my senses, I refactored to use the (still tiny) luaposix & luasocket libraries and that code is now fairly straightforward and largely ugly-hack-free.
Because of Twitter's OAuth, the controller still relies on the 'openssl' binary in order to calculate the required HMAC-SHA1 signature. There is a Lua library for Twitter which does this automatically via a Lua library for OAuth, but this ends up pulling in a half-dozen libraries which are not yet packaged for OpenWRT. My NIH solution, "Barebones Lua Twitter", is a module that only requires LuaSocket and the openssl binary to work (with reduced functionality) on very simple systems. It was inspired by a very impressive hack, "shtter", which is a shell script OAuth-enabled Twitter client script that requires only openssl, and either wget or curl, in order to authenticate and send tweets.
Of course, I could have chosen to use C or even C++ instead of Lua. However, I decided that a high-level scripting language was more appropriate and more convenient (no cross-compiler setup) in this case. I'm certain the Lua version has significantly less scaffolding code than an equivalent C program would require. For example, in C the simple FSM encompassing the probe state would probably have required a transition table with associated code to evaluate each state change. In Lua, I can easily leverage tail call optimisation so each state is a function which just executes the next state as a tail call. Similarly, the config file in Lua is just a a plain Lua source file that returns a table. In C I would either need to implement a simple parser, find a parser or config file library supported on OpenWRT, or recompile the whole program (on the host machine) each time I made a simple change.
The full controller software is on github, too.
I should also mention that the controller implements a few Easter Eggs to (hopefully) keep people (or, at least, the author) entertained on occasion...
Overall, testing the space probe has gone pretty well (only a few bugs, and good resilience to our flaky internet connection) and it's had a good reception. I hope it will remain useful for MHVers.
It's also been a good instructive experience for me, a reminder of how even a very simple concept can require design time & effort. I'm glad I built it, and it was still very easy in the greater scheme of things, but I wish I'd shaken the "it's so trivial, I don't even need to think about it" attitude from the very beginning. Nothing is ever quite as trivial as you think.