Automatic Parachute Deployment for Water Rocket

So I have been working on this project for a few months now. It goes as follows:

Task: Detect when the rocket has reached apogee, then deploy a parachute.

Here are some pictures of the finished product.



And here is a video of a working trial.

So my issue is, the system is not 100% reliable, nor does it deploy fast enough. As seen in the video, the rocket falls a good distance before the parachute is deployed.

So, I'm positive it's something with the code I've written up. Here it is. Feel free to butcher it all you want, I'm no way an expert at programming, but I'd say I'm decent.

General description of what the code is doing:
It first initializes sensors, LED's, and the sd card reader.
it then begins to read the altitude with no delay until it notices that the altitude since its last check has dropped by 1 meter. It then waits 150ms (slightly more than the speed of gravity) to allow for another 1 meter drop. It then waits another 150ms to be 100% sure it's dropping. If it passes all 3 checks the servo is turned and the parachute is deployed.
Here is the code:

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <Servo.h>
File myFile; //creates a file to be written to
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); // sets up the BMP180
int altitude;
int lastAltitude;
int apogee; // Stores max altitude for total height
int groundAltitude; // Stores starting altitude, before launch
int maxHeight;
byte chipSelect = 4; // for sd card reader
int groundTemp;
int apogeeTemp;
int tempChg;
float temperature;
Servo myservo; // Creates servo object
byte yellowLed = 3;
byte redLed = 2;

void setup() {
pinMode(yellowLed, OUTPUT);
pinMode(redLed, OUTPUT);
Serial.begin(9600); // Begins the serial monitor for debugging
pinMode(4, OUTPUT); // for sd card
Serial.print(F("Initializing SD card..."));
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println(F("initialization failed!"));
    digitalWrite(redLed, HIGH);
    return;
  }
  Serial.println(F("initialization done."));
  myFile = SD.open("data.txt", FILE_WRITE);
    myFile.println(" ");
    myFile.println("Starting data logging");
    myFile.println("---------------------");
    delay(50);
    myFile.close();
if(!bmp.begin()) // Initializes the BMP180
  {
    while(1);
  }
  myservo.attach(9); // Mounts the servo to pin 9
  myservo.write(20); // Writes starting pos of servo
  sensors_event_t event; // Starts a reading
  bmp.getEvent(&event);
  groundAltitude = bmp.pressureToAltitude(1013,event.pressure); //reads altitude
  bmp.getTemperature(&temperature); //reads temp
  groundTemp = temperature;
  myFile = SD.open("data.txt", FILE_WRITE);
    myFile.print(F("Altitude before Launch was "));
    myFile.print(groundAltitude);
    myFile.println(F(" meters."));
    myFile.print(F("Temperature before launch was "));
    myFile.print(groundTemp);
    myFile.println(F(" Degrees C."));
    myFile.close();
    digitalWrite(yellowLed, HIGH);
    digitalWrite(redLed, LOW);
    
}

void loop() {
  getAltitude(); // Gets current altitude
  if(altitude - lastAltitude <= -1) // Checks for a 1 meter drop in altitude
  {
    Serial.println("                                         TRIGGERED, MUST BE VERIFIED");
    delay(150); // Gravity is 0.102ms per meter, so 150ms is enough to compensate for drag.
    getAltitude; // Gets a new altitude reading
    if(altitude - lastAltitude <= -2) // Checks if new altitude reading is 1 meter less than last measured
    {
      Serial.println("                                         TRIGGERED 2, MUST BE VERIFIED");
      delay(150); // Gravity is 0.102ms per meter, so 150ms is enough to compensate for drag.
      getAltitude; // Gets a new altitude reading
      if(altitude - lastAltitude <= -3) // Checks if new altitude reading is 2 meters less than last measured
      {
        myservo.write(180); // Moves servo to deploy parachute
        Serial.println("                         DEPLOYING");
        bmp.getTemperature(&temperature);
        apogeeTemp = temperature;
        myFile = SD.open("data.txt", FILE_WRITE);
        myFile.println("Parachute deploying!");
        myFile.close();
        apogee = lastAltitude;
        apogee = apogee - 3;
        maxHeight = apogee - groundAltitude;
        tempChg = groundTemp - apogeeTemp;
        Serial.print(F("Parachute has been deployed. Max Height of rocket was "));
        Serial.print(maxHeight);
        Serial.println(F("meters"));
        myFile = SD.open("data.txt", FILE_WRITE);
        myFile.print(F("Max Height of rocket was "));
        myFile.print(maxHeight);
        myFile.println(F("meters."));
        myFile.print(F("The altitude at apogee was "));
        myFile.print(apogee);
        myFile.println(F("meters"));
        myFile.print(F("The temperature at apogee was "));
        myFile.print(apogeeTemp);
        myFile.println(F(" C"));
        myFile.print("There was a ");
        myFile.print(tempChg);
        myFile.print(F(" degree C change from launch to apogee"));
        myFile.close();
        while(1)
        {
        digitalWrite(yellowLed, LOW);
        delay(1000);
        digitalWrite(yellowLed, HIGH);
        delay(1000); 
        } 
      }
      else
      {
        lastAltitude = altitude; // False reading. Sets current altitude to the last measured altitude
        Serial.println("                                             Didnt fall, 3");
      }
    }
    else
    {
      lastAltitude = altitude; // False reading. Sets current altitude to the last measured altitude
      Serial.println("                                                 Didnt fall, 2");
    }
  }
  else
  {
    lastAltitude = altitude; // False reading. Sets current altitude to the last measured altitude
    Serial.println("                                                 Didnt fall");
  }
}

void getAltitude() // Reads the BMP180 and returns an altitude in meters
{
  sensors_event_t event; // Starts a reading
  bmp.getEvent(&event);
  altitude = bmp.pressureToAltitude(1013,event.pressure); // Sets the altitude to int 'altitude'
  Serial.print(altitude); // Prints Altitude to Serial monitor
 Serial.println( "meters");
 }

So any help of making this system any faster/ reliable would be very helpful! Thanks so much!

So my issue is, the system is not 100% reliable, nor does it deploy fast enough. As seen in the video, the rocket falls a good distance before the parachute is deployed.

There doesn't seem to be any mechanism to eject the nose cone off of the rocket body. You might put a piece of paper under the rubber band that will quickly fall free of the rocket when the rubber band is released. This would give a visual indication when the rubber band releases and compare that to when the nosecone actually separates.

zoomkat:
There doesn't seem to be any mechanism to eject the nose cone off of the rocket body.

There is a folded up "spring" of plastic bottle under the nose cone, as found here.

Back in the day amateur rocket types used a simple tilt detector switch to fire a flash bulb when the rocket started to tilt over. You might do the same to trigger the servo using simple servo button code. The tilt detector was a piece of metal ball chain hanging thru a metal ring. When the rocket started tilting over, the ball chain would touch the metal ring making the electrical switch circuit flashing the bulb.

Wouldn't a accelerometer give better indication of the apogee?

Hi,

Have you tried a dry run with the assembly, push it up and stop it, let it see the drop in altitude and see how long it responds.
Even a vertical track and a launching spring so you can do lab tests.
Make it sound a beeper when ejecting the parachute.
What does your logged data say, is it deploying correctly?
What is the difference in logged data between a good deployment and delayed deployment?
Where abouts have you positioned your pressure sensor, are there any pressure changes inside the capsule due to air speed, which will give you altitude errors.

I like the concept, looks fun.
Tom.... :slight_smile:
PS I would have Excell sprouting graphs of each flight and deployment times.

nutcrapper:
So any help of making this system any faster/ reliable would be very helpful! Thanks so much!

I think your apogee calculation is wrong as well as the condition for releasing the parachute is wrong.

Your apogee calculation should be done each time you read the actual altitude, so perhaps:

      getAltitude; // Gets a new altitude reading
      if (altitude>apogee) apogee=altitude; // remember max. apogee value

And the parachute is not to be activated when falling more than 3 meters since the last measure, but perhaps when falling more than 3 meters since apogee was reached.

      if(apogee>altitude+3) // condition for parachute

jurs:
Your apogee calculation should be done each time you read the actual altitude, so perhaps:

      getAltitude; // Gets a new altitude reading

if (altitude>apogee) apogee=altitude; // remember max. apogee value

Why does it need to save the apogee on every loop? The only reason for the apogee variable is for data logging. This seems like an unnecessary step.

jurs:
And the parachute is not to be activated when falling more than 3 meters since the last measure, but perhaps when falling more than 3 meters since apogee was reached.

      if(apogee>altitude+3) // condition for parachute

Im not sure how this is better than my 3 step check. The reason I used 3 if's was to rule out bad sensor readings. If I were to use the condition you provided a single bad reading <=3 would cause a deploy, which could happen at literally any time the sensor decides to be inconsistent.

nilton61:
Wouldn't a accelerometer give better indication of the apogee?

Probably, but I decided to use an altimeter.

TomGeorge:
Hi,

Have you tried a dry run with the assembly, push it up and stop it, let it see the drop in altitude and see how long it responds.
Even a vertical track and a launching spring so you can do lab tests.
Make it sound a beeper when ejecting the parachute.
What does your logged data say, is it deploying correctly?
What is the difference in logged data between a good deployment and delayed deployment?
Where abouts have you positioned your pressure sensor, are there any pressure changes inside the capsule due to air speed, which will give you altitude errors.

I like the concept, looks fun.
Tom.... :slight_smile:
PS I would have Excell sprouting graphs of each flight and deployment times.

Here is some data logged from 5 launches. The data seems to be correct, and even shows it deploying the parachute at the height it should. What's interesting is 2 of these 5 launches it did not deploy until a few seconds from impact.

Starting data logging
---------------------
Altitude before Launch is 1715 meters.
Temperature before launch is 23 Degrees C.
Parachute deploying!
Max Height of rocket was 37meters.
The altitude at apogee was 1752meters
The temperature at apogee was 22 C
There was a 1 degree C change from launch to apogee


Starting data logging
---------------------
Altitude before Launch is 1720 meters.
Temperature before launch is 22 Degrees C.
Parachute deploying!
Max Height of rocket was 26meters.
The altitude at apogee was 1746meters
The temperature at apogee was 21 C
There was a 1 degree C change from launch to apogee

Starting data logging
---------------------
Altitude before Launch is 1721 meters.
Temperature before launch is 22 Degrees C.
Parachute deploying!
Max Height of rocket was 32meters.
The altitude at apogee was 1753meters
The temperature at apogee was 22 C
There was a 0 degree C change from launch to apogee

Starting data logging
---------------------
Altitude before Launch is 1720 meters.
Temperature before launch is 22 Degrees C.
Parachute deploying!
Max Height of rocket was 38meters.
The altitude at apogee was 1758meters
The temperature at apogee was 22 C
There was a 0 degree C change from launch to apogee

Starting data logging
---------------------
Altitude before Launch is 1721 meters.
Temperature before launch is 22 Degrees C.
Parachute deploying!
Max Height of rocket was 38meters.
The altitude at apogee was 1759meters
The temperature at apogee was 24 C
There was a -2 degree C change from launch to apogee

If your first two readings show the same (falling) result, release the parachute. If not, take a third reading for best of three.

read the pressure in the thrust compartment

As Tom George pointed out, air pressure measurements made from within a moving vehicle usually won't agree with the external air pressure.

Try logging the pressure data for the entire run, from prelaunch to post landing, and plot it out.

Henry_Best:
If your first two readings show the same (falling) result, release the parachute. If not, take a third reading for best of three.

I don't fully understand your proposal. Is this what you mean?
Have two nested if's, if the condition is true for both then deploy. If not true, take one more reading and average all 3 readings together.

If that is what you were saying, I don't understand what the average is for?

I appreciate your help a ton!

jremington:
As Tom George pointed out, air pressure measurements made from within a moving vehicle usually won't agree with the external air pressure.

Try logging the pressure data for the entire run, from prelaunch to post landing, and plot it out.

Thank you for elaborating more on TomGeorge's response, it didn't make a whole lot of sense to me. I will run a launch that logs pressure data the entire flight, then post the data here.

This is caused by the Bernoulli Effect, which states that air (or any fluid) moving parallel to a surface exerts less sideways pressure, and is why airplane wings provide lift.

jremington:
This is caused by the Bernoulli Effect, which states that air (or any fluid) moving parallel to a surface exerts less sideways pressure, and is why airplane wings provide lift.

To solve this could I place 3 1/4in holes in my electronics bay equally around, then place the altimeter in the center of the electronics bay? If not then how could I combat this?

That would certainly help, but apogee detection is not a simple problem. I suggest to do some reading in the model rocketry forums. Here is some excellent work. In particular, this paper describes filtering the data for a much improved estimate of the apogee.

nutcrapper:
I don't fully understand your proposal. Is this what you mean?
Have two nested if's, if the condition is true for both then deploy. If not true, take one more reading and average all 3 readings together.

If that is what you were saying, I don't understand what the average is for?

I appreciate your help a ton!

Not an average, but two out of three. IOW, ignore the one reading that is different to the other two.