https://www.youtube.com/watch?v=0qzOzjRJpaU
Anyways, I thought it would be neat to build a flight computer around an Arduino. For this project I used a Duemilanove, an Adafruit BMP085 pressure sensor, and an SD card breakout board.
The system has a few basic functions:
1) press a button to close a servo (which would be used to secure a parachute)
2) press a button to arm the system, and wait to detect a launch
3) use the pressure sensor and SD card breakout board to log the altitude
4) detect a descent and deploy the parachute
This was a fun little project and I learned a lot along the way, the breakout boards for the pressure sensor and the SD card were super easy to use. Hope you like it, and I hope someone else might be able to use it, or learn from it too!
- Code: Select all
/*
Air/Water Rocket Flight Computer
Written by Ben Shiner 3/9/2013
Uses a BMP085 pressure sensor to detect altitude
Detects descent and activates a servo to deploy a parachute
Logs altitude throughout the flight to an SD card
SD Card Breakout Board
CLK - PIN 13
DO - PIN 12
DI - PIN 11
CS - PIN 10
BMP085
SCL - PIN 5 (ANALOG)
SDA - PIN 4 (ANALOG)
*/
//include the library for servos, wire, the Adafruit BMP085 pressure sensor, and SD cards
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <SD.h>
//create objects for the pressure sensor, the servo, and the data file
Adafruit_BMP085 bmp;
Servo deployservo;
File dataFile;
//create constants used for the pins
const int armpin = 2; //Pushbutton connected to +5v
const int servopin = 9; //Servo signal
const int readyled = 5; //Ready LED
const int initled = 4; //Initialized LED
const int armled = 3; //Arm LED
const int chipSelect = 10; //CS pin for SD card Breakout Board
//create constant for logging interval
const int loginterval = 300;
//create constants for the launch and descent thresholds and touchdown altitude (in meters)
const float launchthreshold = 2;
const float descentthreshold = 2;
const float touchdownalt = .5;
//create variables for armed states, button states, altitude and time
int armed = 0;
int buttonstate;
int lastbuttonstate;
float currentalt = 0;
float groundalt = 0;
float peakalt = 0;
float adjustedalt = 0;
long launchmillis = 0;
long armmillis = 0;
void setup(){
Serial.begin(9600);
bmp.begin();
//set pinmodes
pinMode(armpin, INPUT);
pinMode(readyled, OUTPUT);
pinMode(servopin, OUTPUT);
pinMode(armled, OUTPUT);
pinMode(initled, OUTPUT);
pinMode(chipSelect, OUTPUT);
Serial.println("Initializing SD card..."); //check if the sd card can be initialized
if(!SD.begin(chipSelect)){
Serial.println("SD card failed to initialize");
}
deployservo.attach(servopin);
Serial.println("Zeroing servo position...");
deployservo.write(0); //intitalize the servo position
buttonstate = digitalRead(armpin); //initialize the button states
lastbuttonstate = buttonstate;
//open the datafile
dataFile = SD.open("log.txt", FILE_WRITE);
if (dataFile) {
dataFile.println("System Powered ON");
}
}
void loop(){
initialize(); //this function waits for a button press to initialize the system
arm(); //this function waits for a button press to arm the system
launch(); //this function detects a launch, when a change in altitude exceeds the launch threshold
inflight(); //this function logs the alittude during the flight and detects a decent when a decrease in altitude exceeds the descent threshold
descent(); //this function logs altitude during descent detects when the altitude falls below the touchdown threshold
}
void initialize(){
//if the data file isn't already open, then open the file
if(!dataFile){
dataFile = SD.open("log.txt", FILE_WRITE);
}
while(armed == 0){
digitalWrite(readyled, HIGH); //turn on the readyled
buttonstate = digitalRead(armpin);
//check for a button press to initialize the system
if(buttonstate != lastbuttonstate){
if(digitalRead(armpin) == HIGH){
armed = 1;
Serial.println("Initializing...");
digitalWrite(initled, HIGH);
if(deployservo.read() == 0){
deployservo.write(180);
Serial.println("Initialized");
if (dataFile) {
dataFile.println("System Initialized");
}
}
lastbuttonstate = buttonstate;
// wait .5 seconds to protect against accidental double clicking and arming
delay(500);
}
}
lastbuttonstate = buttonstate;
}
}
void arm(){
while(armed == 1){
//check for a button press to arm the system
buttonstate = digitalRead(armpin);
if(buttonstate != lastbuttonstate){
if(digitalRead(armpin) == HIGH){
armed = 2;
//get the current altitude, set it as the peak and as the ground altitude.
currentalt = bmp.readAltitude();
groundalt = currentalt;
peakalt = currentalt;
Serial.println("ARMED");
if (dataFile) {
dataFile.println("System ARMED");
}
digitalWrite(armled, HIGH);
armmillis = millis();
lastbuttonstate = buttonstate;
}
}
lastbuttonstate = buttonstate;
}
}
void launch(){
while(armed == 2){
currentalt = bmp.readAltitude();
adjustedalt = currentalt - groundalt;
recordAltitude((millis() - armmillis), adjustedalt);
//if the current alt is greater than the ground alt + launch threshold and the rocket has not been launched yet then update arm status
if(currentalt > (groundalt + launchthreshold) && armed == 2){
Serial.println("Launch Detected");
if (dataFile) {
dataFile.println("Launch Detected");
}
launchmillis = millis();
armed = 3;
digitalWrite(armled, LOW);
digitalWrite(initled, LOW);
}
}
}
void inflight(){
while(armed == 3){
currentalt = bmp.readAltitude();
adjustedalt = currentalt - groundalt;
if(currentalt > peakalt){
peakalt = currentalt;
}
recordAltitude((millis() - armmillis), adjustedalt);
//if the current alt plus the descentthreshold is less than the peak alt, then detect a descent and deploy the chute
if(peakalt > (currentalt + descentthreshold) && armed == 3){
deployservo.write(0);
Serial.println("Chute Deployed");
if (dataFile) {
dataFile.println("Chute Deployed");
}
armed = 4;
}
}
}
void descent(){
while(armed == 4){
currentalt = bmp.readAltitude();
adjustedalt = currentalt - groundalt;
recordAltitude((millis() - armmillis), adjustedalt);
//write touchdown and calculate peak altitude and flight duration when the altitude drops below the touchdown altitude.
if(adjustedalt < touchdownalt){
Serial.println("Touchdown!");
Serial.print("Flight Duration: ");
Serial.print(millis() - launchmillis);
Serial.println("ms");
Serial.print("Peak Altitude: ");
Serial.print((peakalt - groundalt) * 3.28);
Serial.println("ft");
if (dataFile) {
dataFile.println("Touchdown!");
dataFile.print("Flight Duration: ");
dataFile.print(millis() - launchmillis);
dataFile.println("ms");
dataFile.print("Peak Altitude: ");
dataFile.print((peakalt - groundalt) * 3.28);
dataFile.println("ft");
}
//clean up the variables before closing out the descent function
peakalt = 0;
currentalt = 0;
groundalt = 0;
buttonstate = digitalRead(armpin);
lastbuttonstate = buttonstate;
dataFile.close();
armed = 0;
}
}
}
void recordAltitude(long flighttime, float altitude){
Serial.print(flighttime);
Serial.print(",");
Serial.println(altitude * 3.28);
if (dataFile) {
dataFile.print(flighttime);
dataFile.print(",");
dataFile.println(altitude * 3.28);
}
delay(loginterval);
}


