Высотомер
- Войдите на сайт для отправки комментариев
Вс, 02/11/2014 - 00:20
Конфигурация - nano + bmp085 + lipo
Предназначение - запись последовательности 500 значений высоты в EEPROM после преодоления минимального порога высоты. В Serial выводится лог при подключении к ПК.
//nano + bmp085 + lipo
//запись последовательности 500 значений высоты в EEPROM
//после преодоления минимального порога высоты
//в Serial выводится лог
#include <EEPROM.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
const int altitudeArrSize = 500;
int altitudeArr[altitudeArrSize]; //массив 500 измерений высоты, приведенной к int (2-а байта), измерения делаются каждые 1/10 секунды
int altitudeArrC = 0; //счетчик измерений
unsigned long altitudeArrTimer;
Adafruit_BMP085 bmp;
int altitude;
int altitudeNorm;
const byte altitudeJmp = 2;
int maxAltitude;
int maxAltitudeEEPROM;
byte altitudeMode;
void EEPROMWriteInt(int p_address, int p_value)
{
byte lowByte = EEPROM.read(p_address);
byte highByte = EEPROM.read(p_address + 1);
int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
if (val != p_value) {
byte lowByte = ((p_value >> 0) & 0xFF);
byte highByte = ((p_value >> 8) & 0xFF);
EEPROM.write(p_address, lowByte);
EEPROM.write(p_address + 1, highByte);
}
}
//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
int EEPROMReadInt(int p_address)
{
byte lowByte = EEPROM.read(p_address);
byte highByte = EEPROM.read(p_address + 1);
return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}
void setup(void) //**************************************************************************************************************
{
//for(int i = 0; i < 1024; i++) EEPROMWriteInt(i,0); // иногда нужно обнулить память для отладки
Serial.begin(9600);
bmp.begin();
// чтение максимальной высоты из EEPROM
maxAltitudeEEPROM = EEPROMReadInt(0);
// запоминаем начальное значение высоты
altitudeNorm = bmp.readAltitude();
//выводим 500 значений лога высоты предыдущего полета
Serial.print("max altitude of previos fly is ");
Serial.print(maxAltitudeEEPROM);
Serial.println(" meter");
Serial.println();
Serial.println("altitude of previos fly is ");
float j = 0;
for(int i = 2; i < 1020; i+=2) {
Serial.print("time ");
Serial.print(j);
j+=1/20.00;
Serial.print(" - ");
Serial.print(EEPROMReadInt(i));
Serial.println();
}
//переводимся в режим ожидания взлета
altitudeMode = 1;
}
void loop(void) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
altitude = bmp.readAltitude() - altitudeNorm;
if (altitude > maxAltitude) {
maxAltitude = altitude;
}
if (maxAltitude > maxAltitudeEEPROM){
maxAltitudeEEPROM = maxAltitude;
EEPROMWriteInt(0, int(maxAltitudeEEPROM));
}
switch (altitudeMode) {
case 0:
// do nothing
break;
case 1://ждем взлет
if (altitude > altitudeJmp){ //значит начали лететь, переводимся из режима ожидания в режим записи высоты
altitudeMode = 2;
}
break;
case 2:
if (altitudeArrTimer < millis()){
altitudeArrTimer = millis() + 50;
//запись в массив
//сохраняем высоту каждые 50 миллисекунд
altitudeArr[altitudeArrC] = int(altitude);
altitudeArrC++;
if (altitudeArrC == altitudeArrSize){
//запись массива в EEPROM
for(int i = 0; i < altitudeArrSize; i++) EEPROMWriteInt(2+i+i,altitudeArr[i]);
altitudeMode = 0;
}
}
break;
}
}
#include <Adafruit_BMP085.h> #include <EEPROM.h> #include <Wire.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte RF_PIN = 13; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const int DURATION_R = 1000; const byte PIN_SSR_LINE_1 = 8; const byte PIN_SSR_LINE_2 = 10; const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte stage2StartAltitude = 6; //const int measureQuantity = 470; const int measureQuantity = 400; const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; int myAltitude; int altitudeNorm; int maxAltitude = 0; int beepTimerDuration = 48; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 11; byte tempF; byte rocketMode = 1; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 3000 #define KEY_LINE_2_PROC_DURATION 3000 int testDA[400] = {0,0,1,1,2,4,4,5,7,12,16,18,18,21,24,27,29,32,36,40,43,48,52,56,56,61,66,71,77,77,83,88,94,99,105,110,110,116,122,129,136,141,141,146,146,150,154,159,159,163,163,166,170,170,172,172,175,175,177,181,183,183,199,194,194,205,209,209,214,220,227,223,223,248,252,252,259,256,264,257,268,268,275,274,278,278,285,288,288,295,296,296,297,304,304,307,310,310,311,316,315,315,319,324,324,328,328,330,332,333,333,334,336,336,339,343,344,347,347,348,348,349,352,354,357,358,361,362,363,364,366,366,368,369,369,371,372,372,372,376,376,376,376,376,378,380,380,382,382,383,383,384,384,384,386,387,388,388,388,389,390,390,391,390,390,390,392,392,392,393,392,394,393,393,394,393,394,394,394,394,394,394,394,393,393,393,392,392,392,391,391,391,390,390,390,389,389,389,387,388,387,387,386,385,384,384,384,384,383,381,382,382,379,379,377,376,376,374,373,372,372,371,369,368,366,364,364,363,363,363,361,361,361,358,355,353,353,351,349,346,346,343,343,340,338,335,334,334,332,330,329,326,323,323,320,319,315,315,312,310,308,305,305,303,300,298,298,296,292,291,289,289,286,284,284,282,278,277,277,273,271,268,268,262,258,257,257,254,252,250,249,249,245,242,242,236,235,232,230,230,227,224,224,221,219,219,215,213,211,211,208,208,205,203,203,198,195,192,189,185,182,179,176,173,170,170,167,163,161,159,159,154,152,152,150,147,142,142,138,138,135,132,132,129,125,125,123,120,115,111,111,110,106,101,98,98,96,92,92,90,85,85,82}; int testDAInd = 0; void setup(void) { //for(int i = 0; i < 1024; i++) EEPROMWriteInt(i,0); // иногда нужно обнулить память для отладки Serial.begin(9600); pinMode(A1, INPUT); int ar = analogRead(A1); if (ar != 0) couldBeep = true; checkSerial(); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_BEEP, OUTPUT); digitalWrite(PIN_LED, HIGH); if (couldBeep) { digitalWrite(PIN_BEEP, HIGH); delay(200); digitalWrite(PIN_BEEP, LOW); delay(500); digitalWrite(PIN_BEEP, HIGH); delay(500); digitalWrite(PIN_BEEP, LOW); } else { delay(1000); } digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); if (!bmp.begin()) { digitalWrite(PIN_LED, HIGH); digitalWrite(PIN_BEEP, HIGH); while (1); } altitudeNorm = bmp.readAltitude(); } void loop() { pinMode (RF_PIN, OUTPUT); float mAA; int aSm; int i; int j; int h; if (sleepMode) { proc1(); digitalWrite(PIN_LED, HIGH); if (couldBeep) digitalWrite(PIN_BEEP, HIGH); delay(30); digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); pinMode (RF_PIN, INPUT); adc_disable(); MCUSR = 0; WDTCSR = bit (WDCE) | bit (WDE); WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); sleep_disable(); } else { if (beepTimer < millis()) { beepTimer = millis() + beepTimerDuration; //myAltitude = bmp.readAltitude() - altitudeNorm; myAltitude = testDA[testDAInd]; testDAInd++; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; h++; } for (i = 0; i < FILTER_SIZE - 1; i++) { aSm = aSm + dA[i]; } mAA = (float)aSm / (FILTER_SIZE - 1); Serial.println(mAA); currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: beepStatus = !beepStatus; if (beepStatus) { mode1BeepStatus = !mode1BeepStatus; } if (mode1BeepStatus) { mode1Beep2Status = !mode1Beep2Status; } if (mode1Beep2Status) { digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); } else { digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); } if (mAA > 0) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(10, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } } break; case 2: beepStatus = !beepStatus; if (beepStatus) { digitalWrite(PIN_LED, HIGH); } else { digitalWrite(PIN_LED, LOW); } tone(RF_PIN, myAltitude); if ((mAA < 0) && !rocketFlyBack) { rocketFlyBack = true; EEPROMWriteInt(0, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(4, timeToCheckAppogeyInMillis); digitalWrite(PIN_SSR_LINE_2, LOW); delay(10); ssr_line_2_worked = true; EEPROMWriteInt(10, myAltitude); digitalWrite(PIN_SSR_LINE_1, HIGH); delay(10); ssr_line_1_init = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; } if ((myAltitude > stage2StartAltitude) && !ssr_line_2_init) { digitalWrite(PIN_SSR_LINE_2, HIGH); delay(10); timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; ssr_line_2_init = true; } if ((timer_line_1 < millis()) && !ssr_line_1_worked) { digitalWrite(PIN_SSR_LINE_1, LOW); delay(10); ssr_line_1_worked = true; turn3Mode = true; } if ((timer_line_2 < millis()) && !ssr_line_2_worked ) { digitalWrite(PIN_SSR_LINE_2, LOW); delay(10); ssr_line_2_worked = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart); EEPROMWriteInt(6, recordsTime); int speedOfRecordInSec = recordsTime / measureQuantity; speedOfRecordInSec = 1000 / speedOfRecordInSec; EEPROMWriteInt(8, speedOfRecordInSec); } } if ( turn3Mode && eepromWritingComplete ) { rocketMode = 3; tone(RF_PIN, 540); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 340); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(RF_PIN); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } break; case 3: sleepMode = true; break; } } } } void proc0() { tone(RF_PIN, 450); delay(DURATION_0); noTone(RF_PIN); } void proc1() { tone(RF_PIN, 550); delay(DURATION_1); noTone(RF_PIN); } void checkSerial() { delay(3000); if (Serial.available()) { int maxAltitudeEEPROM = EEPROMReadInt(0); int line_1_InitiatedAltitude = EEPROMReadInt(10); int timeToCheckAppogeyInMillis = EEPROMReadInt(4); int recordsTimeInMillis = EEPROMReadInt(6); int recordsRate = EEPROMReadInt(8); Serial.println(); Serial.print("max altitude: "); Serial.print(maxAltitudeEEPROM); Serial.println(" m"); Serial.println(); Serial.print("line_1_InitiatedAltitude: "); Serial.print(line_1_InitiatedAltitude); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogeyInMillis: "); Serial.print(timeToCheckAppogeyInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsTimeInMillis: "); Serial.print(recordsTimeInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsRate: "); Serial.print(recordsRate); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = 0; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } ISR (WDT_vect) { wdt_disable(); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } }Версия 2
#include <Adafruit_BMP085.h> #include <EEPROM.h> #include <Wire.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte RF_PIN = 11; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const byte PIN_SSR_LINE_1 = 8; const byte PIN_SSR_LINE_2 = 10; const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte cAltitude = 5; const byte cS2Altitude = 6; const int measureQuantity = 480; const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; int myAltitude; int altitudeNorm; int maxAltitude = 0; int beepTimerDuration = 50; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 11; byte rocketMode = 1; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 3000 #define KEY_LINE_2_PROC_DURATION 3000 void setup(void) { //for(int i = 0; i < 1024; i++) EEPROMWriteInt(i,0); Serial.begin(9600); pinMode(A1, INPUT); int ar = analogRead(A1); if (ar != 0) couldBeep = true; checkSerial(); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_BEEP, OUTPUT); digitalWrite(PIN_LED, HIGH); if (couldBeep) { digitalWrite(PIN_BEEP, HIGH); delay(200); digitalWrite(PIN_BEEP, LOW); delay(500); digitalWrite(PIN_BEEP, HIGH); delay(500); digitalWrite(PIN_BEEP, LOW); } else { delay(1000); } digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); if (!bmp.begin()) { digitalWrite(PIN_LED, HIGH); digitalWrite(PIN_BEEP, HIGH); while (1); } altitudeNorm = bmp.readAltitude(); } void loop() { pinMode (RF_PIN, OUTPUT); int mAA; int aSm; int i; int j; int h; if (sleepMode) { proc1(); digitalWrite(PIN_LED, HIGH); if (couldBeep) digitalWrite(PIN_BEEP, HIGH); delay(30); digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); pinMode (RF_PIN, INPUT); adc_disable(); MCUSR = 0; WDTCSR = bit (WDCE) | bit (WDE); WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); sleep_disable(); } else { if (beepTimer < millis()) { beepTimer = millis() + beepTimerDuration; myAltitude = bmp.readAltitude() - altitudeNorm; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; h++; } for (i = 0; i < FILTER_SIZE - 1; i++) { aSm = aSm + dA[i]; } mAA = aSm / (FILTER_SIZE - 1); currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: beepStatus = !beepStatus; if (beepStatus) { mode1BeepStatus = !mode1BeepStatus; } if (mode1BeepStatus) { mode1Beep2Status = !mode1Beep2Status; } if (mode1Beep2Status) { digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); } else { digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); } if (mAA > 0 && myAltitude > cAltitude) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(10, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } } break; case 2: beepStatus = !beepStatus; if (beepStatus) { digitalWrite(PIN_LED, HIGH); } else { digitalWrite(PIN_LED, LOW); } tone(RF_PIN, myAltitude); if ((mAA <= 0) && !rocketFlyBack && myAltitude > cAltitude) { rocketFlyBack = true; EEPROMWriteInt(0, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(4, timeToCheckAppogeyInMillis); digitalWrite(PIN_SSR_LINE_2, LOW); delay(10); ssr_line_2_worked = true; EEPROMWriteInt(10, myAltitude); digitalWrite(PIN_SSR_LINE_1, HIGH); delay(10); ssr_line_1_init = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; } if ((myAltitude > cS2Altitude) && !ssr_line_2_init) { digitalWrite(PIN_SSR_LINE_2, HIGH); delay(10); timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; ssr_line_2_init = true; } if ((timer_line_1 < millis()) && !ssr_line_1_worked && ssr_line_1_init) { digitalWrite(PIN_SSR_LINE_1, LOW); delay(10); ssr_line_1_worked = true; turn3Mode = true; } if ((timer_line_2 < millis()) && !ssr_line_2_worked && ssr_line_2_init) { digitalWrite(PIN_SSR_LINE_2, LOW); delay(10); ssr_line_2_worked = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart); EEPROMWriteInt(6, recordsTime); int speedOfRecordInSec = recordsTime / measureQuantity; speedOfRecordInSec = 1000 / speedOfRecordInSec; EEPROMWriteInt(8, speedOfRecordInSec); } } if ( turn3Mode && eepromWritingComplete ) { rocketMode = 3; tone(RF_PIN, 540); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 340); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(RF_PIN); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } break; case 3: sleepMode = true; break; } } } } void proc0() { tone(RF_PIN, 450); delay(DURATION_0); noTone(RF_PIN); } void proc1() { tone(RF_PIN, 550); delay(DURATION_1); noTone(RF_PIN); } void checkSerial() { delay(3000); if (Serial.available()) { int maxAltitudeEEPROM = EEPROMReadInt(0); int line_1_InitiatedAltitude = EEPROMReadInt(10); int timeToCheckAppogeyInMillis = EEPROMReadInt(4); int recordsTimeInMillis = EEPROMReadInt(6); int recordsRate = EEPROMReadInt(8); Serial.println(); Serial.print("maxAltitude: "); Serial.print(maxAltitudeEEPROM); Serial.println(" m"); Serial.println(); Serial.print("line_1_InitiatedAltitude: "); Serial.print(line_1_InitiatedAltitude); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogey: "); Serial.print(timeToCheckAppogeyInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsTimeInMillis: "); Serial.print(recordsTimeInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsRate: "); Serial.print(recordsRate); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = startEEPPROMWriting; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } ISR (WDT_vect) { wdt_disable(); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } }UPS, а что произойдет если одновременно с набором высоты меняется и атмосферное давление?
Проект заточен для использования в системах спасения моделей ракет, а там как раз с одновременным набором высоты меняется давление, алгоритм определяет момент старта и прохождения аппогея. Что конкретно интересует?
У Вас процесс быстрый, так что все в порядке.
Заинтересовало, если буду пешком подниматься и одновременно меняются метеоусловия, ведь обманет.))))
Если подниматься ооочень долго, то скорее всего, влияние метеоусловий на показания может иметь место, но насколько это может быть существенно?
на высоте 500 метров над уровнем моря давление меняется в пределах 10 мм ртутного столба ( в районе 714)
примерно 1мм на 10,5м. При изменении с 760 до 750, ошибка составит 100 метров.
Для ТС не актуально, для альпинистов вопрос.
// MRIA-2 #include <Adafruit_BMP085.h> #include <EEPROM.h> #include <Wire.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte RF_PIN = 11; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const byte PIN_SSR_LINE_1 = 8; // ключ для инициации первой мортиры (тормозной парашют) const byte PIN_SSR_LINE_2 = 10; // ключ для инициации второй мортиры (основной парашют), либо запуска второй ступени для режима 2С (b2SPMode = true) const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte cAltitude = 10; //высота активации режима "полет" const byte cS2Altitude = 12; //высота активации ключа для запуска второй ступени для режима 2С (b2SPMode = true) const int measureQuantity = 480; // длина лога данных (ограничена емкостью ПЗУ) const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long delay_timer_line_1 = 0; unsigned long delay_timer_line_2 = 0; unsigned long delay_timer_line_3 = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; unsigned long timer_line_3 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_3_worked = false; boolean ssr_line_1_down = false; boolean ssr_line_2_down = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean ssr_line_3_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; boolean b2SPMode = false; //для режима 2С (b2SPMode = true) int myAltitude; int altitudeNorm; int maxAltitude = 0; int beepTimerDuration = 50; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 10; byte rocketMode = 1; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 3000 #define KEY_LINE_2_PROC_DURATION 3000 #define KEY_LINE_3_PROC_DURATION 3000 //задержки мс инициации ключей после определения прохождения аппогея #define DELAY_LINE_1 0 #define DELAY_LINE_2 3500 void setup(void) { //for(int i = 0; i < 1024; i++) EEPROMWriteInt(i,0); Serial.begin(9600); pinMode(A1, INPUT); pinMode(A2, INPUT); int ar1 = analogRead(A1); int ar2 = analogRead(A2); //2 STAGE ************** if (b2SPMode) { ar2 = 0; } //************** if (ar1 != 0 || ar2 != 0) couldBeep = true; checkSerial(); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_BEEP, OUTPUT); digitalWrite(PIN_LED, HIGH); if (couldBeep) { digitalWrite(PIN_BEEP, HIGH); delay(200); digitalWrite(PIN_BEEP, LOW); delay(500); digitalWrite(PIN_BEEP, HIGH); delay(1000); digitalWrite(PIN_BEEP, LOW); } else { delay(1000); } if (!bmp.begin()) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_LED, HIGH); digitalWrite(PIN_BEEP, HIGH); while (1); } digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); altitudeNorm = bmp.readAltitude(); } void loop() { pinMode (RF_PIN, OUTPUT); int mAA; int aSm; int i; int j; int h; if (sleepMode) { proc1(); digitalWrite(PIN_LED, HIGH); if (couldBeep) digitalWrite(PIN_BEEP, HIGH); delay(30); digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); pinMode (RF_PIN, INPUT); adc_disable(); MCUSR = 0; WDTCSR = bit (WDCE) | bit (WDE); WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); sleep_disable(); } else { if (beepTimer < millis()) { beepTimer = millis() + beepTimerDuration; myAltitude = bmp.readAltitude() - altitudeNorm; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; h++; } for (i = 0; i < FILTER_SIZE - 1; i++) { aSm = aSm + dA[i]; } mAA = aSm / (FILTER_SIZE - 1); currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: beepStatus = !beepStatus; if (beepStatus) { mode1BeepStatus = !mode1BeepStatus; } if (mode1BeepStatus) { mode1Beep2Status = !mode1Beep2Status; } if (mode1Beep2Status) { digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); } else { digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); } if (mAA > 0 && myAltitude > cAltitude) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(10, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } } break; case 2: beepStatus = !beepStatus; if (beepStatus) { digitalWrite(PIN_LED, HIGH); } else { digitalWrite(PIN_LED, LOW); } tone(RF_PIN, myAltitude); //2 STAGE ************** if (b2SPMode) { if (myAltitude > cS2Altitude && !ssr_line_3_init) { // режим второй ступени, задействован 2-й ключ ssr_line_3_init = true; delay_timer_line_3 = millis() + KEY_LINE_3_PROC_DURATION; digitalWrite(PIN_SSR_LINE_2, HIGH); } if (ssr_line_3_init && delay_timer_line_3 < millis() && !ssr_line_3_worked) { digitalWrite(PIN_SSR_LINE_2, LOW); ssr_line_3_worked = true; } } if ((mAA < 0) && !rocketFlyBack && myAltitude > cAltitude) { rocketFlyBack = true; EEPROMWriteInt(0, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(4, timeToCheckAppogeyInMillis); EEPROMWriteInt(10, myAltitude); delay_timer_line_1 = millis() + DELAY_LINE_1; ssr_line_1_init = true; delay_timer_line_2 = millis() + DELAY_LINE_2; ssr_line_2_init = true; } if (ssr_line_1_init && !ssr_line_1_worked && delay_timer_line_1 < millis()) { ssr_line_1_worked = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; digitalWrite(PIN_SSR_LINE_1, HIGH); } if (ssr_line_2_init && !ssr_line_2_worked && delay_timer_line_2 < millis()) { ssr_line_2_worked = true; timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; if (!b2SPMode) { digitalWrite(PIN_SSR_LINE_2, HIGH); } } if ((timer_line_1 < millis()) && ssr_line_1_worked && !ssr_line_1_down) { digitalWrite(PIN_SSR_LINE_1, LOW); ssr_line_1_down = true; } if ((timer_line_2 < millis()) && ssr_line_2_worked && !ssr_line_2_down) { digitalWrite(PIN_SSR_LINE_2, LOW); ssr_line_2_down = true; } if (ssr_line_1_down && ssr_line_2_down) { turn3Mode = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart); EEPROMWriteInt(6, recordsTime); int speedOfRecordInSec = recordsTime / measureQuantity; speedOfRecordInSec = 1000 / speedOfRecordInSec; EEPROMWriteInt(8, speedOfRecordInSec); } } if (turn3Mode && eepromWritingComplete) { rocketMode = 3; } break; case 3: playExitFlyModeAction(); sleepMode = true; break; } } } } void playExitFlyModeAction() { tone(RF_PIN, 540); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 340); delay(500); digitalWrite(PIN_LED, LOW); tone(RF_PIN, 440); delay(500); digitalWrite(PIN_LED, HIGH); tone(RF_PIN, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(RF_PIN); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } void proc0() { tone(RF_PIN, 450); delay(DURATION_0); noTone(RF_PIN); } void proc1() { tone(RF_PIN, 550); delay(DURATION_1); noTone(RF_PIN); } void checkSerial() { delay(3000); if (Serial.available()) { int maxAltitudeEEPROM = EEPROMReadInt(0); int line_1_InitiatedAltitude = EEPROMReadInt(10); int timeToCheckAppogeyInMillis = EEPROMReadInt(4); int recordsTimeInMillis = EEPROMReadInt(6); int recordsRate = EEPROMReadInt(8); Serial.println(); Serial.print("maxAltitude: "); Serial.print(maxAltitudeEEPROM); Serial.println(" m"); Serial.println(); Serial.print("line_1_InitiatedAltitude: "); Serial.print(line_1_InitiatedAltitude); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogey: "); Serial.print(timeToCheckAppogeyInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsTimeInMillis: "); Serial.print(recordsTimeInMillis); Serial.println(" millis"); Serial.println(); Serial.print("recordsRate: "); Serial.print(recordsRate); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = startEEPPROMWriting; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } ISR (WDT_vect) { wdt_disable(); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } }В итоге сколько по времени это устройство может записывать высоту?
в текущей конфигурации 24 секунды, 480 значений и десять параметров работы
Вы, наверное, изучали эту тему. Возможно ли увеличить объем EEPROM памяти в ардуино? И почему бы не использовать модуль для sd карты?
чем меньше составляющих, тем надежнее работает устройство, и так сталось, для логов полетов моих моделей ракет много памяти не нужно, вот смотрите
http://forum.modelka.com.ua/threads/65988-Запуски-ракет-и-испытания-двигателей/page21?p=749606&viewfull=1#post749606
Я вот тоже ракеты клепаю, но времени явно мало для записи всего полета до приземления. Хотя, если замерять дважды в секунду, то можно добится времени до 250 с, что для моего уровня пока что хватит =) Еще одна проблема- невозможно записать сразу второй полет, пока не скинешь данные с высотомера.
можно часто писать данные до апогея, затем реже.
лог полета можно передавать по радиоканалу, хотя сливать данные в пк еще проще, непроблема подключить шнур, вбить в сериал что-либо и дождаться лога в мониторе.
да, а есть ссылки на модели?
Ага, думаю реализовать возможность подключения bluetooth- модуля для передачи лога прямо на телефон.
В моделях ничего необычного нет, все технологии с сайта rocki и serge77. Пока набираюсь опыта =) Я посмотрел на ваши ракеты. Зачем нужен такой огромный калибр (75), можно ведь намного улучшить летные характеристики, уменьшив диаметр?
все начиналось с малого, но большой калибр лучше видно, т.е. зрелищность, а попробуйте?
и посмотрите на проект Мрия
Да, зрелищность на высоте) Что за топливо? Факел хоршоший.
Я сделал высотомер с вашей прошивкой. Спасибо, все отлично работает =)
если что, там на форуме есть инфа, карамель с титаном
// IRP.1.2 FOR MRIA & 75 2S & 40 //#include <Adafruit_BMP280.h> #include <Adafruit_BMP085.h> #include <EEPROM.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte PIN_RF = 11; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const byte PIN_SSR_LINE_1 = 8; // ключ для инициации первой мортиры (тормозной парашют) const byte PIN_SSR_LINE_2 = 10; // ключ для инициации второй мортиры (основной парашют) const byte PIN_SSR_LINE_3 = 7; // ключ для инициации мотора второй ступени const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte cAltitude = 10; //высота активации режима "полет" const byte cS2Altitude = 10; //высота активации ключа для запуска второй ступени const int measureQuantity = 480; // длина лога данных (ограничена емкостью ПЗУ) const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long waiting2StageStart = 0; unsigned long RF_Beeping = 0; unsigned long delay_timer_line_1 = 0; unsigned long delay_timer_line_2 = 0; unsigned long delay_timer_line_3 = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; unsigned long timer_line_3 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_3_worked = false; boolean ssr_line_1_down = false; boolean ssr_line_2_down = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean ssr_line_3_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; int myAltitude; int sUmErMax; int altitudeNorm; int maxAltitude = 0; int beepTimerDuration = 100; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 10; byte rocketMode = 1; //Adafruit_BMP280 bmp; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 3000 #define KEY_LINE_2_PROC_DURATION 3000 #define KEY_LINE_3_PROC_DURATION 3000 //задержки мс инициации ключей после определения прохождения аппогея #define DELAY_LINE_1 0 #define DELAY_LINE_2 5000 #define DELAY_WAITING_2STAGE_START 5000 #define DELAY_RF_FLY_START 30000 #define MAX_ALTITUDE_EEPROM 0 #define ALTITUDE_IND_EEPROM 2 #define CHECK_APOGEY_EEPROM 4 #define REC_DURATION_EEPROM 6 #define RECORDS_RATE_EEPROM 8 #define MIDDLE_ALT_I_EEPROM 10 void setup(void) { Serial.begin(9600); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_SSR_LINE_3, OUTPUT); pinMode(PIN_BEEP, OUTPUT); delay(50); if (!bmp.begin()) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); while (1); } delay(50); int ar1 = analogRead(A1); int ar2 = analogRead(A2); int ar3 = analogRead(A3); couldBeep = true; if (ar1 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(1000); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); if (ar2 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(1000); if (ar3 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(1000); } } } checkSerial(); altitudeNorm = bmp.readAltitude(); RF_Beeping = millis() + DELAY_RF_FLY_START; } void loop() { int mAA; long aSm; int i; int j; int h; long sUmEr; pinMode (PIN_RF, OUTPUT); if (sleepMode) { proc1(); digitalWrite(PIN_LED, HIGH); if (couldBeep) digitalWrite(PIN_BEEP, HIGH); delay(30); digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); pinMode (PIN_RF, INPUT); adc_disable(); MCUSR = 0; WDTCSR = bit (WDCE) | bit (WDE); WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); sleep_disable(); } else { if (beepTimer < millis()) { beepTimer = millis() + beepTimerDuration; myAltitude = bmp.readAltitude() - altitudeNorm; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; } sUmEr = 0; for (i = 0; i < FILTER_SIZE; i++) { aSm = aSm + dA[i]; sUmEr = sUmEr + altitudes[i]; } mAA = aSm / FILTER_SIZE; sUmEr = sUmEr / FILTER_SIZE; if (sUmEr > sUmErMax) { sUmErMax = sUmEr; } currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: beepStatus = !beepStatus; if (beepStatus) { mode1BeepStatus = !mode1BeepStatus; } if (mode1BeepStatus) { mode1Beep2Status = !mode1Beep2Status; } if (mode1Beep2Status) { digitalWrite(PIN_LED, HIGH); if (RF_Beeping > millis()) { tone(PIN_RF, 540); } } else { digitalWrite(PIN_LED, LOW); noTone(PIN_RF); } if (myAltitude > cAltitude) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(2, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); EEPROMWriteInt(10, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } waiting2StageStart = millis() + DELAY_WAITING_2STAGE_START; } break; case 2: beepStatus = !beepStatus; if (beepStatus) { digitalWrite(PIN_LED, HIGH); } else { digitalWrite(PIN_LED, LOW); } tone(PIN_RF, myAltitude); if (myAltitude > cS2Altitude && !ssr_line_3_init) { ssr_line_3_init = true; delay_timer_line_3 = millis() + KEY_LINE_3_PROC_DURATION; digitalWrite(PIN_SSR_LINE_3, HIGH); } if (ssr_line_3_init && delay_timer_line_3 < millis() && !ssr_line_3_worked) { digitalWrite(PIN_SSR_LINE_3, LOW); ssr_line_3_worked = true; } if ((mAA < 0) && !rocketFlyBack && (sUmEr < sUmErMax) && (myAltitude > cAltitude) && (waiting2StageStart < millis())) { rocketFlyBack = true; EEPROMWriteInt(MAX_ALTITUDE_EEPROM, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(CHECK_APOGEY_EEPROM, timeToCheckAppogeyInMillis); EEPROMWriteInt(ALTITUDE_IND_EEPROM, measureCurrent); EEPROMWriteInt(MIDDLE_ALT_I_EEPROM, sUmEr); delay_timer_line_1 = millis() + DELAY_LINE_1; ssr_line_1_init = true; delay_timer_line_2 = millis() + DELAY_LINE_2; ssr_line_2_init = true; } if (ssr_line_1_init && !ssr_line_1_worked && delay_timer_line_1 < millis()) { ssr_line_1_worked = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; digitalWrite(PIN_SSR_LINE_1, HIGH); } if (ssr_line_2_init && !ssr_line_2_worked && delay_timer_line_2 < millis()) { ssr_line_2_worked = true; timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; digitalWrite(PIN_SSR_LINE_2, HIGH); } if ((timer_line_1 < millis()) && ssr_line_1_worked && !ssr_line_1_down) { digitalWrite(PIN_SSR_LINE_1, LOW); ssr_line_1_down = true; } if ((timer_line_2 < millis()) && ssr_line_2_worked && !ssr_line_2_down) { digitalWrite(PIN_SSR_LINE_2, LOW); ssr_line_2_down = true; } if (ssr_line_1_down && ssr_line_2_down) { turn3Mode = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart) / 10; EEPROMWriteInt(REC_DURATION_EEPROM, recordsTime); int speedOfRecordInSec = recordsTime / measureQuantity; speedOfRecordInSec = 100 / speedOfRecordInSec; EEPROMWriteInt(RECORDS_RATE_EEPROM, speedOfRecordInSec); } } if (turn3Mode && eepromWritingComplete) { rocketMode = 3; } break; case 3: playExitFlyModeAction(); sleepMode = true; break; } } } } void playExitFlyModeAction() { tone(PIN_RF, 940); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 840); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 740); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 640); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(PIN_RF); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } void proc0() { tone(PIN_RF, 450); delay(DURATION_0); noTone(PIN_RF); } void proc1() { tone(PIN_RF, 550); delay(DURATION_1); noTone(PIN_RF); } void checkSerial() { delay(3000); if (Serial.available()) { Serial.println(); Serial.print("maxAltitude: "); Serial.print(EEPROMReadInt(MAX_ALTITUDE_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("Altitude Index Pyro Initiated: "); Serial.print(EEPROMReadInt(ALTITUDE_IND_EEPROM)); Serial.println(" "); Serial.println(); Serial.print("Midde Altitude Pyro Initiated: "); Serial.print(EEPROMReadInt(MIDDLE_ALT_I_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogey: "); Serial.print(EEPROMReadInt(CHECK_APOGEY_EEPROM)); Serial.println(" millis"); Serial.println(); Serial.print("recordsTimeInMillis/10: "); Serial.print(EEPROMReadInt(REC_DURATION_EEPROM)); Serial.println(" millis"); Serial.println(); Serial.print("recordsRate: "); Serial.print(EEPROMReadInt(RECORDS_RATE_EEPROM)); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = startEEPPROMWriting; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } ISR (WDT_vect) { wdt_disable(); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } }оптимизация кода и алгоритма определения апогея, доработано под BMP280
// IRP.1.3 FOR MRIA & 75 2S & 40 //#include <Adafruit_BMP280.h> #include <Adafruit_BMP085.h> #include <EEPROM.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte PIN_RF = 11; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const byte PIN_SSR_LINE_1 = 8; // ключ для инициации первой мортиры (тормозной парашют) const byte PIN_SSR_LINE_2 = 10; // ключ для инициации второй мортиры (основной парашют) const byte PIN_SSR_LINE_3 = 7; // ключ для инициации мотора второй ступени const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte cAltitude = 5; //высота активации режима "полет" const byte cS2Altitude = 7; //высота активации ключа для запуска второй ступени const int measureQuantity = 480; // длина лога данных (ограничена емкостью ПЗУ) const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long waiting2StageStart = 0; unsigned long RF_Beeping = 0; unsigned long delay_timer_line_1 = 0; unsigned long delay_timer_line_2 = 0; unsigned long delay_timer_line_3 = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; unsigned long timer_line_3 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_3_worked = false; boolean ssr_line_1_down = false; boolean ssr_line_2_down = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean ssr_line_3_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; int myAltitude; int sUmErMax; int altitudeNorm; int maxAltitude = 0; int beepTimerDuration = 100; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 10; byte rocketMode = 1; //Adafruit_BMP280 bmp; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 5000 #define KEY_LINE_2_PROC_DURATION 5000 #define KEY_LINE_3_PROC_DURATION 5000 //задержки мс инициации ключей после определения прохождения аппогея #define DELAY_LINE_1 0 #define DELAY_LINE_2 10000 #define DELAY_WAITING_2STAGE_START 5000 #define DELAY_RF_FLY_START 60000 #define MAX_ALTITUDE_EEPROM 0 #define ALTITUDE_IND_EEPROM 2 #define CHECK_APOGEY_EEPROM 4 #define REC_DURATION_EEPROM 6 #define RECORDS_RATE_EEPROM 8 #define MIDDLE_ALT_I_EEPROM 10 void setup(void) { Serial.begin(9600); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_SSR_LINE_3, OUTPUT); pinMode(PIN_BEEP, OUTPUT); delay(50); if (!bmp.begin()) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); while (1); } delay(50); int ar1 = analogRead(A1); int ar2 = analogRead(A2); int ar3 = analogRead(A3); couldBeep = true; if (ar1 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(1000); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); if (ar2 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(1000); if (ar3 > 900) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); digitalWrite(PIN_RF, LOW); digitalWrite(PIN_LED, LOW); delay(1000); } } } checkSerial(); altitudeNorm = bmp.readAltitude(); RF_Beeping = millis() + DELAY_RF_FLY_START; } void loop() { int mAA; long aSm; int i; int j; int h; long sUmEr; pinMode (PIN_RF, OUTPUT); if (sleepMode) { proc1(); digitalWrite(PIN_LED, HIGH); if (couldBeep) digitalWrite(PIN_BEEP, HIGH); delay(30); digitalWrite(PIN_LED, LOW); digitalWrite(PIN_BEEP, LOW); pinMode (PIN_RF, INPUT); adc_disable(); MCUSR = 0; WDTCSR = bit (WDCE) | bit (WDE); WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); sleep_disable(); } else { if (beepTimer < millis()) { beepTimer = millis() + beepTimerDuration; myAltitude = bmp.readAltitude() - altitudeNorm; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; } sUmEr = 0; for (i = 0; i < FILTER_SIZE; i++) { aSm = aSm + dA[i]; sUmEr = sUmEr + altitudes[i]; } mAA = aSm / FILTER_SIZE; sUmEr = sUmEr / FILTER_SIZE; if (sUmEr > sUmErMax) { sUmErMax = sUmEr; } currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: beepStatus = !beepStatus; if (beepStatus) { mode1BeepStatus = !mode1BeepStatus; } if (mode1BeepStatus) { mode1Beep2Status = !mode1Beep2Status; } if (mode1Beep2Status) { digitalWrite(PIN_LED, HIGH); if (RF_Beeping > millis()) { tone(PIN_RF, 540); } } else { digitalWrite(PIN_LED, LOW); noTone(PIN_RF); } if (myAltitude > cAltitude) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(2, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); EEPROMWriteInt(10, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } waiting2StageStart = millis() + DELAY_WAITING_2STAGE_START; } break; case 2: beepStatus = !beepStatus; if (beepStatus) { digitalWrite(PIN_LED, HIGH); } else { digitalWrite(PIN_LED, LOW); } tone(PIN_RF, myAltitude); if (myAltitude > cS2Altitude && !ssr_line_3_init) { ssr_line_3_init = true; delay_timer_line_3 = millis() + KEY_LINE_3_PROC_DURATION; digitalWrite(PIN_SSR_LINE_3, HIGH); } if (ssr_line_3_init && delay_timer_line_3 < millis() && !ssr_line_3_worked) { digitalWrite(PIN_SSR_LINE_3, LOW); ssr_line_3_worked = true; } if ((mAA < 0) && !rocketFlyBack && (sUmEr < sUmErMax) && (myAltitude > cAltitude) && (waiting2StageStart < millis())) { rocketFlyBack = true; EEPROMWriteInt(MAX_ALTITUDE_EEPROM, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(CHECK_APOGEY_EEPROM, timeToCheckAppogeyInMillis); EEPROMWriteInt(ALTITUDE_IND_EEPROM, measureCurrent); EEPROMWriteInt(MIDDLE_ALT_I_EEPROM, sUmEr); delay_timer_line_1 = millis() + DELAY_LINE_1; ssr_line_1_init = true; delay_timer_line_2 = millis() + DELAY_LINE_2; ssr_line_2_init = true; } if (ssr_line_1_init && !ssr_line_1_worked && delay_timer_line_1 < millis()) { ssr_line_1_worked = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; digitalWrite(PIN_SSR_LINE_1, HIGH); } if (ssr_line_2_init && !ssr_line_2_worked && delay_timer_line_2 < millis()) { ssr_line_2_worked = true; timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; digitalWrite(PIN_SSR_LINE_2, HIGH); } if ((timer_line_1 < millis()) && ssr_line_1_worked && !ssr_line_1_down) { digitalWrite(PIN_SSR_LINE_1, LOW); ssr_line_1_down = true; } if ((timer_line_2 < millis()) && ssr_line_2_worked && !ssr_line_2_down) { digitalWrite(PIN_SSR_LINE_2, LOW); ssr_line_2_down = true; } if (ssr_line_1_down && ssr_line_2_down) { turn3Mode = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart) / 10; EEPROMWriteInt(REC_DURATION_EEPROM, recordsTime); int speedOfRecordInSec = recordsTime / measureQuantity; speedOfRecordInSec = 100 / speedOfRecordInSec; EEPROMWriteInt(RECORDS_RATE_EEPROM, speedOfRecordInSec); } } if (turn3Mode && eepromWritingComplete) { rocketMode = 3; } break; case 3: playExitFlyModeAction(); sleepMode = true; break; } } } } void playExitFlyModeAction() { tone(PIN_RF, 940); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 840); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 740); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 640); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(PIN_RF); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } void proc0() { tone(PIN_RF, 450); delay(DURATION_0); noTone(PIN_RF); } void proc1() { tone(PIN_RF, 550); delay(DURATION_1); noTone(PIN_RF); } void checkSerial() { delay(3000); if (Serial.available()) { String myStr = Serial.readStringUntil('\n'); if (myStr.compareTo("clear") == 0) { digitalWrite(PIN_BEEP, HIGH); delay(2000); for (int i = 0 ; i < EEPROM.length() ; i++) { EEPROM.write(i, 0); } digitalWrite(PIN_BEEP, LOW); } Serial.println(); Serial.print("maxAltitude: "); Serial.print(EEPROMReadInt(MAX_ALTITUDE_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("Altitude Index Pyro Initiated: "); Serial.print(EEPROMReadInt(ALTITUDE_IND_EEPROM)); Serial.println(" "); Serial.println(); Serial.print("Middle Altitude Pyro Initiated: "); Serial.print(EEPROMReadInt(MIDDLE_ALT_I_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogey: "); Serial.print(EEPROMReadInt(CHECK_APOGEY_EEPROM)); Serial.println(" millis"); Serial.println(); Serial.print("recordsTimeInMillis/10: "); Serial.print(EEPROMReadInt(REC_DURATION_EEPROM)); Serial.println(" millis"); Serial.println(); Serial.print("recordsRate: "); Serial.print(EEPROMReadInt(RECORDS_RATE_EEPROM)); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = startEEPPROMWriting; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } ISR (WDT_vect) { wdt_disable(); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } }// IRP.1.4 FOR MRIA & 75 2S & 40 //#include <Adafruit_BMP280.h> #include <Adafruit_BMP085.h> #include <EEPROM.h> #include <avr/sleep.h> #include <avr/wdt.h> const byte PIN_RF = 11; const byte SPLITTER = 200; const int DURATION_0 = 550; const int DURATION_1 = 350; const byte PIN_SSR_LINE_1 = 8; // ключ для инициации первой мортиры (тормозной парашют) const byte PIN_SSR_LINE_2 = 10; // ключ для инициации второй мортиры (основной парашют) const byte PIN_SSR_LINE_3 = 7; // ключ для инициации мотора второй ступени const byte PIN_BEEP = 9; const byte PIN_LED = 3; const byte cAltitude = 5; //высота активации режима "полет" const byte cS2Altitude = 10; //высота активации ключа для запуска второй ступени const int measureQuantity = 480; // длина лога данных (ограничена емкостью ПЗУ) const byte startEEPPROMWriting = 20; unsigned long beepTimer = 0; unsigned long flyTimeStart = 0; unsigned long waiting2StageStart = 0; unsigned long delay_timer_line_1 = 0; unsigned long delay_timer_line_2 = 0; unsigned long delay_timer_line_3 = 0; unsigned long timer_line_1 = 0; unsigned long timer_line_2 = 0; unsigned long timer_line_3 = 0; boolean couldBeep = false; boolean beepStatus = false; boolean mode1BeepStatus = false; boolean mode1Beep2Status = false; boolean mode1Beep4Status = false; boolean mode1Beep8Status = false; boolean keyWorked = false; boolean recordsSecTimerFlg = false; boolean ssr_line_1_worked = false; boolean ssr_line_2_worked = false; boolean ssr_line_3_worked = false; boolean ssr_line_1_down = false; boolean ssr_line_2_down = false; boolean ssr_line_1_init = false; boolean ssr_line_2_init = false; boolean ssr_line_3_init = false; boolean sleepMode = false; boolean rocketFlyBack = false; boolean eepromWritingComplete = false; boolean turn3Mode = false; boolean line3Ready = false; int myAltitude; int sUmErMax; int altitudeNorm; int maxAltitude = 0; int measureCurrent = 0; int altitudes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int altitudesSorted[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte currentAltitudesInd = 0; const byte FILTER_SIZE = 10; byte rocketMode = 1; //Adafruit_BMP280 bmp; Adafruit_BMP085 bmp; #define adc_disable() (ADCSRA &= ~(1<<ADEN)) #define adc_enable() (ADCSRA |= (1<<ADEN)) #define KEY_LINE_1_PROC_DURATION 3000 #define KEY_LINE_2_PROC_DURATION 3000 #define KEY_LINE_3_PROC_DURATION 3000 //задержки мс инициации ключей после определения прохождения аппогея #define DELAY_LINE_1 0 #define DELAY_LINE_2 10000 #define DELAY_WAITING_2STAGE_START 5000 #define MAX_ALTITUDE_EEPROM 0 #define ALTITUDE_IND_EEPROM 2 #define CHECK_APOGEY_EEPROM 4 #define REC_DURATION_EEPROM 6 #define RECORDS_RATE_EEPROM 8 #define MIDDLE_ALT_I_EEPROM 10 void setup(void) { Serial.begin(9600); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(PIN_LED, OUTPUT); pinMode(PIN_SSR_LINE_1, OUTPUT); pinMode(PIN_SSR_LINE_2, OUTPUT); pinMode(PIN_SSR_LINE_3, OUTPUT); pinMode(PIN_BEEP, OUTPUT); pinMode(PIN_RF, OUTPUT); delay(50); if (!bmp.begin()) { digitalWrite(PIN_BEEP, HIGH); digitalWrite(PIN_RF, HIGH); digitalWrite(PIN_LED, HIGH); while (1); } delay(50); int ar1 = analogRead(A1); int ar2 = analogRead(A2); int ar3 = analogRead(A3); couldBeep = true; Serial.println(ar1); Serial.println(ar2); Serial.println(ar3); if (ar1 > 900) { digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(1000); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(1000); } if (ar2 > 900) { digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(1000); } if (ar3 > 900) { line3Ready = true; digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(100); digitalWrite(PIN_BEEP, HIGH); tone(PIN_RF, 540); digitalWrite(PIN_LED, HIGH); delay(100); digitalWrite(PIN_BEEP, LOW); noTone(PIN_RF); digitalWrite(PIN_LED, LOW); delay(1000); } checkSerial(); altitudeNorm = bmp.readAltitude(); } void loop() { int mAA; long aSm; int i; int j; int h; long sUmEr; beepStatus = !beepStatus; if (sleepMode) { proc1(); beeper(); myWatchdogEnable(0b000100); //0,25 s } else { myAltitude = bmp.readAltitude() - altitudeNorm; if (myAltitude > maxAltitude) { maxAltitude = myAltitude; } altitudes[currentAltitudesInd] = myAltitude; //sort altitudes array switch (currentAltitudesInd) { case 0: altitudesSorted[FILTER_SIZE - 1] = altitudes[0]; for (i = 0; i < FILTER_SIZE - 1; i++) { altitudesSorted[i] = altitudes[i + 1]; } break; case FILTER_SIZE: for (i = 0; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[i]; } break; default: j = 0; for (i = currentAltitudesInd + 1; i < FILTER_SIZE; i++) { altitudesSorted[j] = altitudes[i]; j++; } h = 0; for (i = j; i < FILTER_SIZE; i++) { altitudesSorted[i] = altitudes[h]; h++; } } for (i = 1; i < FILTER_SIZE; i++) { dA[i - 1] = altitudesSorted[i] - altitudesSorted[i - 1]; } sUmEr = 0; for (i = 0; i < FILTER_SIZE; i++) { aSm = aSm + dA[i]; sUmEr = sUmEr + altitudes[i]; } mAA = aSm / FILTER_SIZE; sUmEr = sUmEr / FILTER_SIZE; if (sUmEr > sUmErMax) { sUmErMax = sUmEr; } currentAltitudesInd++; if ( currentAltitudesInd > FILTER_SIZE - 1) { currentAltitudesInd = 0; } switch (rocketMode) { case 1: if (beepStatus) { digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 540); } else { digitalWrite(PIN_LED, LOW); tone(PIN_RF, 0); } if (myAltitude > cAltitude) { maxAltitude = 0; EEPROMWriteInt(0, 0); EEPROMWriteInt(2, 0); EEPROMWriteInt(4, 0); EEPROMWriteInt(6, 0); EEPROMWriteInt(8, 0); EEPROMWriteInt(10, 0); measureCurrent = FILTER_SIZE; flyTimeStart = millis(); rocketMode = 2; for (i = 0; i < FILTER_SIZE; i++) { EEPROMWriteInt(startEEPPROMWriting + i + i, altitudesSorted[i]); } waiting2StageStart = millis() + DELAY_WAITING_2STAGE_START; digitalWrite(PIN_LED, LOW); } break; case 2: tone(PIN_RF, myAltitude); if (myAltitude > cS2Altitude && !ssr_line_3_init && line3Ready) { ssr_line_3_init = true; delay_timer_line_3 = millis() + KEY_LINE_3_PROC_DURATION; digitalWrite(PIN_SSR_LINE_3, HIGH); } if (ssr_line_3_init && delay_timer_line_3 < millis() && !ssr_line_3_worked) { digitalWrite(PIN_SSR_LINE_3, LOW); ssr_line_3_worked = true; } if ((mAA < 0) && !rocketFlyBack && (sUmEr < sUmErMax) && (myAltitude > cAltitude) && (waiting2StageStart < millis())) { rocketFlyBack = true; EEPROMWriteInt(MAX_ALTITUDE_EEPROM, maxAltitude); int timeToCheckAppogeyInMillis = millis() - flyTimeStart; EEPROMWriteInt(CHECK_APOGEY_EEPROM, timeToCheckAppogeyInMillis); EEPROMWriteInt(ALTITUDE_IND_EEPROM, measureCurrent); EEPROMWriteInt(MIDDLE_ALT_I_EEPROM, sUmEr); delay_timer_line_1 = millis() + DELAY_LINE_1; ssr_line_1_init = true; delay_timer_line_2 = millis() + DELAY_LINE_2; ssr_line_2_init = true; } if (ssr_line_1_init && !ssr_line_1_worked && delay_timer_line_1 < millis()) { ssr_line_1_worked = true; timer_line_1 = millis() + KEY_LINE_1_PROC_DURATION; digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 1000); beeper(); digitalWrite(PIN_SSR_LINE_1, HIGH); } if (ssr_line_2_init && !ssr_line_2_worked && delay_timer_line_2 < millis()) { ssr_line_2_worked = true; timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; digitalWrite(PIN_SSR_LINE_2, HIGH); } if (ssr_line_2_init && !ssr_line_2_worked && delay_timer_line_2 > millis() && ssr_line_1_down && myAltitude < 200) { ssr_line_2_worked = true; timer_line_2 = millis() + KEY_LINE_2_PROC_DURATION; digitalWrite(PIN_SSR_LINE_2, HIGH); } if ((timer_line_1 < millis()) && ssr_line_1_worked && !ssr_line_1_down) { digitalWrite(PIN_SSR_LINE_1, LOW); ssr_line_1_down = true; } if ((timer_line_2 < millis()) && ssr_line_2_worked && !ssr_line_2_down) { digitalWrite(PIN_SSR_LINE_2, LOW); ssr_line_2_down = true; } if (ssr_line_1_down && ssr_line_2_down) { turn3Mode = true; } if (!eepromWritingComplete) { EEPROMWriteInt(startEEPPROMWriting + measureCurrent + measureCurrent, myAltitude); measureCurrent++; if (measureCurrent > measureQuantity) { eepromWritingComplete = true; int recordsTime = (millis() - flyTimeStart) / 1000; EEPROMWriteInt(REC_DURATION_EEPROM, recordsTime); int speedOfRecordInSec = measureQuantity*10 / recordsTime; EEPROMWriteInt(RECORDS_RATE_EEPROM, speedOfRecordInSec); } } if (turn3Mode && eepromWritingComplete) { rocketMode = 3; } break; case 3: //playExitFlyModeAction(); sleepMode = true; break; } delay(200); } } void myWatchdogEnable(const byte interval) { // sleep bit patterns: // 1 second: 0b000110 // 2 seconds: 0b000111 // 4 seconds: 0b100000 // 8 seconds: 0b100001 //0,25 seconds: 0b000100 adc_disable(); // clear various "reset" flags MCUSR = 0; // allow changes, disable reset WDTCSR = bit (WDCE) | bit (WDE); // set interrupt mode and an interval WDTCSR = 0b01000000 | interval;// set WDIE, and delay wdt_reset(); // pat the dog set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); // turn off brown-out enable in software MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); sleep_cpu (); // cancel sleep as a precaution sleep_disable(); } ISR (WDT_vect) { wdt_disable(); // disable watchdog } void playExitFlyModeAction() { tone(PIN_RF, 940); digitalWrite(PIN_LED, HIGH); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 840); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 740); delay(500); digitalWrite(PIN_LED, LOW); tone(PIN_RF, 640); delay(500); digitalWrite(PIN_LED, HIGH); tone(PIN_RF, 540); delay(1000); digitalWrite(PIN_LED, LOW); noTone(PIN_RF); delay(2000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); sendAltitude(); delay(5000); } void proc0() { tone(PIN_RF, 450); delay(DURATION_0); noTone(PIN_RF); } void proc1() { tone(PIN_RF, 550); delay(DURATION_1); noTone(PIN_RF); } void checkSerial() { delay(3000); if (Serial.available()) { String myStr = Serial.readStringUntil('\n'); if (myStr.compareTo("clear") == 0) { digitalWrite(PIN_BEEP, HIGH); delay(2000); for (int i = 0 ; i < EEPROM.length() ; i++) { EEPROM.write(i, 0); } digitalWrite(PIN_BEEP, LOW); } Serial.println(); Serial.print("maxAltitude: "); Serial.print(EEPROMReadInt(MAX_ALTITUDE_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("Altitude Index Pyro Initiated: "); Serial.print(EEPROMReadInt(ALTITUDE_IND_EEPROM)); Serial.println(" "); Serial.println(); Serial.print("Middle Altitude Pyro Initiated: "); Serial.print(EEPROMReadInt(MIDDLE_ALT_I_EEPROM)); Serial.println(" m"); Serial.println(); Serial.print("timeToCheckAppogey: "); Serial.print(EEPROMReadInt(CHECK_APOGEY_EEPROM)); Serial.println(" millis"); Serial.println(); Serial.print("recordsTime: "); Serial.print(EEPROMReadInt(REC_DURATION_EEPROM)); Serial.println(" sec"); Serial.println(); Serial.print("recordsRate: "); int val = EEPROMReadInt(RECORDS_RATE_EEPROM); float valf = val / 10.0; Serial.print( valf); Serial.println(" records/sec"); Serial.println(); Serial.println("log: "); float j = 0; for (int i = startEEPPROMWriting; i < (measureQuantity + measureQuantity + 1); i += 2) { Serial.print(EEPROMReadInt(i)); Serial.println(); delay(50); } } } void EEPROMWriteInt (int p_address, int p_value) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); int val = ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); if (val != p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } } int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } void sendAltitude() { String beaconData = String(maxAltitude); String oneStr = ""; delay(1000); int d2RF; for (int i = 0; i < beaconData.length(); i++ ) { d2RF = 0; oneStr += beaconData.charAt(i); d2RF = oneStr.toInt(); send_d2RF(d2RF); delay(1000); oneStr = ""; } } void send_d2RF(int d2RF) { switch (d2RF) { case 0: proc0(); break; case 1: proc1(); break; case 2: proc1(); delay(SPLITTER); proc0(); break; case 3: proc1(); delay(SPLITTER); proc1(); break; case 4: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 5: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; case 6: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc0(); break; case 7: proc1(); delay(SPLITTER); proc1(); delay(SPLITTER); proc1(); break; case 8: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); break; case 9: proc1(); delay(SPLITTER); proc0(); delay(SPLITTER); proc0(); delay(SPLITTER); proc1(); break; } } void beeper() { digitalWrite(PIN_BEEP, HIGH); delay(200); digitalWrite(PIN_BEEP, LOW); }