123hridoy
Published

Model Rocket

In this project I tried to describe the working of a rocket. The controls are done with arduino.

IntermediateProtip679
Model Rocket

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Altitude/Pressure Sensor Breakout MPL3115A2
SparkFun Altitude/Pressure Sensor Breakout MPL3115A2
×1
Inertial Measurement Unit (IMU) (6 deg of freedom)
Inertial Measurement Unit (IMU) (6 deg of freedom)
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
Memory Socket, SD Card
Memory Socket, SD Card
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Story

Read more

Schematics

Rocket model guide

All codes , Schematics , CAD are provided here

Schematic

Code

Without SD and IMU

Arduino
#include <SFE_BMP180.h>
#include <Wire.h>
#include <Servo.h>

// You will need to create an SFE_BMP180 object, here called "pressure":

SFE_BMP180 pressure;

Servo servo;
int GREENLED=9;
int REDLED=10;
int Check_downs = 0;

double baseline; // baseline pressure

void setup()
{
  Serial.begin(9600);
  Serial.println("REBOOT");

  // Initialize the sensor (it is important to get calibration values stored on the device).
  pinMode(REDLED,OUTPUT);
  pinMode(GREENLED,OUTPUT);
  if (pressure.begin()){
    Serial.println("BMP180 init success");
  }
  else
  {
    
    Serial.println("BMP180 init fail (disconnected?)\n\n");
    while(1); // Pause forever.
  }

  // Get the baseline pressure:
  
  baseline = getPressure();
  
  Serial.print("baseline pressure: ");
  Serial.print(baseline);
  Serial.println(" mb");
  Serial.print("baseline pressure: ");
  Serial.print(baseline/33.864,0);
  Serial.println(" Inhg");  
  
  servo.attach(5); 
  servo.write(90); //sets servo to its midpoint
}

void loop()
{servo.write(90);
delay(10);
  double a,P,a1,a2,P2,Difference;
  
  // Get a new pressure reading:
  
  // Show the relative altitude difference between
  // the new reading and the baseline reading:
  
  //a = pressure.altitude(P,baseline);

  //Serial.print("relative altitude: ");
  //if (a >= 0.0) Serial.print(" "); // add a space for positive numbers
  //Serial.print(a,1);
  //Serial.print(" meters, ");
  //if (a >= 0.0) Serial.print(" "); // add a space for positive numbers
  
  P = getPressure();
  
  a1 = pressure.altitude(P,baseline);

  delay(3000);
  
  P2 = getPressure();
  
  a2 = pressure.altitude(P2,baseline);

  Difference = a2 - a1;
  if (abs(Difference) > 1) {
    if (Difference < 0 ) Check_downs =+ 1;  
    if (Difference > 0 ) Check_downs = 0;  
  }
  
  Serial.print("Start >");
  Serial.print(a1);
  Serial.print(" meter >");
  Serial.println(a2);
 
  Serial.print("Difference: ");
  Serial.print(a1 - a2);
  Serial.println("meters");
  Serial.print("Check downs : ");
  Serial.print(Check_downs);
  Serial.println();

  if (Check_downs == 3) {
    servo.write(90);
     digitalWrite(REDLED,LOW);
  digitalWrite(GREENLED,HIGH);
  
  }
  else
  { digitalWrite(REDLED,HIGH);
  digitalWrite(GREENLED,LOW);
  }
  delay(1000);

}


double getPressure()
{
  char status;
  double T,P,p0,a;

  
  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:

    delay(status);

    
    status = pressure.getTemperature(T);
    if (status != 0)
    {
     
      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Use '&P' to provide the address of P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}

Final Code for full project

Arduino
#include <SD.h>           
#include <Wire.h>       
#include <SFE_BMP180.h>   
#include<Servo.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif
#define INTERRUPT_PIN 2  //I2C Interrupt Pin for MPU6050, use pin 2 on Arduino Uno & most boards
#define BUZZER_PIN 3     //set buzzer pin
#define BLUE_LED_PIN 8   //set blue LED pin
#define YELLOW_LED_PIN 9 //set yellow LED pin
#define RED_LED_PIN 10   //set red LED pin
#define BUTTON_PIN 7     //set button pin
#define chipSelect 4     //set chip select pin for MicroSD Card Adapter (CS pin)
SFE_BMP180 pressure;

Servo servo;

int Check_downs = 0;

double baseline;
//declare general use variables
int buttonState = 0;
int MODE = 0;       //initialize mode to zero
int t = 0;          //create timestamp value
int dataRate = 10;  //set specified sampling rate (data points per second) (somewhere between 10-200 is ideal)

//declare MPU control/status vars
bool blinkState = false;
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

//declare orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

//create objects
File file; 
SFE_BMP180 BMP;
MPU6050 mpu;

//Interrupt Detection Routine
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

void setup() {
  //--- Serial Debugging --- 
  Serial.begin(9600); 
  //--- Establish Pin Modes and turn off all LEDs ---
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);
  pinMode(YELLOW_LED_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(chipSelect, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(INTERRUPT_PIN, INPUT);
  digitalWrite(YELLOW_LED_PIN, LOW);
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
  tone(BUZZER_PIN, 500, 250);
  //initialize SD Card
  if(!SD.begin(chipSelect)){
    //Serial debugging
    Serial.println("Could not initialize SD card");
  }
  //clear SD data
  if(SD.exists("file.txt")){
    if(SD.remove("file.txt") == true){
      Serial.println("removed data");
    }
  }
  //initialize BMP sensor
  if(BMP.begin()){
    Serial.println("BMP init success");
  }
  //initialize IMU and I2C clock
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE  
      Wire.begin();
      Wire.setClock(400000); 
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif
  mpu.initialize(); //start MPU
  Serial.println(F("Testing device connections...")); //debugging serial statement
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); //debugging serial statement
  devStatus = mpu.dmpInitialize();
  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(0);
  mpu.setYGyroOffset(0);
  mpu.setZGyroOffset(0);
  mpu.setZAccelOffset(1688); // 1688 factory default for my test chip
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);
      // enable Arduino interrupt detection
      Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
      Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
      Serial.println(F(")..."));
      attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
      mpuIntStatus = mpu.getIntStatus();
      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;
      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }
  servo.attach(9);
  //set mode
  MODE = 1; //set to PAD IDLE mode - initialize sensors and SD card
  //MODE = 2; //set to FLIGHT mode - log data
  //MODE = 3; //set to RECOVERY mode - close file
}

void loop() {
  servo.write(90);
  delay(100);
  // put your main code here, to run repeatedly:
  if(MODE == 1){  //PAD IDLE MODE
    digitalWrite(RED_LED_PIN, HIGH);
    file = SD.open("file.txt", FILE_WRITE); //Open SD card file
    if(file) {
      Serial.println("t,T,P,ax,ay,az,rx,ry,rz"); //print first line with data labels
      file.println("t,T,P,ax,ay,az,rx,ry,rz");
      MODE = 2;
    }
    else{
      Serial.println("Error opening file");
      delay(5000); //just chill for 5 seconds before trying again
    }
  }
  if(MODE == 2){ //ACTIVE FLIGHT mode
    digitalWrite(YELLOW_LED_PIN, HIGH);
    digitalWrite(RED_LED_PIN, LOW);
    digitalWrite(BLUE_LED_PIN, LOW);
    //print timestamp and comma to separate data
    Serial.print(t);
    Serial.print(",");
    file.print(t);
    file.print(",");
    
    char status;
    double a,P,a1,a2,P2,Difference;
  
  
  P = getPressure();
  
  a1 = pressure.altitude(P,baseline);

  delay(3000);
  
  P2 = getPressure();
  
  a2 = pressure.altitude(P2,baseline);

  Difference = a2 - a1;
  if (abs(Difference) > 1) {
    if (Difference < 0 ) Check_downs =+ 1;  
    if (Difference > 0 ) Check_downs = 0;  
  }
  
  Serial.print("Start >");
  Serial.print(a1);
  Serial.print(" meter >");
  Serial.println(a2);
 
  Serial.print("Difference: ");
  Serial.print(a1 - a2);
  Serial.println("meters");
  Serial.print("Check downs : ");
  Serial.print(Check_downs);
  Serial.println();

  if (Check_downs == 3) {
    servo.write(180);
     digitalWrite(RED_LED_PIN ,LOW);
  digitalWrite(BLUE_LED_PIN,HIGH);
  
  }
  else
  { digitalWrite(RED_LED_PIN ,HIGH);
  digitalWrite(BLUE_LED_PIN,LOW);
  }
  delay(1000);
    
    file.print(",");
    //get IMU data
    if (!dmpReady) return;
    while (!mpuInterrupt && fifoCount < packetSize){
      if (mpuInterrupt && fifoCount < packetSize){
        fifoCount = mpu.getFIFOCount();
      }
    }
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    fifoCount = mpu.getFIFOCount();
    if((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >=1024){
      mpu.resetFIFO();
      fifoCount = mpu.getFIFOCount();
      Serial.println("FIFO Overflow!");
    }
    else if(mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)){
      while(fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
      mpu.getFIFOBytes(fifoBuffer, packetSize);
      fifoCount -= packetSize;
      //get real-world acceleration
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetAccel(&aa, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
      //print real-world acceleration
      Serial.print(aaReal.x);
      file.print(aaReal.x);
      Serial.print(",");
      file.print(",");
      Serial.print(aaReal.y);
      file.print(aaReal.y);
      Serial.print(",");
      file.print(",");
      Serial.print(aaReal.z);
      file.print(aaReal.z);
      Serial.print(",");
      file.print(",");
      //get Euler angles
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetEuler(euler, &q);
      //print Euler angles
      Serial.print(euler[0]*180/M_PI);
      file.print(euler[0]*180/M_PI);
      Serial.print(",");
      file.print(",");
      Serial.print(euler[1]*180/M_PI);
      file.print(euler[1]*180/M_PI);
      Serial.print(",");
      file.print(",");
      Serial.print(euler[2]*180/M_PI);
      file.print(euler[2]*180/M_PI);
    }
    //end data entry line
    Serial.println(); //ends line
    file.println(); //ends line
    //check for mode switch
    buttonState = digitalRead(BUTTON_PIN);
    if(buttonState == LOW){
      MODE = 3;
      tone(BUZZER_PIN, 1000, 250);
      delay(100);
    }
  }
  if(MODE == 3){ //RECOVERY MODE
    file.close();
    digitalWrite(YELLOW_LED_PIN, LOW);
    digitalWrite(RED_LED_PIN, LOW);
    digitalWrite(BLUE_LED_PIN, HIGH);
    delay(1000);
  }
  t = t + 1;              //increment t value
  delay(1000/dataRate);   //pause so that data output corresponds to data rate
  if(t > 32765){          //prevents issues related to integers rolling over at 32767
    t = 1;
  }
}
double getPressure()
{
  char status;
  double T,P,p0,a;

  
  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:

    delay(status);

    
    status = pressure.getTemperature(T);
    if (status != 0)
    {
     
      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}
 \

Credits

123hridoy

123hridoy

2 projects • 3 followers

Comments