Hi all. I'm experiencing an issue with my Arduino Nano based rocket flight computer. It happens very rarely but I'd like to avoid even the small possibility that the rocket crashes. The flight computer basically activates an SG90 servo motor which is deploying a parachute, based on a prefixed amount of time. Sometimes when the timer gets to 0, the servo activates but immediatly after moving to the desired position, the Arduino Nano resets, bringing back the servo to the initial position.
Here is the circuit schematic and the code:
#include <U8x8lib.h>
#include <Wire.h>
#include <MPU6050_light.h>
#include <Servo.h>
#include <Adafruit_BME280.h>
#include <SPI.h>
#include <SD.h>
#include <SimpleKalmanFilter.h>
#define SEA_LEVEL_PRESSURE 997.96
#define G_LAUNCH_THRESHOLD 1.3
#define ALTITUDE_TOLERANCE 0.
#define OPERATIONS_RATE 50
File myFile;
Adafruit_BME280 bme;
MPU6050 mpu(Wire);
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8;
Servo servo;
SimpleKalmanFilter altitudeFilter(0.03, 0.03, 0.01); // Parametri da calibrare
int deploy_time = 5;
unsigned long timer = 0, launch_time = 0;
float alt_ref, apogee = 0;
float last_altitude;
byte servo_status = 0, lift_off = 0, break_wire = 0, start_timer = 0;
byte deploy_mode = 0; // 0 for timer only
// 1 for apogee detection + backup timer
byte launch_detection_mode = 0; // 0 for break wire only
// 1 for break wire OR acceleration rise detection
byte pinB1 = 2;
byte pinB2 = 3;
byte pinB3 = 4;
byte pinB4 = 5;
byte pinBW = 6;
byte pinCS = 7;
void setup() {
pinMode(pinB1, INPUT_PULLUP);
pinMode(pinB2, INPUT_PULLUP);
pinMode(pinB3, INPUT_PULLUP);
pinMode(pinB4, INPUT_PULLUP);
pinMode(pinBW, INPUT_PULLUP);
pinMode(pinCS, OUTPUT);
Wire.begin();
bme.begin(0x76);
mpu.begin();
servo.attach(10);
servo.write(10);
delay(1000);
mpu.calcOffsets(true);
alt_ref = bme.readAltitude(SEA_LEVEL_PRESSURE);
last_altitude = alt_ref;
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r); // Set a readable font for text
if (!SD.begin(pinCS)) {
while(1);
}
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {
myFile.println("\nT(ms)\tAlt(m)\tVel\tServo\tAcc(g)");
myFile.close();
}
delay(500);
}
void loop() {
if (digitalRead(pinBW) == HIGH && break_wire == 0) {
break_wire = 1;
}
static bool B1WasPressed = false;
static bool B2WasPressed = false;
static bool B3WasPressed = false;
static bool B4WasPressed = false;
bool B1Pressed = digitalRead(pinB1) == LOW;
bool B2Pressed = digitalRead(pinB2) == LOW;
bool B3Pressed = digitalRead(pinB3) == LOW;
bool B4Pressed = digitalRead(pinB4) == LOW;
if (lift_off == 0){
if (B2Pressed && !B2WasPressed) {
deploy_time++; // Incrementa la variabile
if (deploy_time > 9) {
deploy_time = 0; // Reimposta a 0 se supera 10
}
}
if (B1Pressed && !B1WasPressed) {
deploy_time--; // Riduce la variabile
if (deploy_time < 0) {
deploy_time = 9; // Reimposta a 9 se va sotto 1
}
}
if (B3Pressed && !B3WasPressed) {
deploy_mode = !deploy_mode;
}
if (B4Pressed && !B4WasPressed) {
launch_detection_mode = !launch_detection_mode;
}
}
mpu.update();
unsigned long dt = millis() - timer;
if (dt > OPERATIONS_RATE){
float ax = mpu.getAccX();
float alt = altitudeFilter.updateEstimate(bme.readAltitude(SEA_LEVEL_PRESSURE));
unsigned long dt_2;
launch_detection(ax);
if (start_timer == 1){
dt_2 = millis() - launch_time;
}
parachute_deploy(alt, lift_off, dt_2, dt);
if (lift_off == 1) {
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {
myFile.print(dt_2);
myFile.print("\t");
myFile.print(alt - alt_ref, 2);
myFile.print("\t");
myFile.print(((alt - last_altitude)) / (dt / 1000.0), 4);
myFile.print("\t");
myFile.print(servo_status);
myFile.print("\t");
myFile.println(ax);
myFile.close();
}
}
last_altitude = alt;
draw(u8x8, lift_off, servo_status, apogee);
timer = millis();
}
B1WasPressed = B1Pressed;
B2WasPressed = B2Pressed;
B3WasPressed = B3Pressed;
B4WasPressed = B4Pressed;
}
void draw(U8X8_SH1106_128X64_NONAME_HW_I2C &oled, byte lift, byte servo, float apo) {
static byte last_lift = 255; // Initialize with an invalid value
static byte last_servo = 255;
static float last_apo = -10000.0;
oled.drawString(0, 7, "T:");
oled.setCursor(2, 7);
oled.print(deploy_time);
oled.setCursor(12, 1);
oled.print(deploy_mode);
oled.setCursor(14, 1);
oled.print(launch_detection_mode);
// Clear and update display only if there's a change in status
if (lift != last_lift || servo != last_servo || (servo == 1 && abs(apo - last_apo) > 0.1)) {
oled.clearDisplay();
if (lift == 0) {
oled.drawString(0, 1, "Ready");
} else {
oled.drawString(0, 1, "Launched");
}
if (servo == 0) {
oled.drawString(0, 3, "P: Not Deployed");
} else {
oled.drawString(0, 3, "P: Deployed");
}
if (servo == 1) {
oled.drawString(0, 5, "Apogee:");
oled.setCursor(7, 5);
oled.print(apo);
oled.drawString(7, 7, "Td:");
oled.setCursor(10, 7);
oled.print((millis() - launch_time)/1000, 1);
}
// Update the tracked state
last_lift = lift;
last_servo = servo;
if (servo == 1) {
last_apo = apo;
}
}
}
void launch_detection(float acc_x){
if (launch_detection_mode == 0){ // only break wire
if (break_wire == 1 && lift_off == 0) {
lift_off = 1; // Launch detected
start_timer = 1;
launch_time = millis();
}
} else if (launch_detection_mode == 1 || launch_detection_mode == true) { // break wire + acceleration detection
if ((abs(acc_x) >= G_LAUNCH_THRESHOLD || break_wire == 1) && lift_off == 0){
lift_off = 1; // Launch detected
start_timer = 1;
launch_time = millis();
}
}
}
void parachute_deploy(float altitude, byte lift, unsigned long dt2, unsigned long dt){
float velocity = ((altitude - last_altitude)) / (dt / 1000.0);
if (deploy_mode == 1) { // velocity check + backup timer
if (((velocity < - 1 && altitude > alt_ref + ALTITUDE_TOLERANCE) || (dt2 > deploy_time*1000)) && lift == 1 && servo_status == 0 ) {
apogee = altitude - alt_ref;
servo.write(180); // deploy parachute
servo_status = 1;
}
} else if (deploy_mode == 0) { // only timer
if (dt2 > deploy_time*1000 && lift == 1 && servo_status == 0) {
apogee = altitude - alt_ref;
servo.write(180); // deploy parachute
servo_status = 1;
}
}
}
The power supply is a 2S 7.4v 20C LiPo battery, which is immediately regulated down to 5V by the MP1584 voltage regulator. I'll be glad if you could help me tackling this issue, thank you.


