June 18, 2012

Quantitative Two-Dimensional Temperature Measurements

Lab Experiments involving the Heat Equation are usually one-dimensional exercises involving a copper pipe and a half-dozen thermocouples. But with DS18B20 "One-Wire" thermometer chips and an Arduino, it's possible to measure hundreds of temperature values simultaneously. Here's what my students Daniel Lund and Lawrence Lechuga and I came up with for 2-D temperature measurements.

We began by laying out a 10x10 grid of sensor locations on a 30cm-square plate of 5mm-thick aluminum. We laid Kapton tape in strips under where the sensor leads would be located, to prevent the leads from shorting against the aluminum plate; then we glued each sensor to the plate using thermal epoxy.

Next, we temporarily attached each sensor to an Arduino microcontroller running FindAddress.ino. This program first determines how many devices are on One-Wire bus; then for each device, it sends the address of that device to the Arduino serial port. A terminal emulator on the attached computer displays those addresses. By running this program with the sensors attached individually, we could then determine the hard-coded addresses of each sensor. One hundred tests later, we had a complete list of sensor addresses, ordered by their physical position on the grid.

Once we knew the individual addresses and corresponding locations of the sensors, we permanently wired all the sensors to the Arduino. Power and ground are provided by the USB connection to the computer, and the data pins for each sensor are all connected via a single wire to one input pin of the Arduino. The data bus is also connected to power via a 1k pull-up resistor. (Note: the datasheet for the DS18B20 calls for a 4.7k pull-up resistor, but we found that with 100 sensors on a single bus a 1k pull-up resistor provided more reliable operation.) The Arduino itself is connected to the computer via a “FTDI Friend” USB-serial converter board.

The completed hardware (bottom side) can be seen below. The plastic stand-offs allow it to be placed flat on a table with the bare top side up.

The final step in construction is to program the Arduino to measure the temperatures and send those temperatures (in order of grid position) to the computer. With this many sensors we found that we were straining the capacity of the microcontroller: although the ATmega328 chip on the Arduino board has 32k of program space, it has only 2k of RAM. This RAM is used by the serial and One-Wire communications libraries as well as by our program, and when the RAM is full the Arduino behaves erratically. Our solution was to store the array of sensor addresses in the 1k array of EEPROM on the microcontroller. This required a second Arduino program (address_storage.ino) which was run once to store the sensor address array in EEPROM. Once that program did its job, we uploaded our final program, ThermoPlate.ino.

The ThermoPlate.ino program operates in two steps after the initialization procedures: first, it sends out a “broadcast” message on the One-Wire bus telling all sensors to record the current temperature. Next, it goes through all the sensor addresses stored in EEPROM. For each address it sends a temperature inquiry to that address, converts the sensor response to °C, and sends the temperature as text down the serial line to the computer. When the Arduino has gotten the temperature from each sensor it sends an EOL character to the serial port, then repeats the process. That’s the final output of the device: line after line of serial data, each line containing 100 temperatures in left-to-right, top-to-bottom order. With our 16-MHz Arduino, it takes just under 2 seconds to measure all points, with the limiting factor being the speed of the One-Wire bus itself.

The computer has to be able to listen to the apparatus and make sense of the incoming data. Since the incoming data is simply text, there is a wide range of possible tools to use for this purpose, ranging from LabVIEW to IDL to C++. For simplicity, we chose to write our program, TempMovie.py, in Python. This program captures each line of data coming in the serial port, splits the line into individual temperatures, rearranges those temperatures into a grid, and then draws a filled contour plot based on that grid data. One can set the temperature scale in the program to cover the expected range of values, and if desired the program will save the raw data for later analysis. The figure below shows a single frame of output of TempMovie.py when a small bag of ice was placed at the upper right and a hot soldering iron was placed near the center.

The image changes as the plate moves towards its new equilibrium state, and one can observe the heat flow in real time. For the sequence of images shown below, the plate was hit with a flame from a propane torch, which was removed after a few seconds. (Time in the video below is sped up by a factor of 4.) Time-dependent thermal data such as this can be compared to numeric solutions of the Heat Equation.


Note: These temperature sensors can detect changes as small as 0.1°C. If you look closely at all of these images, you can see that an area near the lower left corner of the plate is about 0.3°C warmer than the rest of the plate, due to the power dissipation of the microcontroller.

This technique of using multiple DS18B20 sensors controlled by a single Arduino can be used for one-dimensional experiments as well. Twenty-five sensors, evenly spaced along a meter of copper pipe, would make a wonderful replacement for the typical half-dozen thermocouples we’ve all used and hated as undergrads!

The sensors can be ordered from Newark.com or Jameco.com. For our thermal epoxy we used "Arctic Silver Alumina" from Newegg.com.

May 16, 2012

Off-topic, but... AT&T sucks.

For the past several years we've gotten our internet through AT&T DSL. Unless you want to support Comcast with your money (and nobody with an interest in net neutrality does) AT&T DSL has been the only option in this town.

I got tired of slow network. Calling AT&T did no good, they claimed things were fine. So I measured the actual speed. Repeatedly!

It just happens that I have access to a pair of very nice servers at my work; I wrote a script on my home machine that downloaded a small file from one of them and recorded the download speed every 15 minutes. An identical script on the second server served as control: should the problem be the server rather than the DSL line, the second server would show it.

After sitting through more than a year of dreadful AT&T service, here are the results.

  • Up through the end of April of this year, my actual download speed was at most HALF the advertized "up to" speed. For most of last year, I got a quarter of the advertised speed on average.
  • The jump in speed at the end corresponds to the date at which many of my neighbors gave up and got Comcast. Speeds after that point are still less than 2/3 the advertised "up to" speed.
  • The "control" server (graph not shown here) showed a flat constant speed of nearly 100 Mbps. In other words, the limiting factor was the transfer, not the source.
Conclusions: AT&T sucks, and we need for them to have some serious competition in this area.

They just switched me to "U-Verse" (still the same "up to 1.5 Mbps" speed) so we'll see if that's any improvement. I'm not holding my breath, and the script is still running.

Oh, and here's the code, which was executed every 15 minutes by cron.


DATESTRING=`date "+%Y-%m-%dT%H:%M:%S%t"`
DOWNLOADSPEED=`curl -s -o /tmp/whatever -w '%{speed_download}' http://REDACTED/randomblock`
echo "$DATESTRING    $DOWNLOADSPEED" >> /REDACTED/speedresults.txt

rm /tmp/whatever

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.