Помогите объединить два скетча
- Войдите на сайт для отправки комментариев
Сб, 22/02/2020 - 15:00
Есть два скетча под ардуино. Один специализируется на вычислении частоты, глубины дыхания, а второй нужен для вычисления пульса с выхода AD8232. Прекрасно работают по отдельности, но вместе - нет. Пульс явно неверный. Дело в том, что они написаны по одному, немного измененному шаблону, и имеют одинаковые функции, я решил вывести повторяющуюся функцию в отдельную библиотеку, но все равно скетч работает некорректно.
#include <SPI.h> // Подключаем библиотеку SPI #include <SD.h> // Подключаем библиотеку SD int pulse; const int auf = 10; //после скольких записей подтверждается запись // медианный фильтр int medFilt(int value) { const int bufSize = 70; // количество элементов // должно быть нечётным static int buf[bufSize]; // массив нескольких // последних элементов static int sortBuf[bufSize]; // массив элементов // который сортируется static int pos = 0; // текущая позиция в массиве buf[pos] = value; // запись нового значения в массив // вычисление позиции следующего элемента pos++; if (pos == bufSize) pos = 0; // копирование первого массива во второй for (int i = 0; i < bufSize; i++) { sortBuf[i] = buf[i]; } // сортировка второго массива for (int i = 0; i < bufSize; i++) { for (int j = i; j < bufSize; j++) { if (sortBuf[i] < sortBuf[j]) { int k = sortBuf[i]; sortBuf[i] = sortBuf[j]; sortBuf[j] = k; } } } // возвращается средний элемент // из отсортированного массива return sortBuf[(bufSize / 2)]; } File my; const int chipSelect = 4;// Указываем к какому выводу подключен CS unsigned long seed;//случайное имя String str;//.txt boolean pz; //состояние переключателя void setup() { pinMode (5, INPUT_PULLUP); pinMode (3, INPUT_PULLUP); pinMode (A6, INPUT); pinMode (13,OUTPUT); pinMode (A2, INPUT); Serial.begin(9600); // Открытие последовательную связь Serial.print("Initializing SD card..."); if (!SD.begin(4)) { Serial.println("Card failed, or not present"); } seed = 1; seed *= 4; seed += analogRead(A1) & 3; randomSeed(seed); str = String (random (100000)); static String xp = ".txt"; static String asfd = str + xp; Serial.println("card initialized."); Serial.println("initialization done."); // Печатаем текст, если инициализация прошла успешно my = SD.open(asfd, FILE_WRITE); delay (1); pz = !digitalRead (A2); } // пересечения порогового уровня сверху вниз int buf1 [15]; float buf1f [15]; int pos = 0; //позиция буфера unsigned long prevTime, time; int ti = 0; // текущее значение int tm = 0; // прошлое значение float f = 0.0000; //фильтрованное значение byte kol; // кол-во записей int q = 0; int d = 0; int por = 0; //нейтральный порог int por1 = 0; //порог вдоха int por2 = 0;//порог выдоха boolean per2; //пересечение низа (выдох) boolean per1, podt;// пересечение верха (вдох), подтверждение о записи boolean ed = 0; //еденичная запись void loop() { ti = analogRead (A6); f = (ti * 0.75) + (tm * 0.25); por = medFilt (f); // вычисление нейтрального порога por1 = por + 3; // вычисления остальных прогов - вдоха и выдоха por2 = por - 3; q++; if (q > 70) { q = 0; } if (f > por1 && per1 == 0) { per1 = 1; } if (per1 == 1 && f < por) { // если было пересечение вверх а текущее ниже нижнего порога то происходят вычисления а факт пересечения стирается digitalWrite (13,1); per1 = 0; prevTime = time; // текущее время обновляется time = millis(); // вычисляется мгновенное значение пульса // (60 секунд) * 1000 / (период в миллисекундах) int period = time - prevTime; pulse = 60000 / period; // компенсация погрешности целочисленного деления if ((60000 % period) >= (60000 / 2)) pulse++; buf1f [pos] = (float) millis () / 1000.000; buf1 [pos] = pulse; kol++; pos++; Serial.println (pulse) // Serial.println (pos); ; if (pos > 14) { for (int xt = 0; xt < 15; xt++) { my.print (buf1f [xt]); my.print (" "); my.println (buf1 [xt]); } pos = 0; my.flush(); } //Serial.print (kol); // Serial.println ("вдох"); digitalWrite (13,0); } Serial.print (f); Serial.print (" "); Serial.print (por); Serial.print (" "); Serial.print (por1); Serial.print (" "); Serial.println (por2); ti = tm;z delay (50); }Скетч датчика дыхания.
#include <LiquidCrystal.h> // используемые пины const int ledPin=6; // анод инфракрасного светодиода const int sensorPin=A0; // выход датчика const int beepPin=7; // анод бипера со встроенным генератором // размер буфера для вычисления порога const int bufSize=16; // буфер для вычисления порога int buf[bufSize]; // текущая позиция в буфере int bufPos=0; // сумма значений в буфере long int bufSum=0; // порог, вычисляемый, как среднее арифметическое // значений в буфере int threshold=0; // расстояние до верхнего и нижнего порогов // больше значение - меньше ложных срабатываний // и меньше чувствительности const int hyst=45; // пропуск некоторого количества замеров // после пересечения порога int skipDetect=0; // количество замеров, // которые необходимо пропустить const int crossSkip=7; // пишется в skipDetect // после каждого пересечения порога // напряжение на датчике при включенном светодиоде int sensorValueLedOn; // при выключенном светодиоде // фоновая засветка int sensorValueLedOff; // значение на датчике с компенсацией фонового освещения // по формуле sensorValueLedOff - sensorValueLedOn int sensorValue; // начало и конец текущего периода // время записывается при детектировании // пересечения порогового уровня сверху вниз unsigned long prevTime, timer; // находилось ли значение предыдущего отсчёта выше порога boolean above; // мгновенное значение пульса // количество ударов в минуту int pulse; // медианное значение пульса int pulseMed; // среднее значение пульса int pulseAvg; // медианный фильтр int medFilt(int value){ const int bufSize=7; // количество элементов // должно быть нечётным static int buf[bufSize]={93,93,93,93,93,93,93}; // массив нескольких // последних элементов static int sortBuf[bufSize]; // массив элементов // который сортируется static int pos=0; // текущая позиция в массиве buf[pos]=value; // запись нового значения в массив // вычисление позиции следующего элемента pos++; if (pos==bufSize) pos=0; // копирование первого массива во второй for(int i=0; i<bufSize; i++){ sortBuf[i]=buf[i]; } // сортировка второго массива for(int i=0; i<bufSize; i++){ for(int j=i; j<bufSize; j++){ if(sortBuf[i]<sortBuf[j]){ int k=sortBuf[i]; sortBuf[i]=sortBuf[j]; sortBuf[j]=k; } } } // возвращается средний элемент // из отсортированного массива return sortBuf[(bufSize/2)]; } // вычисление среднего значения int avg(int value){ const int bufSize=16; // количество значений static int buf[bufSize]; // массив из последних значений static int pos; // текущая позиция static long int sum=0; // сумма всех значений int avg; // среднее значение buf[pos] = value; // добавление нового значения sum += value; // его добавление в сумму avg = sum/bufSize; // вычисление среднего значения // компенсация погрешности целочисленного деления if ((sum%bufSize)>=(bufSize/2)) avg++; // вычисление позиции следующего элемента pos++; if (pos==bufSize) pos=0; sum -= buf[pos]; // элемент, который будет перезаписан // в следующий раз заранее вычитается // из суммы return avg; } // символьный дисплей HD44780 16x2 // RS, EN, D4, D5, D6, D7 LiquidCrystal lcd(10, 8, 5, 4, 3, 2); void setup() { pinMode(ledPin, OUTPUT); pinMode(beepPin, OUTPUT); digitalWrite(beepPin, LOW); Serial.begin(9600); lcd.begin(16, 2); } void loop() { digitalWrite(ledPin, HIGH); // светодиод включается delay(10); // задержка, чтобы фототранзистор успел среагировать // замеряется напряжение с датчика со включенным светодиодом sensorValueLedOn = analogRead(sensorPin); digitalWrite(ledPin, LOW); // светодиод выключается delay(10); // замер с выключенным светодиодом sensorValueLedOff = analogRead(sensorPin); // компенсация фоновой засветки sensorValue =sensorValueLedOn; buf[bufPos] = sensorValue; // запись нового значения в буфер bufSum += sensorValue; // прибавление его к сумме // вычисление порога // (среднее арифметическое всех значений в буфере) threshold = bufSum/bufSize+1; // вычисление позиции следующего элемента bufPos++; if (bufPos==bufSize) bufPos=0; // элемент, который будет перезаписан в следующий раз, // вычитается из суммы заранее bufSum -= buf[bufPos]; // если не нужно пропускать замеры if (skipDetect==0){ // детектирование того, что значение находится выше // верхнего порога if (sensorValue<(threshold+hyst-10)){ // при пересечении порога детективрование отключается // на несколько замеров if (!above) skipDetect=crossSkip; // показания с датчика теперь выше порога above=true; } // детективрование того, что значение находится ниже // нижнего порога else if (sensorValue>(threshold+hyst)){ // при пересечении порога сверху вниз происходят вычисления if (above){ // текущее время становится предыдущим prevTime = timer; // текущее время обновляется timer = millis(); // вычисляется мгновенное значение пульса // (60 секунд) * 1000 / (период в миллисекундах) int period = timer-prevTime; pulse = 60000/period; // компенсация погрешности целочисленного деления if ((60000%period)>=(60000/2)) pulse++; // если значение пульса реалистично, то оно выводится if ((pulse>=40)&&(pulse<=200)){ // би digitalWrite(beepPin, HIGH); // вывод данных lcd.clear(); lcd.print("Inst:"); lcd.print(pulse); lcd.setCursor(9,0); lcd.print("Med:"); pulseMed = medFilt(pulse); lcd.print(pulseMed); lcd.setCursor(4,1); lcd.print("Avg: "); pulseAvg = avg(pulseMed); lcd.print(pulseAvg); //Serial.print("Inst: "); // Serial.print(pulse); // Serial.print("; Med: "); Serial.println(pulseMed); // Serial.print("; Avg: "); // Serial.println(pulseAvg); // п digitalWrite(beepPin, LOW); // последнее значение с датчика ниже порога // above = false; на самом деле должно быть не тут } // при пересечении порога детективрование отключается // на несколько замеров skipDetect=crossSkip; } // а здесь above = false; } }else{ skipDetect--; // один замер пропущен, // поэтому ещё надо пропустить // на один меньше :-) } }Скетч AD8232, который, по сути и является шаблонным. Изменены только настройки.
Конечно можно сделать проэкт "двухядерным" (с двумя ардуинками). Но, мне кажется, тут можно обойтись и без 2 ядер.
Ничего, что в этих скетчах используются одни и те же пины (3 и 5) для разных целей? Интересно, как Вы их подключали для объединённого скетча?
3 и 5 объявлены, но не используются (код LCD дисплея закомментировал при объединении)
код LCD дисплея закомментировал при объединении
Закомментирован? Т.е. реально у Вас проблемы не с тем кодом, что Вы здесь показали, а с каким-то другим? Значит, я потратил полчаса на изучение не того кода с которым у Вас проблема, а совершенно другого?
Простите, но я расцениваю это как издевательство над собой с Вашей стороны. Поставьте себя на моё место.
До свиданья, удачи Вам с кодом!