Полетный контроллер для ракеты

Shizofreniya

✩✩✩✩✩✩✩
23 Апр 2026
1
0
Добрый день. Просьба тапками не закидывать, это мой первый проект, поэтому часть работы выполнена по принципу, это работало в найденном мной примере, берем от туда. Так что понимаю, что местами будет помесь ежа с носорогом.
Задача: создать систему спасения на ракете с твердотопливным двигателем, а за одно и вести лог полета.
Идея реализации: На основе датчика bmp 280 мерим давление, показания пишем в лог. Когда давление начинает нарастать, подаем сигнал на сервопривод, который высвобождает парашют.
ПРОБЛЕМА: при подключение ардуино к компьютеру скетч работает безупречно, все выполняется как задумал. При запитывании ардуино другим способом - работа останавливается. Причем не важно как, на 5В, на VIN (7В-12В), через USB порт от сети - не работает и все тут.

C++:
#include <Wire.h>
#include <Adafruit_BMP280.h>                                         // библиотека датчика давления
#include <Servo.h>                                                              // библиотека сервопривода
#include "SPI.h"                                                                     // библиотека карты памяти
#include "SD.h"                                                                      // библиотека карты памяти

File myFile;
Servo servoOne;
Adafruit_BMP280 bmp;                                                       // Создание объекта датчика давления
#define SEALEVELPRESSURE_HPA (1021.63)               // Текущее давление на уровне моря в гПа (hPa). Нужно настроить под вашу локальную погоду для точных данных

// НАЗНАЧЕНИЕ ПИНОВ И ПЕРЕМЕННЫХ//
int shake;                                                                              // переменная для хранения значения датчика наклона
int start = 0;                                                                         // переменная для хранения точки старта с датчика наклона
int fall = 0;                                                                            // переменная для хранения точки выпуска парашута
int terra = 0;                                                                         // переменная для хранения точки приземления
float startAlt = 0;                                                                // переменная высоты старта
float maxAlt = 0;                                                                // переменная максимальной высоты
float curAlt;                                                                         // переменная текущей высоты
int tiltSensorPin = 3;                                                          // назначение пина для датчика наклона
const int ServoOnePin = 6;                                               // назначение пина сервопривода
const int chipSelect = 4;                                                   // Указываем к какому выводу подключен CS карты памяти

#define RED_PIN 7                                                           // Красный светодиод на 7 пине
#define BLUE_PIN 9                                                         // Синий светодиод на 9 пине
#define GREEN_PIN 8                                                      // Зеленый светодиод на 8 пине

void setup(){
  pinMode(RED_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(ServoOnePin, OUTPUT);
  servoOne.attach(ServoOnePin);
if (!SD.begin())                                                                    // если карта не завелась
  {
    digitalWrite(RED_PIN, HIGH);                                       // включаем красный светодиод
    return;
  }
  else
  {
    digitalWrite(RED_PIN, HIGH);                                       // включаем красный светодиод
    delay(2000);                                                                    // ждем 2 секунды
    digitalWrite(RED_PIN, LOW);                                        // выключаем красный светодиод
  } 
   
  if (!bmp.begin(0x76)){                                                     // если датчик давления не завелся
    digitalWrite(BLUE_PIN, HIGH);                                     // включаем синий светодиод   
    return;
    }
    else
    {
   bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,                       /* нормальный режим. */
                Adafruit_BMP280::SAMPLING_X2,                                              /* опрос температуры */
                Adafruit_BMP280::SAMPLING_X16,                                           /* опрос давления */
                Adafruit_BMP280::FILTER_X16,                                                  /* Фильтрация */
                Adafruit_BMP280::STANDBY_MS_63                                         /* Таймаут сна */
                );
    digitalWrite(BLUE_PIN, HIGH);                                      // включаем синий светодиод
    delay(2000);                                                                     // ждем 2 секунды
    digitalWrite(BLUE_PIN, LOW);                                       // выключаем синий светодиод
    }                                    
}
void loop(){
  shake = digitalRead (tiltSensorPin);                                 // чтение состояния датчика наклона если выявлено сотрясение, ракета была запущена
  if (shake > start) start = shake;                                         // обновляем значение обнаружено сотрясение
  curAlt = bmp.readAltitude(1013.25);                               // получаем текущую высоту                                  
    if (start == 1 && startAlt == 0){
       startAlt = curAlt;                                                             // запоминаем высоту старта
       maxAlt = curAlt;                                                             // задаем максимальную высоту
       digitalWrite(GREEN_PIN, HIGH);                                 // включаем зеленый светодиод
          for(int i=0;terra==0;i++){                                            // цикл, для записи показаний - до момента пока ракета не совершит посадку (приблизится к стартовой высоте)
          curAlt = bmp.readAltitude(1021.63);                       // получаем текущую высоту                
             if (maxAlt < curAlt) maxAlt = curAlt;                     // обновляем значение максимальной высоты
          myFile = SD.open("log.txt", FILE_WRITE);               // Открытие файла, одновременно может быть открыт только один файл
          if (myFile){
          myFile.println(i);
          myFile.print(F("Температура: "));
          myFile.print(bmp.readTemperature());
          myFile.println(F(" *C"));
          myFile.print(F("Давление: "));
          myFile.print(bmp.readPressure() / 100.0F);             // Па в гПа
          myFile.println(F(" hPa"));
          myFile.print(F("Высота: "));
          myFile.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
          myFile.println(F(" m"));
          myFile.close();                                                                 // Закрываем файла

// ВЫБРОС ПАРАШУТА //    
        if ((maxAlt-curAlt)>=10 && fall==0){                          // если максимальная высота больше текущей + 10 и парашут не выпущен
          servoOne.write(0);
          servoOne.write(180);                                                   // поворачиваем сервопривод
          fall = start;                                                                    // парашют выпущен (больше сервопривод работать не будет)

// КОНЕЦ ЗАПИСИ - ПОСАДКА //
        if (curAlt<=startAlt+10 && maxAlt>=curAlt+10){      // если текущая высота меньше или равна стартовой + 10 и максимальная больше текущей
                 digitalWrite(BLUE_PIN, HIGH);                            // зажигаем синий светодиод
                 myFile = SD.open("end.txt", FILE_WRITE);         // Открытие файла, одновременно может быть открыт только один файл
        if (myFile) {
          myFile.print(F("Максимальная высота: "));
          myFile.print(maxAlt);
          myFile.println(F(" m"));
        
          myFile.print(F("Стартовая высота: "));
          myFile.print(startAlt);
          myFile.println(F(" m"));
          myFile.print(F("Высота подъема: "));
          myFile.print(maxAlt - startAlt);
          myFile.println(F(" m"));
          myFile.close();
          terra = start;                                                                     //присваиваем переменной, не нулевое значение, завершаем цикл for
         }
        }
        }
        else;
        delay(100);                                                                        // Пауза
  }
  }
  else{
  return;
}
}
 

Вложения

Изменено: