Saturday, January 12, 2013

Embedded Halloween Costume




Summary:
Used Halloween as an excuse to get myself back up to speed on basic electronics and Arduinos. Ended up with something with flashy lights that looked great in the dark.

Motivation:
After finishing my grad school qualifying exams, I took a few days off work to get myself back into electronics. Halloween was coming up, so I could kill two birds with one stone by making some kind of light-up costume.

Build Details:
After searching around the internet for ideas, I found a few sites offering instructions on how to make an Iron Man costume using LEDs and miscellaneous hardware parts. I decided to model my costume after this image and include a microcontroller to control the LED brightness. There were four main components that needed to be built: the chest light, the hand light, the controller circuit, and the arm brace.
Goatee not included.

The chest light was made by punching holes in a circular piece of cardboard and gluing some blue and white LEDs into the holes. The LEDs were connected in series in groups of three or four, so there were a couple wires coming out of the chest unit that would need to be hooked up to power. I didn't care much about the number of wires needed to power everything, more bare circuitry would make it look a little more authentic anyways. To diffuse the light, I added another layer of cardboard and masking tape to the front to get the outline I wanted.
Cardboard and duct tape, because Halloween is only one night.

Poor white balance on my part making the blue LEDs look purple.

Looks much better with the lights off.

The hand light was made similarly with 7 LEDs (mix of blue and white) on a cardboard backing. For some reason I decided it was not interesting enough to take pictures of while building, so you'll have to use your imagination.

With both lights built, it was time to figure out the controller circuit. I wanted the microcontroller to have complete control over the brightness of the hand and chest units independently, so I wired up a simple circuit that would drive the LEDs with transistors and allow pulse-width modulated output from an ATtiny84 to set the brightness.
Testing the circuit.

Final board. Not pretty, but it worked.

After burning the Arduino bootloader on to the ATtiny I uploaded a sketch that would slowly modulate the brightness of the chest light like a heartbeat. When the button is pushed, the chest dims, the hand flashes for a few seconds, then the chest comes back on with a faster heartrate that slows back down over time. The full code can be found here.

I'm a fan of making my Halloween costumes super-cheap, so the entire arm brace was made out of cardboard, duct tape, and an old motorcycle piece or two. While duct tape obviously isn't the best choice for structural stability, the costume only had to last a few hours of one day.
All assembled.

Bright enough to provide dramatic lighting.

Insights:
1) The ATtiny85 is a great alternative to a full-blown Arduino board when you want something cheap and small. I'll probably use them again in future projects.
2) The lights look nice in the dark, but were far too dim in normal lighting. It might have been worth it to significantly increase the number of LEDs and just be prepared to change the battery every now and then.

Thursday, January 3, 2013

Water Level Analysis

The water level sensor has been steadily collecting data for more than 4 years now. Well, not so steadily. There are small gaps in the data due to things like internet connectivity issues, power outages, code bugs, you name it. Then there are larger data gaps, usually due to a physical malfunction of the sensor. Not to say it was poorly set up or is poorly maintained, in fact it has lived through a good number of storms.

As mentioned in the previous post about the build details, two sets of data are held in the online database. One is high temporal resolution data from only the most recent few days, and the other is coarser data for as long as the project has been going. For this post I will be showing this second data set and hopefully pointing out some interesting features. No build details or motivation, just good ol' analysis.

(Click to Embiggen)

Without any processing, this is what it looks like for the first 1000 days. After this, it's mostly gaps in the data due to my own negligence. But even in this 'nicer' part, there are some obvious flaws. The first is the large gap around day 200. I'll get back to that one. Next is the spiderweb of lines going back and forth through time near day 400. At some point around that time there was a bug in determining the timestamp to associate with a data point, so data was being sent around in time. A quick sweep through the data to remove non-sequential data points would probably clear that up. Next is some anomalous data near data 800 and 1000 showing the water level suddenly dropping to a constant -2.7 feet. After conversion, that is the level returned if the ultrasonic sensor consistently reads the maximum value it can. I'll be honest, I don't remember why that happened. Oh well!

Now that we've pointed out all of the flaws, let's look at the clean parts.
The first couple of days of data sure look clean. The most obvious trend is the daily tides which cause about a foot of variation every day.
More normal daily variations, but suddenly we hit the large gap from the first plot. Even before the gap, there is a long trend of rising water level. Right around the day 175 marker on this plot, Hurricane Ike made landfall a few miles away. The damage to pretty much everything on the island was pretty bad, so getting the water level sensor back up and running was not the number one priority. And so, large data gap.

But back to the cleaner parts of the data, we can also look at tide patterns and how storms play into the mix.
This is the longest portion of uninterrupted data I have, so I'll spend some time analyzing it. As before, we see the daily tide variation causing a foot of variation, but there is something else on top of this signal causing low amplitude nodes every 14 days or so. These low amplitude tides are called neap tides, while the large tides that occur in between are spring tides (this wiki article explains it more). Near day 125 is a storm that rolled through and messed up the nice tide pattern from the weeks before. As seen in both this storm and the hurricane from before, it's possible to predict incoming storms by a day or so just by keeping track of the water level.

The daily and monthly tidal variations are pretty obvious by looking at these time-series plots, but periodic features such as these should also be visible when looking as a function of frequency. The neap/spring tide pattern mimics a beat, so we might expect to see two peaks of power separated by a frequency splitting corresponding to 14 days. To look for this, I apodized the data from the previous plot using a reasonable-looking Gaussian, took a Fourier Transform, and plotted the logarithm of the magnitude.
The whole spectrum, log power. Clearly I record too many data points per day.

Looking at the low frequency power, there are two significant peaks located at 11 uHz and 22 uHz. These frequencies correspond to 25.3 hours and 12.6 hours, respectively. Not quite the frequency splitting I was looking for, but nice to see the daily tides showing up strong. Now at this point in my analysis, I nearly gave up thinking the frequency splitting was hidden under the noise. Maybe it takes more than just a few weeks of clean data to measure this subtle sun-moon interaction.

On a whim, I decided to check out the two small peaks on top of the left larger peak. Considering the scale of noise in the rest of the spectrum, I wouldn't really want to assign much meaning to these. But maybe.. By eye, the two peaks have frequencies 10.76 uHz and 11.57 uHz, so a difference of 0.81 uHz, which is a period of... 14.3 days! Exactly what was expected. Unfortunately, the scientist in me is saying this is just a cute coincidence due to noise and we shouldn't take this seriously. Still, kind of cool to see.

Wednesday, January 2, 2013

Water Level Sensor


Summary:
Used an ultrasonic sensor, 555 timer, netbook, and PHP skills to create a live online database of the water level in Galveston Bay.


This is a project started by my father and me in Spring 2008, with modifications and additions being made intermittently through the years. It is by far the longest running project I've ever done. The setup has been recording water level data in Galveston, TX almost continuously since the beginning (minus a hurricane or two), and the most recent few days of data can be viewed live on the internet:

Most recent 6 days of data. Sometimes looks weird if I've recalibrated something, or if a hurricane has wiped out our house. The dashed blue line is roughly the height of the bulkhead.

Motivation:
Measure the water level in Galveston Bay and display the results on the internet. Simple enough..

Build Details:
1) Sensor
The first issue was how to actually measure the water level. We have a house with a boat slip, so direct access to the water isn't a problem. One method would have been to have some sort of sensor float on top of the water or run down the height of the bulkhead. Exposure to salt water would cause problems for any kind of sensor we could think of, so we opted for remote sensing. We mounted an ultrasonic sensor a few feet above the water pointed down to measure the distance between the sensor and the top of the water. The first sensor we used had a range of 6 to 255 inches with one inch resolution. The connections needed to control the sensor (Vin, GND, TX, RX) were made through an ethernet cable running from the mounted sensor all the way back into our house (~50' of cable) where the rest of the electronics were. We did this to limit the amount of circuitry exposed to the elements.


2) Controller
The second part was figuring out how to trigger the sensor to take a measurement and how to read the result. All that is needed to trigger a measurement on the sensor we chose is a single pulse at least 20us long on the RX line. I wired up a simple astable 555 timer circuit that would send such a pulse 4 times per second, enough to capture the change in water level due to individual waves moving by. Once the sensor has made a measurement, the result is sent back on the TX line as regular serial data in the format R###, with the number corresponding to the distance between sensor and water. The TX line runs straight into an adjacent netbook for processing.

3) Processing
Running on the netbook is a short C# code that reads the incoming serial data and parses it. After converting the R### message from the sensor into a water height using a known calibration, the code stores the result into a buffer. After collecting about 100 measurements (25 seconds of data), the mean and standard deviation of the buffered data is computed. Since the measurements are being taken a few times per second, the standard deviation is taken as an approximate wave height and stored along with the mean water level. Once a few of these water level / wave height pairs are collected, the code sends them off to the internet for logging.

4) Logging
One measurement every 25 seconds is still a lot of data to store if you are interested in keeping track of years of data. The data set sent from the netbook gets stored in two different databases. The first stores every measurement received, but clears out any data that is over 7 days old. This way, recent data can be viewed at high resolution and only requires about 25k data points. The second database stores 15 minute averages of the incoming data, so even years of data only needs 100k data points. In all, both databases combined only take up a few megabytes of memory.

5) Plotting
To generate live plots of the most recent few days of data, I wrote a somewhat lengthy PHP script that would read data from the database and output a png file plotting the data. Instead of using a library for plotting things, I for some reason hand-wrote how to set up the axes, autoscale them, draw grids, print labels, and plot the water level line by line. While this allowed for a significant amount of customization, in hindsight I think we could have survived with a pre-built library like Google Chart Tools. Still, the plot works well and allows the user to set both the image dimensions and the time extent to display.

To this day, the water level plots have been useful for figuring out water conditions, tide patterns, and incoming storms. At some point I'll write a post showing some of the long-term recorded data and how it can be analyzed. All kinds of interesting features can be seen, like the interplay between solar and lunar tides and the effects of incoming storms.



Insights:
1) Weather-proofing an outdoor sensor is difficult, but not impossible. Over 4.5 years the sensor had only been compromised once, and that was from a hurricane that was able to take someone else's boat and place it on our lawn.
2) The 555 timer is too simple and static, while the netbook is too complicated and overpowered. A simpler solution would be to use a single Arduino board to trigger the sensor, process the measurements, and send data to the internet.

Monday, December 31, 2012

Informed Battleship AI




Summary:
Set out to measure where people typically place ships in Battleship, possibly found pattern? Mostly learned about online survey biases.

This project is from a little after the Multitouch Screen, in Fall 2007 at the beginning of my sophomore year of college. A friend and I were considering algorithms to use in a Battleship AI and started to wonder if people tend to place ships in common locations. It seemed reasonable to assume corners would be frequently populated, but we didn't want to just build in a few heuristics based on guesswork. We decided to measure how often spots on the Battleship board were populated by ships by recording how people placed ships when playing.

Motivation:
To build an 'informed' Battleship AI, we wanted to measure how frequently spaces on the board are populated.

Build Details:
To record how people place ships, I wrote a simple web-app that presented the user with a blank board and allowed them to click to place ships. Once all of the ships are placed, the app would submit the placement mask to a database that would keep track of every entry as well as a composite board that combined every submission into a heat map.

Blank board presented to the user. Full of AJAX-y goodness.

Populated board with score that meant little to nothing.

I never had the energy to actually write a working Battleship AI, so after the ship placement was submitted, the app would return a score based on how much the submitted pattern differed from the current composite map. A low score was supposed to indicate that an AI using the recorded results would quickly find your ships by following a look-up table.

To collect data, I sent out a link to the app to college friends. We got maybe 40 submissions from that, but we wanted much more. After submitting a link to reddit, the number of submissions shot up above 600, enough to start looking for trends. The heat map below shows the frequency of a spot being occupied by a ship, with black being 10% and white being 25%.

Strangely symmetric?

First thing of note is how the upper left and bottom right corners are populated nearly a quarter of the time, while the other corners are significantly less. The whole board shows rough symmetry around a line connecting top left to bottom right, which seems strange to me now. Before I make any grand claims about significant patterns in Battleship placement, I would redo the experiment with a few changes:
1) Verify the code to make sure the board isn't accidentally getting flipped every now and then (I wasn't the best programmer back when I did this)
2) Log the IP address of a user to eliminate duplicate submissions.
3) Create an interface that is easier to use and mimics ship placement on a real board (the click-to-rotate might have biased the ship orientations)

Insights:
1) Asking people to fill out an online survey is asking for people to mess with your results.
2) If you want people to pretend to play Battleship, make an interface that mimics Battleship

Multitouch Screen




Summary:
I built a 30" multitouch podium on wheels using a webcam, projector, laptop, and some failures.

This project goes back to Summer 2007 when I had just completed my freshman year at college, so I'm a little hazy on the details. This started back in the days before the iPhone and before multitouch screens were in everyone's pockets. Large multitouch screens were a common DIY project on the internet, and open source software libraries for processing input were starting to appear. I decided this would be a fun project to try, and luckily had a summer job that offered to pay for it (as long as they could keep it in the end). I was working as a web developer for the local community college at home, and they decided a multitouch screen would be a cool tech demo for prospective students.

Motivation:
Build a large multitouch screen podium for educational purposes.

Build Details:
Luckily I found some old pictures I took during the build process, so I will try to piece them together to form a coherent story. The basic concept is to have an infrared camera pointed at the back of an acrylic panel. Through some image processing, fingertips placed on the panel will be registered as individual 'blobs' and tracked as mouse pointers. My first build attempt was to use FTIR to create infrared bright points wherever a finger touched the panel. The infrared light originates from LEDs placed on the edges of the panel pointed inwards. First step was to drill holes in the edge of the panel for the LEDs and solder them together.

I don't remember how many there were, go ahead and count for me.

Holes drilled, LEDs placed.

Soldered together.

Whole panel with wires for short segments of LEDs. Also pictured, messy workbench.

The CCD sensors in webcams are usually sensitive to the wavelengths of IR light emitted by the LEDs I chose. Unfortunately, the webcam I was using had a IR-blocking filter installed. I was able to open up the lens assembly, smash the filter to tiny pieces, clean it out, and reinstall the lens to get a working IR webcam. Since I only want to pick up IR light and not visible, I taped a stack of exposed film negatives to the front of the lens. The film negatives look opaque to the eye, but actually pass IR light through fairly well.

After setting up the panel above the IR webcam, I found that it did not work. Placing a finger on the panel did not create a spot of reflected IR light that the webcam could pick up. I also tried placing a silicone rubber sheet above the panel to increase contact area, but it didn't help. I don't think I ever found out why it didn't work, and I can't think of a good reason now.

Fortunately there is another method of detecting fingertips on the panel that does not involve the side-mounted LEDs. Assuming there is a source of IR light either from above or below the panel and there is an IR diffuser placed on the panel (like a sheet of tracing paper), objects placed directly on the panel will have sharp outlines, while anything farther away will appear blurry. Using an unsharp mask in the image processing, I was able to filter out blurry shapes and isolate any objects placed on the panel.

With a working method of detecting input, I went on to build the podium part. Since the intended use was for showing off to prospective students, I went with a simple gloss black box on wheels.

Basic shape.

Panel rested on a few screws sticking in from the sides.

Painted black.

Wheels, because carrying would end in tragedy.

Added fans to keep the computer cool in the Texas Heat.

Inside the box I placed a laptop and a small projector to display the screen image on the panel from the bottom. Once I had the image processing software calibrated, the results were impressive.

Demo code to show image processing steps alongside a cool fluid/smoke code using the multitouch input.

Calibrated between the webcam, laptop, and projector.

With everything working, I modified NASA World Wind (similar to Google Earth but open source and Java) to use multitouch input. It did all of the things you would expect from Google Earth running on an iPad, with zooming, rotating, and scrolling with gestures. I demoed the screen at an open house day at the college and nearly broke it in the process. The wooden frame was not really sturdy enough to handle being moved around much or even rolled over rough concrete. Still, it performed spectacularly and wowed many young children. My summer job ended days later, and I'm not sure if the screen was ever used again. Still, it was quite an experience.



Insights:
1) If you add wheels to something, make sure it is stable enough to handle a little shaking.
2) For a screen this large, expect people to rest objects/arms on the sides, causing spurious touch events.
3) Sometimes, fancy algorithms can make up for failures in build design.

Introduction

Years of successfully avoiding getting my own blog, and then this happens. Oops.

Well now that it exists, I suppose I should say a little something about why it exists. I tend to work on a lot of projects outside of my real job*, and would like a place to publish what happens. Typically these projects involve some mixture of electronics, programming, and photography. I don't intend on writing up full tutorials on how to do these things, mostly because it would take up too much of my time. Instead, I plan on documenting a few things for each project; the motivation, build details, results, and insights gained. Some of these projects of mine go back a few years, so the posts might not be in chronological order. I also will be learning this whole blog thing as I go, so posts may get a few post-publishing edits before they make sense.

* I'm a graduate student in astrophysics, so I'm using the term "real job" very loosely.