Saturday, November 30, 2013
12 Hour Project: Arduino Mechanomyography
It's the weekend after Thanksgiving. Not only are my grad student responsibilities minimal, but the servers I get most of my data from are down over the holiday. I've tried sitting around doing nothing, but that was too hard. Instead I've decided to challenge myself to a 12-hour electronics/programming project.
Seeing as it's just past Thanksgiving, leftovers are the highlight of the week. I've gathered quite a few miscellaneous electronic parts over the last year, mostly from projects that never got off the ground. I've got leftover sensors, microcontrollers, passive components, various other integrated circuits, and a couple protoboards. To keep myself busy and to get rid of a couple of these spare parts, I've decided to do a short 12-hour project. I set out a few rules for myself:
1) I could only use parts I had sitting around.
2) I had 12 hours to complete it
3) I had to build something useful (OK, maybe just interesting)
I did allow myself to think about the project before I started working. One topic I've been interested in for a long time but haven't yet pursued is bio sensing. This is basically the act of measuring some kind of biological signal (heart rate, blood pressure, brain waves, skin conductivity, etc.). Real medical equipment designed to measure these things is often very accurate, but is fairly expensive. As the cost of the sensor goes down, the accuracy usually goes down too. The goal is then to find a cheap method of measuring these biological signals well enough. While a hospital may need to know your O2 sats to two or three significant digits in order to save your life, an outdoor enthusiast might just be generally curious how their sats change as they hike up a 14,000 foot mountain.
As an avid boulderer, I've been particularly interested in muscle use while climbing. A big thing that new climbers notice is how much forearm strength is required to get off the ground. I wanted to see if I could measure forearm muscle activation using whatever I had lying around. The first method of measuring muscle activity that came to mind was electromyography (EMG). This method measured the electrical potential generated by muscle cells. I figured this would be difficult to do without special probes, so I went on to mechanomyography (MMG). This method measures vibrations created by activated muscles. The vibrations can be picked up using many different sensors, including microphones and accelerometers. Luckily, I had a few of the latter sitting around from a previous project. The night before I planned on starting any work on this, I set up a camera to take a time-lapse of my work area for the next day.
I started working bright and early at 10 am. I found an old MPU-6050 on a breakout board and soldered wires to the power and I2C lines so I could begin collecting data for analysis using an Arduino Mega. I wrote a quick code for the Mega that would grab raw accelerometer readings from the MPU-6050 and print them directly to the serial port every few milliseconds. I simply copy and pasted the data over to a text file that I could read with my own analysis codes.
For this project, I relied heavily on wavelet transforms to help interpret the sensor readings. Since the expected muscle signal would be a transient oscillation with unknown frequency and unknown amplitude, I needed a method that would break down any wave-like signal in both time and frequency. I was lucky enough to find an excuse to learn about wavelets for my grad school research (it ended up not being the best method, go figure) so I started this project with a few analysis codes to work from. Before I get into the results, I can try to give a quick run-down of why wavelets are useful here.
Interlude on Wavelet Transforms
The wavelet transform is an integral transform in that it maps our signal from one domain into another. In many analysis problems, a signal can be difficult to interpret in one domain (time) but easier in another (frequency). An example would be a signal comprised of two sine waves of different frequency added together. The addition creates a strange looking signal that is difficult to interpret, but when mapped on to the frequency domain, the two component sine waves appear distinct and separated. Why is this useful for our problem? Well, I should start by talking about a simpler transform, the Fourier Transform.
Interlude on Fourier Transforms (FTs)
Just kidding, if I follow this I'll fall down a rabbit hole of math. All you need to know is the following: any signal can be thought of as the combination of many sine waves (oscillations) that are at many different frequencies and different amplitudes. An FT is a way of displaying which particular frequencies are prominent in the signal. The issue is that it analyzes the entire signal at once, so if the composition of the signal changes over time, this change gets mixed up with the rest of the signal and you get just a single measure of the components.
Back to Wavelets
Suppose we have a signal we want to analyze in terms of simple oscillations (like a muscle vibrating), but the oscillating component we are interested in changes with time. Maybe the frequency changes, maybe the amplitude changes. A wavelet transform allows us to see the individual frequency components of the signal as a function of time. For an example, I'll use a microphone recording I did for the Music Box project of a few notes played on a violin.
I pulled the data into a little IDL code I adapted from examples here and plotted the results.
The warm/white colors show parts of the signal that have a large amount of power, or are particularly strong. The vertical axis gives the frequency of the component, and the horizontal axis gives the time during the original signal that it occurs. As time progresses, you can see that the microphone picked up a series of notes played at successively higher frequencies. For any of these notes played, you can see multiple prominent components of the signal showing up at distinct frequencies. These are the harmonics of the base note that show up while playing any instrument. If you are used to seeing plots like this and are wondering why it looks so awful, that's because I 'recorded' this by sampling a microphone at about 5kHz using an Arduino, printing the analog value to the serial port, then copy and pasting the results into a text file. I also may have gotten the sampling rate wrong, so the entire plot might be shifted a little in frequency.
Now that we've got the math out of the way, how does this relate to the project at hand? Muscles vibrate at particular frequencies when moving. The frequency at which they vibrate depends slightly on which muscle it is and how much force the muscle is exerting. For more information on these oscillations, check out this paper. It's an interesting read and has quite a few useful plots. My hope is to identify both the frequency and amplitude of the signal I'm interested in by looking at the wavelet transform of the accelerometer output.
Going all the way back to my simple MPU-6050 + Arduino Mega setup, I set the sensor down on my workbench next to me and recorded data for a few seconds. Near the end of the recording, I dropped a pen a few inches away from the sensor to see what it would pick up.
I've broken the sensor analysis into the three distinct directional components from the accelerometer (x,y,z). The colors once again show relative amplitude of the signal, and anything near the dark cross-hatching is not to be believed.
For the first 15 seconds, we see the noise signature of the sensor. There appears to be a slight frequency dependence, in that there is a little more power near 25 Hz and 150 Hz than in other places. I'm not sure where this is coming from, but it's low enough amplitude that I'm not concerned. At 15.5 seconds, the pen hits the desk and we see a spike in power at high frequency, along with a few of the bounces the pen made in the second after first impact.
Next I duct taped the sensor to my forearm with the x-axis pointing down the length of my arm, the z-axis pointing out from my skin, and the y-axis obviously perpendicular to both. I started by recording data with my arm as limp as possible.
Similar to the previous plot, but with a constant signal between 2 and 10 Hz. I don't really know what this is coming from wither, but it's roughly consistent with my heart rate when I have a sharp metal object glued tight to my arm.
Next I recorded data while squeezing a hand exerciser twice to see if there was a significant difference between that and my relaxed arm.
Luckily, it was obvious when I was flexing and when I wasn't. There was a significant increase in the power around 13 Hz whenever I engaged my forearm muscle, and a spike in power right when I relaxed it. After a few more tries, I found this signal to be fairly robust. Even when I was moving my whole arm around to try to confuse the accelerometer, I could see a distinct signal around 13 Hz whenever I activated the muscles underneath the sensor. I decided that the x-component of the accelerometer data was giving the highest signal-to-noise ratio, so for the rest of my analysis I only used that.
Since the power at 13 Hz wasn't the only thing present in the accelerometer data, I had to filter out everything around it. I used a 4th-order Butterworth band-pass filter centered on the frequency I wanted. I found this nice site that calculates the proper coefficients for such filters and even gives filtering code examples in C. After implementing the filter, I compared the new signal to the unfiltered one.
With the signal I wanted extracted from the rest of the accelerometer data, I implemented a quick algorithm for determining how much power was in the signal at any given time. Over a 0.1 second window, the Arduino would record the maximum amplitude of the filtered signal and feed that in to a running average of every previous maximum from past windows. This created a somewhat smooth estimate of the amplitude of the 13 Hz oscillations. I modified the Arduino code to only print this amplitude estimation to the serial port and recorded the result while flexing a few times.
I finally had a simple quantity that gave an estimate of muscle activation. The next step was to add some kind of visual response. I had an extra RGB LED strip sitting around from my Daft Punk Helmet project, so I went with that. The strip of 7 LEDs I planned on using only needed three connections, Vcc, Gnd, and Data. I had plenty experience getting these strips to work with the helmet project, so that was a breeze.
Next was to transfer the code over to a little 16 MHz Arduino Pro Mini and wire everything to it. To power the setup I added a little Molex connector so it would be compatable with the 5V battery packs I made for my helmets (a 3-cell LiPo dropped to 5V with a switching regulator).
I added a simple conversion between signal amplitude and LED color to the code and tried it out. Unfortunately, I couldn't find any plastic or cloth straps that would work for securing the sensor and display to my arm, so I duct taped them on. Over the course of the day I had ripped around 5 pieces of tape off my arm so I was getting used to the pain.
At this point I declared the project a success. Not only had I built a contraption to measure muscle activity using components I had sitting around on my desk (and found a use for wavelet transforms), but I had done it in my 12-hour limit (actual time ~10.5 hrs). I've placed the final code on github for those interested.
I've got close to 10,000 still frames from the time-lapse I recorded while working, but it will take me a day or two to get that compiled and edited. I'll update once it's live!