March 21, 2012

Driving multiple Sparkfun 7-segment displays with an Arduino

I'm currently helping a couple of engineering students finish a senior project that didn't get finished last year. Long story... Anyway, it's a bicycle brake tester being built for Paul Components. The mechanical design is great, but they had trouble with the electronics.

Part of those electronics involved writing numbers to a pair of Sparkfun 7-segment displays. There's a lot of discussion on the Sparkfun board about these: apparently they're difficult. I had some issues making them work ---baud rate, for example, which should be set to 9600 in setup() not 2400 as stated in some references--- but it's relatively straightforward once those issues are straightened out. Here's my code, in hopes that it'll be helpful to anyone else trying to write to several 7-segment displays simultaneously.

The serial TX line (second pin given in the SoftwareSerial declaration) should be connected to the RX pin on the corresponding Sparkfun breakout board; the RX line in the SoftwareSerial declaration should be left unconnected. I've only tested it with two boards at a time, but it should work with as many as you have room for on the Arduino. It works fine for just one display, also!

February 12, 2012

Remote key-switch operation

One of my colleagues, Dr. Shane Mayor, has built a very nice LIDAR system for atmospheric research. It's located at a remote site, at the end of a dirt road, and everything about the system can be controlled remotely except the main pump laser power supply. That supply has a key-switch, which has to be manually turned to activate the system. He asked me to see what I could do to make it all remote-controlled.

Due to the cost of the laser, and Dr. Mayor's unwillingness to void the warranty, my suggestion that he just replace the key-switch with a computer-activated relay was met with some resistance. He absolutely did NOT want me to do anything inside that case! So instead, I built a servomotor key-turner.

The basic idea is to use one of the spare digital lines on his main National Instruments control board to signal the servo controller. When the line goes high, the servo turns the key to the 'on' position, and when the line goes low, the servo turns the key to the 'off' position. Any simple microcontroller should be sufficient for the task: rather than commit an entire Arduino board to the job I just used an Attiny85. Still overkill, but it's so cheap that I don't stock anything cheaper in my parts bin anymore!

Here's the circuit:
And here's the board, which I etched using Pulsar's "Fab-in-a-box" toner-transfer paper.

The software uses Ilya Brutman's Servo8Bit library, and I programmed the Attiny85 using MIT's High-Low Tech instructions. Here's my code. There's a 6-pin ISP header on the board (J1), which I use with an Arduino-as-ISP programmer.

I used the top of a scrapped project box to mount the servo directly above the key and hold the servo output shaft coaxial with the key. The actuator consists of a rubber stopper with a slot cut in it, mounted on a servo control arm. The slot in the stopper fits over the key so that the servo turns the key directly.

It took one re-programming cycle to make the microcontroller turn the servo the right direction (what kind of key turns left for on, anyway?) and then a very simple LabVIEW program to control the digital line to the servo, but that's it! Works great.

December 5, 2011

Christmas-tree water-level alert

Update 12/11/11: A fix to the program--- changed to capSenseRaw() instead of capSense(). The problem with capSense() is that it auto-adjusts the output for touch sensing, rather than absolute capacitive measurement. capSense() reports whatever capacitance it observed the first time as zero from then on. This means that if the water level is high when the Arduino is turned on, high will be interpreted as dry... And it's not very convenient to make sure the sensor is outside the tree-stand whenever you first turn the lights on! Kinda misses the point of this whole exercise if you have to take the sensor out, dry it off, turn the lights on, put it back... But using capSenseRaw() takes care of the problem.

One other note: the sensor has to be very waterproof! The 4 coats of polyurathane were marginal: I've since added a thin coat of silicon RTV and it works much better. If water touches the electrode strips, it shorts out the capacitor and the sensing function returns -2, which leads to erroneous reports of low water level.

-- --- ----- ------- ----------- -------------

About a year ago I made a Christmas-tree water-level sensor that didn't hold up well. Here's a link, but don't make that one. It had a flashing LED, then an audible alarm, to let you know that the water was either low or gone. But why use an LED? As "Joe" suggested in his comment last year, the tree has a lot of lights on it already and why not flash them instead?

Good idea, Joe. Thanks!

The functional problem with last year's model is that the copper traces used for the water-level sensor corroded quickly, and the device was useless in less than a week. The fix I came up with this year is to use a capacitive measurement of water level instead of a conductive measurement. This method (and the necessary CapSense library) is described on the Arduino Playground wiki as an idea for a proximity sensor. Since water has a very high dielectric constant, the presence or absence of water significantly changes the capacitance of a pair of copper traces. Measuring the capacitance of those traces then gives you a measurement of water level while keeping the traces isolated from the water.

Here's my sensor. It's just a strip of strip-type protoboard. (It's 4 traces wide, but I'm only using 2 traces.) It's been covered with 4 coats of spray-on clear polyurethane, so it is (one hopes) completely waterproof. There are two neodymium magnets glued to the back so I can mount it to the inside of the Christmas-tree stand. I forgot to put something in the picture for scale, sorry: it's 9cm long.
With this improved sensor, I can now use the CapSense library to measure water level without worrying about corrosion of the copper traces. And I probably should have stopped there, but Joe's suggestion just seemed to good to pass up. So here's the schematic for the rest of it:
Everything inside the dashed lines is built into a small box. The box has a plug receptacle on the top, into which are plugged the tree's lights. Power to that receptacle is switched by a relay, controlled by an Arduino Pro Mini. (The Pro Mini and relay are powered by a 9V wall-wart transformer, also mounted inside the box.)

If the Arduino detects a "good" water level, it leaves the relay alone and the lights plugged into the receptacle stay on continuously. When the water level drops to "fair", the Arduino cuts the lights briefly once every 5 seconds. When the water level drops below that, the Arduino flashes the lights once a second. Here's the box: I wrapped it in shiny paper to help it "blend in" under the tree.
Here's the code. The values of "fair" and "good" will depend on the exact geometry of your sensor and sensor cable. Uncomment the serial lines in that code and see what values are coming back from the Arduino to determine what levels are appropriate for your setup.

A note for the Arduino-haters: Yes, this could be done with an ATtiny85. Here's why I decided to use a whole Arduino this time:
  1. You need fairly precise timing to measure capacitance repeatably with the CapSense library. That means you need an external crystal rather than the microcontroller's internal oscillator.
  2. The 12A relay I used needed 9V to activate. (My local Radio Shack didn't have a 5V relay that could switch more than 1A.) An ATtiny needs 5V at most, so I would need a voltage regulation circuit.
  3. I needed to know the values coming out of the CapSense routines so as to be able to set the cutoffs for "good" and "fair" in the final program. That meant I needed a serial link back to the computer for the setup process.
  4. Put all this together and hey, it's an Arduino. The Arduino is built already, and I have to write an exam this week also.
But yeah, it'd be cheaper and more elegant if I just used an ATtiny85. :-)

Update: Since I have the memory available, I tweaked the program a bit. Instead of a fast blink when the tree gets dry, it now blinks "water... water... water..." in Morse code.

September 14, 2011

Hovercraft

Stefan and I cleaned out the garage last weekend. We found some useful scraps of plywood, and plastic sheeting, and a roll of duct tape, and a leafblower that nobody was using for blowing leaves. Rather than just throw them away, we decided to stick them together first and THEN throw them away. So we built a hovercraft.

This is not the usual electronics-related hack; it has nothing to do with microcontrollers or teaching physics. But it was fun... and it's definitely a hack! Here's how to build your own.

Start with a piece of plywood with an area of 7-9 square feet or so. Circular would probably work best, but anything roughly symmetric should be fine. Cut an off-center hole in it. Cut a piece of plastic sheeting about 6" larger than the plywood.

Put the plastic under the plywood and fold the plastic loosely up over the edges. Tape the plastic down with duct tape. Staple through the tape every 1-2 inches, then put a second strip of tape over the staples to seal it. It should be evenly loose, not tight!
 We put the staples too far from the edge in these pictures, and had to put in a second row of staples closer to the edge. More duct tape! Make sure the plastic is completely sealed to the plywood, because when it comes off your hovercraft will stop hovering.

Now turn it over and cut four (roughly) symmetric holes around an 8-inch circle in the center. We just cut slits a little more than 2 inches wide. We then fed duct tape through the holes so that the center of the plastic was attached to the plywood. Anchor it firmly with more staples, and reinforce the plastic around the holes with —you guessed it— more duct tape.
Air can now blow in the hole in the plywood from the top, inflate the plastic into a flattened donut shape, and exit through the holes in the center. The filled plastic "bubble" makes a skirt for the hovercraft.

Next, turn it right-side up again and attach the leafblower. We used more plastic and duct tape and staples... Lots of staples... More duct tape... and eventually got something that would direct the air through the hole without too much leakage.


Sit on top and turn the blower on — you're good to go!
Obviously a gas-powered leafblower would be an improvement — this one is limited in range by the 50-foot extension cord. It's still fun for sliding around the driveway, though!

August 25, 2011

How long until Christmas?

I have kids. They have questions. One of their big questions, all year long it seems, is "How long until Christmas?" Here's one way to answer that question.


The circuit consists of three main elements: Arduino Pro Mini, DS3231 real-time clock (RTC) breakout board, and a standard 2x16 LCD. 

The Arduino Pro Mini takes power (raw) from the 9V battery through the toggle switch. The Vcc output  of the Arduino's regulator (5V) is used to drive the LCD and the clock. Here's the program on that Arduino. The program reads the time from the RTC, calculates the number of seconds between 'now' and a hard-coded 'targetDate', then from that time differential calculates and displays the number of days/hours/minutes/seconds remaining. It does this roughly 4x/second, which makes a nice ticking-second countdown. When the countdown reaches zero, it displays "Merry Christmas!" and goes to sleep.

The Arduino uses I2C to communicate with the RTC. I used a homemade DS3231 breakout board with a battery backup for my RTC, but one could use the more standard Sparkfun DS1307 breakout as well. In either case, my DS3231 library works fine. The code provided above does not set the clock: it assumes the clock has been set previously. I used the setClock.pde sketch from my DS3231 library to set the clock using the serial port, and no hardware changes are required to make that program set the clock on this circuit.

The LCD is a standard 2x16 LCD with the HD44780 driver, as shown here.

Nothing particularly fancy, but I just happened to have all the necessary parts sitting on my workbench anyway so I threw it together one evening. You can of course change the target date and message in the software so it works for any other event you might want. At this point in the semester, I'm leaning towards counting the seconds until the Physics 202B final...

August 3, 2011

Simple Arduino data-collection

At this year's "Arduinos in the Physics Lab" workshop at the AAPT meeting, one of the participants asked for a simple way of using the Arduino as a tethered A/D converter for data collection direct to a computer. This is my quick & dirty demonstration solution.

Here's the code for the Arduino. It waits for a single byte 'N' to arrive on the serial port, then once that byte arrives it sends out N data pairs formatted as tab-separated millis() and analogRead() values. The readings are separated by roughly 10 milliseconds. This version of the code only reports the values of analog pin 0 (A0), but it can be easily modified to return other (or more) ports.

For the computer end, I used Python: here's the code. This was done on a Macintosh, with Pylab installed so I can use matplotlib to handle the plotting nicely. On Linux or Windows the port will be described differently, and if the program fails for you on the line 'import pylab as pl' then ... well, install pylab on your system. It's a great wrapper package for scipy, numpy, and matplotlib. The program expects two arguments: the number of points to collect and the filename where points should be saved.

Here's a sample output plot, showing relatively meaningless data from a light sensor.
One glitch I found was that there needs to be a short delay between starting the serial communications to the Arduino and sending the request for N data points. I do not know whether this is a problem with the Arduino in general, or with the Arduino Uno I was using as a testbed, or with the pyserial library, or with the Macintosh implementation of pyserial... It was a mess trying to figure out what was going on, though, because when in interactive mode everything would work perfectly but the exact same commands in a Python script would not work. The difference of course is that I would take several seconds to type commands in interactive mode, and it took me a long time to figure out what was causing the problem! The solution I used is in line 37 of the code:
    time.sleep(1.5)
The sleep value (1.5 seconds) was determined by trial and error. ser.flush() should work also, but I did not find this to be the case.

June 25, 2011

Stereo Camera rig


This is something I've been wanting to try for awhile: I'd like to take pictures I can use with an old-school stereoscope. It seems like a simple enough idea: you just need two pictures of the same thing, taken from a few inches apart. I've seen it done with just two cameras —no external synchronization, just push both buttons at the same time — but it seemed like I could probably synchronize things a bit better than that.

Ideally, it would be perfect to set things up so that one camera was a master and the other a slave: exposure and zoom parameters would be set on the one, which would then be duplicated on the other. The Canon Hack Development Kit (CHDK) gave me some hope that this might be doable, but I haven't found any straightforward way of setting up a master/slave relationship, so instead I used cruder methods. The cameras use a CHDK script to time how long power is applied to the USB connectors, and depending on the pulse width the cameras either zoom in, zoom out, or shoot.

The pill-bottle on the left contains a 4-AA battery pack, 5V regulator, some buttons, and an ATtiny85 to convert button presses to appropriate-length pulses for the cameras. It's not ideal, but it does give me synchronized zoom and shoot capacity using the one set of controls on the pill-bottle.

Here's the code for the cameras, and here's the code for the ATtiny85. One thing I found out by extensive trial and error is that the signal at the USB connector must be 5V. Less than 4.5V does not work, at least on these eBay-special A590is cameras.

I still think there should be some way of having one of the two cameras tell the microcontroller its settings, and have the microcontroller set things to the same values on the second camera. That would allow much easier use of the excellent controls available on the A590is camera. But someone else will have to figure that one out. Send me a link if you know of someone who's successfully managed this!