I had thought about just purchasing an altimeter, but that's boring. I wanted to put time, and thought, into creating something that I could use almost on a daily basis. And I had been doing some research and there were a couple great tutorials online about this that I could fall back on. Specifically, this Instructables article by qubist, and I got most of my inspiration from ALTDuino.
What really irritated me is that no matter how envious I was about the graphs that the ALTDuino creates, I will probably never be able to look at the code (for some reason he won't let his code be OpenSource...).
So, I did the next best thing, I took the design/layout that Qubist used on his Instructables tutorial and wrote my own code for it. And wrote my own Processing program to read data from my altimeter and graph it (this was a rough process).
In this blog post, I plan to highlight the key challenges I faced when coding this altimeter, along with solutions to these. I hope that this article will be able to serve as a backbone for other people's future projects. And, yes, my code is, and always will be open sourced.
This is NOT a tutorial, if you can use as one then feel free to use it as one though.
What I used:
The First Obstacle
The first "real" problem I had with this project was unreliable readings from the altimeter, I was using
readAltitudeFt() which just called the standard
readAltitude() function to get the altitude in meters (above sea level), and then converted it to feet (since I'm in the U.S. this was more desirable to me).
However, these readings were extremely unreliable, they would fluctuate up or down 2 feet while in the same spot. I know that 2ft is not that big of a deal, and it still makes it accurate, but it just wasn't okay with me.
I tried the program using
readAltitude() and noticed that the reading appeared to be more stable, even though it was doing the same thing (the conversion to ft. made the numbers larger so it jumped around more), the stable print out was much more satisfying with me. So that's why it reports the altitude in meters.
The Logging Issues
At this point I had my altimeter working the way I wanted it to; when the board was powered on it would take a baseline reading, and use this to get the rocket's altitude above ground level. Well, if I want to graph the flights of my rocket then I need to save data during the flight; and I'm not really sure how long each flight will be, probably no more than 2 minutes (at my current level). And the Nano and the Pro Mini (both ATmega328) only have limited storage from program variables (2KB). And I knew that I wasn't going to write to the EEPROM every 1/4th of a second, either.
I solved this by saving the current altitude in an array of integers that has 500 elements, that's 1KB of memory (Integers are 2-bytes) just for the data logging, about half of what each board will be able to provide me. And if you're wondering, the variables are all stored in volatile memory, so if I loose power during the flight I will be unable to graph it.
I did, however, design my code to detect an apogee (once it's 2m below the highest point in the flight) it will write the highest point to the EEPROM. This will allow me to recover at least that much if I loose power (after apogee). The program will also load that value in the
setup() function and display it on the bubble display.
Back to the logging, I designed the program to log the altitude detected every 200ms after a launch was detected (2m above the baseline reading). By doing this I will be able to graph at most, a 100 second flight. I'm sure that will be plenty to at least get the apogee recorded. The program will only log data from the point that a launch is detected to the point a landing is detect (at or below the baseline, or repeating the same altitude 30+ times).
If the program runs out of logging before the apogee, it will still detect and save the apogee to EEPROM :).
The Serial Connection Problem
In my program, once a landing is detected the program (in the
loop()) will just loop through the array items and send them over
Serial. It's separated by an '
a' whenever the index of the array is
0.This is so I will be able to tell when the logged data starts and ends. Each index item is also separated by a '
,' to be able to distinguish between them.
Originally I wanted to just be able to connect the Arduino to my computer over USB to get the data off it, but when you do this, the Arduino will automatically reset, and from what I looked up on this there wasn't anyway of getting around the issue. I tried shorting out the
GROUND pins but this wasn't solving the issue for me.
I was able to solve this issue by using another Arduino, this time an Uno. I was able to have this connected to the computer with the Serial Monitor (or Processing) open, and then connect the
GROUND pin from the Uno to the Altimeter's ground, then connect the
RX (Serial receiving) pin on the Uno to the
TX (Serial transmitting) pin on my altimeter. This would then send the data to the Uno, which could process it and make sure that the computer only receives the data one time, not continuous looping. Otherwise in Processing the graph would keep redrawing over and over again.
It's important to note, and was a learning point for me, that if you have these pins connected to your Altimeter and then you open the Serial monitor (or the graphing program) on your computer, both Arduinos will reset!
The Graphing Program
I have only used Processing one other time (as of 4/2015), and it was just a program someone else wrote so I didn't actually use it. Writing the graphing program did present a little learning curve, but nothing some research and sample programs couldn't solve. I won't go much into this, as it's not the main function of the altimeter, it's just a bonus feature.
Yes, I could have just used Excel, but if I was going to take the easy way out then I would have purchased an altimeter.
The Graph Issues
At first, while I was using
readAltitudeFt() I would get some really messed up graphs. They would read all of the charts, not like the graph of a rocket (or anything tossed up) should resemble (I'm sorry I don't have any screenshots of these graphs, I wish I would have taken some).
I wasn't quite sure if this was a problem with the graphing program or how I was logging the data in my Arduino. I added some error checking for the logged data.
For example, if the altitude was less than the previous altitude and there wasn't apogee yet then it wouldn't log that data. This solved most of the problems, I knew there would still be some anomalies on the graphs though, as of now most of them are on the descent of the rocket. I can live with that.
On 4/18/2015 I was able to test my altimeter in model rockets for the first time. The results were beautiful. At lest they were half of the time... After flying twice in my Estes Heat Seeker I waited maybe an hour and a half before trying to fly it in my Estes Skywriter (modified to have a payload section); during this time the weather did change and the wind picked up some. When attempting to launch in my Skywriter I experienced the strange problem of the altimeter detecting apogee moments after turning on. Of course, it may have been the weather but I'm looking into the issue.
Above: The Estes Heat Seeker with the altimeter in the payload bay. Above: The graph of its very first flight (160m), at apogee I believe that the ejection gases (or turbulence from the ejection) caused the inaccurate reading which you can see dip down. Above: The Estes Heat Seeker with the altimeter for its second flight. Above: The graph of the second flight (123m). I added recovery wadding into the payload section to protect it from the gasses. Above: The modified Estes Skywriter. Above: The Skywriter with a commercial altimeter for comparison (my altimeter turned off for some reason but the altitude reported by the other was around what mine had been reporting all day).
High Powered Flights
On 5/2/2015 I flew my altimeter in Elizabethtown, Kentucky for its first mid-power flight and high powered flight. The altimeter performed well on an F-16 engine. However, I was unable to record the flight on a high-powered I-180 Skidmark motor because I'm an idiot. It took four failed attempts to launch the I-180 due to a bad igniter and then some tries until we realized we had to clean the alligator clips, after doing that it finally launched. Since it was on the 5th attempt that it worked I was just anxious to launch the rocket and forgot to re-arm the altimeter... I even left the key for it in the rocket. Whoops.
Here are some pictures of the launch anyways. Above: How I had the altimeter in the payload section (please excuse my finger and the out-of-focus picture). Above: The Ascender ready for flight Above: The graph of the Ascender flight, read 285m on an F15-6 engine. Above: How I had the altimeter in the DX3 Above: More of the improvised altimeter bay for the Super DX3
As I said earlier in this article, my code is open to the public, and forever will be. You can check out the entire altimeter project on GitHub here. Suggestions to the code are always welcome!
Above: the first version Above: the second version, more compressed down for testing Above: the container I used to toss the altimeter up for testing data Above: the final, most compact, version of the altimeter with its battery Above: a test slingshot rocket that produced the graph below Above: a good example of the anomaly I was talking about (Apogee: 14m)