Introduction: Model Rocket Flight Computer With Arduino
This project began as a quest to answer a seemingly simple question. In the fall of 2018, I brought my newly-finished model of NASA's Black Brant VC sounding rocket to a field for its first launch. The flight went exactly according to plan and the camera deployed at an apogee of roughly 300 feet above the ground. While this launch was a great success (and can be seen here), I left the launch pad with some unanswered questions: what was its top speed? what was the net force acting on the rocket after burnout? how high did it really go? "Roughly 300 feet" is an educated guess, as I had no way of directly measuring the rocket's altitude without placing altimeters and other sensors on board. To answer these questions, I looked in to purchasing a small flight computer to place inside of it. Upon realizing that the sensor data provided by many commercially-available flight computers is rather underwhelming, I set out to create my own.
What follows is a flight computer is designed to be a low-cost, open-source, multi-purpose avionics and datalogging platform for model rockets. It can be used to log flight data including acceleration and rotation, take simple atmospheric measurements (temperature and pressure), and potentially serve as the basis for an active stability system. This flight computer is meant to be a perfect addition to any backyard space program.
In this instructable, I will walk through the process of designing, building, and testing this flight computer as well as discuss possible applications and design improvements moving forward. The first section of this instructable will cover the hardware and software portion of the project, while the second section will dive into the math and data analysis methods to get useful information from this flight computer.
Disclaimer: Model rockets can be dangerous! Please use caution and abide by your local laws and regulations when launching model rockets. If you chose to re-create this project, you are fully responsible for ensuring that it is used safely and responsibly. This flight computer was not specifically designed for active stability or control applications, any attempts to modify or use it for such applications (including thrust vector control, reaction control, roll control, etc.) should use extreme caution. I am not responsible for any damages caused by unsafe use of this project.
- Arduino NANO or similar clone (should use an ATMEGA 328 chip for same results)*
- Inertial measurement unit - I used the MPU 6050
- temperature and pressure sensor - I used the BMP 180, although better sensors are available
- microSD card reader with SPI bus
- microSD card with SD adapter
- (3) 5mm LEDs - I used a red, yellow, and blue one
- normally open pushbutton or tactile switch
- (2) 220 ohm resistors (or similar value)
- 5k ohm resistor (or similar value)
- piezo buzzer or small speaker
- 2-6 additional header pins (optional)
- several lengths of 22 awg wire (or smaller)
- 9 volt battery connector or other power adapter
- through-hole PCB for prototyping (I used 50 mm x 70 mm perfboard)
- 3D printed enclosure or plastic plate (optional - useful for protecting the flight computer during flight)
- soldering iron
- a solderless breadboard and jumpers (for testing)
- adjustable "3rd hand" tool or vice (optional but highly reccomended)
- pliers and other small hand tools for working with electronics
- a computer with MATLAB, Excel, or another data analysis/spreadsheet program capable of reading .csv files
- a computer with the Arduino IDE
- Arduino USB programming cable
I found the total cost of components to be less than $50 USD, though your costs may vary, especially if you chose to design a custom PCB. Spending extra time finding discounts may decrease the cost even further.
*Note that I2C and SPI busses are different for other ATMEGA chips. This is discussed in slightly more detail later
Step 1: What Is I2C? No Seriously, What Is It?
Honestly, I'm still not entirely sure.
I can say, with some degree of confidence, that it is the communication protocol that digital sensors use to send data back and forth to the host device, in this case an Arduino. Another advantage of I2C is that multiple sensors can share a set of connections, requiring only one set of I2C pins on the Arduino to control multiple sensors.
I2C uses four (or five, if you count the interrupt) pins to communicate:
- VCC - voltage in, +3.3V (NOT +5V !!)
- GND - ground
- SDA - serial data
- SCL - serial clock
- INT - interrupt
For Arduino UNO, NANO, and anything else that uses the ATMEGA 328 chip*, the connections for I2C are:
- VCC - +3.3 Volts
- GND - ground (any)
- SDA - analog pin A# (Yes, analog. I know, the data is digital. Trust me, it works. No, I don't know why)
- SCL - analog pin A#
- INT - digital pin 2 or 3
Ok so there's one more serial bus we have to worry about. The sensors use I2C to communicate, but the microSD card reader uses SPI. We have to deal with that one too.
But wait, then what is SPI?
I wish I knew. I should probably look it up. For now though, I'll only consider which pins we're going to need:
- VCC - +5 V on Arduino
- GND - any ground connection
- MISO - D12
- MOSI - D11
- SCK - D13
- CS - D4
It's worth noting that the microSD reader I am using has a bug which limits SPI communication such that it prevents other SPI devices from connecting to the Arduino. Keep this in mind if you plan on modifying this design.
*I2C and SPI pins differ on other chips. check the Arduino documentation or spec sheet if your board uses a chip other than the ATMEGA 328.
Step 2: Test Your Components!
Before you start piecing together the computer, it is work taking some extra time to test each component on a solderless breadboard. Tedious? Very. But still less tedious than trying to desolder a component with half a dozen pins after figuring out the hard way that there is a problem. A schematic showing all connections can be found on the next step.
Four major components should be tested for proper functionality:
- the Arduino (of course)
- the BMP 180 temperature and pressure sensor (should spit out temperature and pressure data)
- the MPU 6050 gyro and accelerometer (should spit out gyro data as quaternions or euler angles and accelerometer data, though these two may need to be tested separately)
- the microSD card reader (should be able to read and write data to a microSD card)
Example code for each component is widely available online. To test the MPU 6050, I used Jeff Rowberg's example code, which includes a nice visual demonstration of the IMU's output. Sparkfun has example code available for the BMP 180 which outputs temperature and pressure. The Arduino IDE also contains example sketches for saving data to an SD card, which is useful for testing your SD card.
For now, we won't worry too much about the sensor values, so long as those values make some amount of sense. Check the manufacturer's specification sheet for each sensor to verify that the output is appropriate for the given circumstances.
Feeling ambitious? Want to be super sure of everything before you commit to soldering? Build the whole thing on a breadboard! It doesn't take that long and you can make some minor adjustments before you spend a few hours soldering this thing together.
Step 3: Make the Thing!
This step isn't really a step. It's a process, or something like that. Whatever it is, how you chose to approach it is up to you.
The schematic shown above shows all the connections between the sensors and the Arduino. Note that the pins on the Arduino are arranged according to their physical location, while the pins on the sensors are not.
I began by establishing a set of criteria for the board. The board must allow easy access to the microSD card, easy access to the USB port on the Arduino. The IMU must be placed near the center axis of the board with breakout pins near the edge. The board must have a maximum width of no more than 2.25 inches (to fit inside a 2.5 inch diameter rocket). Additionally, the two I2C sensors should be placed near to each other so that they can share a set of connections to the Arduino.
I then layed out all the components on the board in different arrangements until I found one that met all of my criteria. The final layout that I chose required some of the components, namely the microSD reader, to be stacked on top of the breakout pins and several jumper wires connecting to other components. While this arrangement proved to be very difficult to solder by hand, it made efficient use of limited space. The schematic above roughly approximates the location of each component on the board. I also found that placing some components on the board upside-down, including the microSD and BMP sensor, made it easier to conserve space on the circuit board.
The large number of connections means that the schematic can be a little hard to follow. To remedy that, I found it easier to make a table of all the connections and add wires between each connection one at a time, checking off each connection on the list when the wire is soldered in place.
Step 4: The Software
I wrote a basic though somewhat inefficient data logging program that writes a steady stream of sensor data from the on-board sensors to a text file saved on the microSD. The Arduino program is based on a combination of example datalogging programs for each of the sensors. This combination of programs led to some inefficiency in the datalogging process. I am stilll working to iron out some of the bugs.
In order for this program to run, several code libraries will be required. Some of these may already be included with the Arduino IDE. For more on standard libraries see: https://www.arduino.cc/en/Reference/Libraries
- wire.h (standard library)
- SD.h (standard library)
- SFE_BMP180.h available from: https://learn.sparkfun.com/tutorials/bmp180-barometric-pressure-sensor-hookup-/all
- I2Cdev.h available from: https://github.com/jrowberg/i2cdevlib
- MPU6050_6Axis_MotionApps20.h available from: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
The flight software is built around the idea of the flight computer in three different modes: 1, 2, and 3. Mode 1 sets up each sensor and connects to the microSD card file. A red LED indicates that the flight computer is in Mode 1. If the program fails to connect to the microSD card or fails to open the file, the computer stays in Mode 1. If the program successfully initializes all sensors and the microSD card file, the program moves on to Mode 2.
In Mode 2, the program saves data from each sensor to the data file on the microSD card. It does this at a rate that is specified by the dataRate variable. The reccommended dataRate is anywhere between 10-100, depending on the application. Note that dataRate specifies the maximum rate at which data is logged, not the exact rate. This is because the Arduino takes some time to execute the commands required to move the data around, and that all of those very small delays add up to enough time to affect the performance of the program. Mode 2 is indicated by the yellow LED.
When the button on pin D7 is pressed, setting the value of the pin to LOW, the computer transitions to Mode 3. In Mode 3, the computer closes the data file, ensuring that the data is saved. It is then safe to disconnect the power and remove the microSD card. The blue LED indicates Mode 3.
The program saves data as a text file labelled "FILE" on the microSD card (yes I know, very original). This file contains a block of data values separated by commas and lines. Opening this file in a text editor, such as Notepad, and saving it as a .csv file allows spreadsheet and data programs to interact with the file.
The software has a few bugs that I am still working out. The first being that an FIFO buffer overflow problem causes the program to drop several bytes of IMU data, leaving errant blank spots in the .csv data. This problem gets worse as the data rate decreases. Using higher data rates (e.g. 100 lines/second) largely addresses the issue.
The program, with USB serial communication included, requires nearly 86% of the Arduino's available memory in order to run. While some of this can be attributed to inefficient code, a significant portion of that memory is used by the code libraries required to run the program.
Step 5: Launch!
Implementing this flight computer into a rocket is beyond the scope of this instructable, as the exact setup is going to vary wildly based on the vehicle itself. It remains a very imporant thing to consider as a flight computer is most useful when it... well... flies. You might notice in some of the photos that I have 3D printed a plastic plate to protect the circuit board during testing.
As a result of the pandemic putting all club rocket launches on hold, I decided to test this computer using a plastic bottle and some kite string. A video of the absurdity is linked above.
Step 6: Data Analysis - Part I: "What Do All These Numbers Even Mean?"
Again, I'm still not sure. Let's check that spec sheet again and see if we can make sense of some of these outputs.
Ouputs for the BMP 180:
- temperature (in degrees C, no conversion needed)
- pressure (in hecto-paschals [hPa], must convert to Pa by multiplying by 100)
Outputs for the MPU 6050*:
- acceleration in X, Y, and Z direction (in gs, times some constant multiple)
- angular position about X, Y, and Z axis (in degrees, kindof)
Looking at the Data in a Spreadsheet:
Opening the .csv file in a spreadsheet software such as Excel allows us to visualize the data in a graph and perform some basic analysis on the data set. In this step, I have included two versions of the same data file (one in .txt, the other in .csv). Note that they do not correlate with the graphs included above. Each timestep represents a delta-t value of 0.1, meaning that each time interval is approximately 1/10th of a second. To convert the raw sensor values into gs, we'll need to check the data sheet for a constant multiple. Since I am using the default sensativity of +/- 2 gs, I'll need to divide the raw data values by 16384 to convert to gs. Since 1 g is equal to 9.81 meter per second^2, I can convert the gs into meters per second^2 by multiplying by 9.81 to make it easier to calculate velocity later on.
We can use the air pressure sensor on the BMP 180 to determine the approximate altitude of the flight computer using the relationship between air pressure and altitude (in Paschals and meters, respectively). Using the equation provided by engineeringtoolbox.com we get:
P = P0(1 - bh)^m
- P is pressure (in Pa)
- P0 is "normal" pressure at sea level (101325 Pa)
- h is altitude (in meters)
- b is a coefficient** (2.2557*10^-5)
- m is a exponent** (5.25588)
Re-arranging the equation to solve for altitude (h) in terms of pressure (P), we get:
h = (1 - e ^ (P / (m * P0))) / b
Note that this equation produces the absolute altitude above sea level. Because of changes in the air pressure due to temperature and weather conditions, we are more interested in calculating the relative change in altitude than the absolute altitude. In order to calculate the relative altitude (Hrel), we'll need to subtract the absolute altitude at the point in question (Habs) from the initial absolute altitude(Habs, init):
Hrel = Habs - Habs, init
Note that performing these calculations in a spreadsheet program or MATLAB may require the use of exp() in place of e^. Note also that if calculating the altitude by hand, the maximum altitude of the vehicle will occur with the minimum pressure reading.
Error Correction and Potential Improvements:
While error correction in excel can get tedious, it is possible. Removing errant zeros or NaN values can be done either manually, by deleting each row in question and then consolidating the data using built-in spreadsheet tools, or by using an elaborate series of if statements which replace the zero value with the value directly above or below it. We will talk more about error correction in the next step.
*Note that the MPU 6050 can be configured to output rotation and acceleration data in several forms, including quaternions, which are preferred for active stability systems because they avoid the issue of gimbal lock. For the purposes of datalogging, rotation is stored in Euler angles, which are easier to interpret.
**Since the equation is a result of nonlinear regression, these m and b values do not necessarily correspond to a physical quantity.
Step 7: Data Analysis - Part II: "More Power!"
Looking at the data in a spreadsheet is helpful. But if we want to make better sense of what's going on, we're going to need something with a little more power.
As an engineering student, I have a reasonable amount of experience (several late nights) using MATLAB* for some of my coursework. The ability to import all of the data in a .csv file and use element-by-element operations makes it a fantasic platform for interpreting the data produced by this flight computer.
A zip folder with my .m code files and example data is available for download here.
To start, I have put together a script which simply parses and plots the raw sensor data. From the plots, it's clear that there is a reasonable amount of error in the beginning of the data, as well as scattered throughout in the form of errant zeros (filled in by the csvread command to replace NaN** values). While this is fine for visualizing what's being spit out by the sensor, it does not tell us much about the actual flight. We'll need some way to filter out errors, trim the data set down to just the points of interest, and use numerical integration to get relevant information.
To do all of those things, I wrote a series of sub-functions which remove errant zeros, trim the data set, numerically integrate with respect to time, and determine altitude based on measured pressure.
Calibrating Steady-State Error
There are several methods of accounting for steady-state error in an accelerometer, but the method which I prefer out of simplicity is to set the steady-state error equal to the average value of the data from the sensor. Therefore, by subtracting the average value of the data from each of the data points, the error can be removed without needing to calibrate the sensor. Note that this is only true if the sensor both starts and ends at rest. This works because the average value of the acceleration must be equal to zero in order for the sensor to start and end at rest. Subtracting the average value of the raw data from the raw data is therefore equivalent to setting the average value of the accleration equal to zero. This would not be a viable method of removing steady-state error from velocity measurements unless the sensor started and ended at the same location, which is not relevant for this case since we will be extracting velocity data using a different method.
Velocity and Speed
----- CORRECTION: REFERENCE FRAMES -----
On revisiting this problem, I realized that the math in the following section of this instructable is wrong. While velocity is the integral of acceleration, it is the integral taken with respect to an inertial reference frame. The reference frame of the sensor is non-inertial, meaning that a number of coordinate conversions taking into account the euler angles are necessary to avoid answers that are completely wrong. I'll have a much more thorough explanation of how this works in a later instructable.
----- The following paragraph is wrong, but you're welcome to read it anway -----
Newtonian physics shows that velocity is the integral of acceleration with respect to time. To calculate velocity at any given time, I created a numerical integral function which outputs the sum of the acceleration values multiplied by the delta-t value. This yields each component velocity (X, Y, and Z) with respect to time. While speed and velocity are often interchanged, speed is a scalar value (one component) while velocity is a vector value (three components). Because speed represents the magnitude of the velocity, we can use the three-dimensional pythagorean theorum on the components of the velocity vector to calculate speed with respect to time.
I wrote a main script, flight_MotionGraphing, which puts all of these sub-functions to work in converting the raw data from the .csv file into presentable and readable graphs of the physical measurements.
*Free alternatives to MATLAB may be equally useful, however I am not familiar with many of those platforms.
**MATLAB gibberish for "not a number"
Step 8: Room for Improvement
The first order of business will be to design a full PCB for this thing. I'm not soldering all of those jumpers together by hand again.
After building and testing this first iteration flight computer, I have identified several opportunities for improvement...
- custom PCB - avoiding the tedious process of soldering everything by hand is much preferred
- pyro channels - parachute deployment would be a nice feature
- better processor - the primary limitations of this computer are in the ATMEGA 328 processor, which has a very limited memory compared to other processors, like the 2560. Other boards, such as the Teensy, also have on-board SD and datalogging capabilities, removing the need for a separate card reader component
- better IMU - while the MPU 6050 is relatively easy to use, a better IMU such as the MPU 6500 or BNO 055 would be more suitable for stability-related
- better pressure sensor - while the BMP 180 is cheap, widely available, and reliable; an updated version of the sensor, such as the BMP 280, would provide better temperature and pressure data, important for experiments requiring such data
- solve FIFO buffer issue - fixing the problem of dropped bytes or substituting dropped data for a reasonable estimate would make the process of interpreting and analyzing the results much simpler
- builtin error correction - the ability to throw out clearly erronious measurements before saving them to the data file would also simplify the process of analyzing the data
- flight status detection - automatically detecting a launch or landing would allow the computer to more efficiently save flight data and switch between modes autonomously
- live acceleration sensitivity adjustments - the MPU 6050 has several levels of sensitivity that can be adjusted by writing specific values to the sensor's registers while the program is running. Adjusting the sensitivity of the sensor while the flight computer is moving would allow for more accurate data across the full range of acceleration
- tweaks to the file handling - the current program deletes and overwrites any existing data on the SD card when the flight computer is powered on, which is problematic as important data can be lost if the computer is powered on accidentally. Modifying the program to create additional files or append existing files rather than overwriting data would allow for safer handling of data
- quaternions in place of Euler angles - switching to a quaternion-based system would improve the efficiency of the datalogging process as well as lay the groundwork for active stability applications
- conversion to gs in place of raw acceleration - again, to simplify the process of data analysis the Arduino program could convert the raw sensor values into acceleration data in terms of g or meters*sec^-2
Step 9: Resources and Further Reading
Websites and Data Sheets:
- For more on I2C: https://www.nxp.com/docs/en/user-guide/UM10204.pdf
- MPU 6050 Data sheet: https://invensense.tdk.com/products/motion-tracki...
- BMP 180 Data sheet: https://cdn-shop.adafruit.com/datasheets/BST-BMP1...
- Arduino Language Reference: https://www.arduino.cc/reference/en/
- The Arduino Cookbook by Michael Margolis
- The Handbook of Model Rocketry by G. Harry Stine and Bill Stine
- Make: High-Powered Rockets by Mike Westerfield
Thank you all so much for reading this instructable! Feel free to share your thoughts in the comments below. If you think that this project deserves some recognition, please vote for it in the Space Challenge!
Participated in the