Объединение двух кодов двух датчиков в одной программе

Я использую два датчика: датчик кожно-гальванической реакции и датчик сердечного ритма. Проблема в том, что когда я объединил оба кода, единственный вывод, который отображается, — это только частота пульса, которая находится на уровне A0. Если я запускаю их отдельно, оба кода работают отлично. У меня базовый опыт программирования, оба кода взяты из Интернета.

Вот коды:

    #define BLYNK_PRINT Serial
    #include <ESP8266_Lib.h>
    #include <BlynkSimpleShieldEsp8266.h>
    #include <SoftwareSerial.h>
    SoftwareSerial EspSerial(2, 3); // RX, TX

    #define samp_siz 4
    #define rise_threshold 4

    // Your ESP8266 baud rate:
    #define ESP8266_BAUD 9600

    char auth[] = "ba4e5bd1bd9549669a02ac378db9faf6";
    char ssid[] = "vivo";
    char pass[] = "takoyaki";


    /*char auth[] = "b3f01a592b78471f9f720b09d2ff8047";
    char ssid[] = "vivo";
    char pass[] = "takoyaki";
    */
    ESP8266 wifi(&EspSerial);

    BLYNK_CONNECTED()
    {
      Blynk.syncAll();
    }

    BlynkTimer timer;

    // Pulse Monitor Test Script

    void setup() {
        Serial.begin(9600);

      // Set ESP8266 baud rate
      EspSerial.begin(ESP8266_BAUD);
      delay(10);

      Blynk.begin(auth, wifi, ssid, pass);

      pinMode(A0, INPUT);
      pinMode(A1, INPUT);

      //timer.setInterval(1000L, myTimerEvent);     //send the arduino's                         uptime
      timer.setInterval(350L, sensor);            //send gsr data every         0.35s
    }

    /*void myTimerEvent()
    {
      // You can send any value at any time.
      // Please don't send more that 10 values per second.
      Blynk.virtualWrite(V4, millis() / 1000);
    }
    */
    void sensor(){

      const int GSR=A1;
      int inputvalue=0;
      int gsr_average=0;
      long total=0;
      for(int j=0;j<10;j++)                       //Average the 10                 measurements to remove the glitch
          {
          inputvalue=analogRead(GSR);
          total += inputvalue;
          delay(5);
          }
       gsr_average = total/10;
       Serial.println(gsr_average);
       Blynk.virtualWrite(V6, gsr_average);
    }

    void heartrate ()
    {
        int sensorPin =A0;
        float reads[samp_siz], sum;
        long int now, ptr;
        float last, reader, start;
        float first, second, third, before, print_value;
        bool rising;
        int rise_count;
        int heartrate;
        int n;
        long int last_beat;

        for (int i = 0; i < samp_siz; i++)
          reads[i] = 0;
        sum = 0;
        ptr = 0;

        while(1)
        {
          // calculate an average of the sensor
          // during a 20 ms period (this will eliminate
          // the 50 Hz noise caused by electric light
          n = 0;
          start = millis();
          reader = 0.;
          do
                  {
            reader += analogRead (sensorPin);
            n++;
            now = millis();
          }
          while (now < start + 20);  
          reader /= n;  // we got an average

          // Add the newest measurement to an array
          // and subtract the oldest measurement from the array
          // to maintain a sum of last measurements
          sum -= reads[ptr];
          sum += reader;
          reads[ptr] = reader;
          last = sum / samp_siz;
          // now last holds the average of the values in the array

          // check for a rising curve (= a heart beat)
          if (last > before)
          {
            rise_count++;
            if (!rising && rise_count > rise_threshold)
            {
              // Ok, we have detected a rising curve, which implies a         heartbeat.
              // Record the time since last beat, keep track of the two previous
      // times (first, second, third) to get a weighed average.
      // The rising flag prevents us from detecting the same rise more than once.
              rising = true;
              first = millis() - last_beat;
              last_beat = millis();

              // Calculate the weighed average of heartbeat rate
              // according to the three last beats
              print_value = 60000. / (0.4 * first + 0.3 * second + 0.3 *         third);

              heartrate = print_value;

              //Serial.print(print_value);
              Serial.print(heartrate);
              Serial.print('\n');
              Blynk.virtualWrite(V7, heartrate);

              third = second;
              second = first;

            }
          }
          else
          {
            // Ok, the curve is falling
            rising = false;
            rise_count = 0;
          }
          before = last;


          ptr++;
          ptr %= samp_siz;

        }
    }

    void loop()
    {
      Blynk.run();
      //timer.run();
      sensor();
      heartrate();
    }

, 👍0

Обсуждение

Если вам нужны коды без команды blynk, просто сообщите мне в разделе комментариев., @tako

функция heartrate() имеет бесконечный цикл, поэтому Uno застревает там, @chrisl

поэтому я не могу использовать код как функцию? как мне нужно его отредактировать?, @tako

Проблема заключается в цикле while(1). Перепишите функцию так, чтобы она считывала данные, что-то с ними делала, а затем выходила в основной цикл, чтобы сделать что-то еще., @chrisl

Поскольку код записывает последние измерения, вам придется сделать эти переменные статическими или глобальными, чтобы они сохраняли свое значение между различными выполнениями функции. И кстати: переменная start должна быть unsigned long, поскольку именно этот тип возвращает функция millis(). То же самое касается переменной «сейчас»., @chrisl

Большое вам спасибо за вашу помощь. Я действительно ценю это, сэр. Я скоро внесу правки, и если у меня возникнут вопросы, я буду здесь снова., @tako

Можете ли вы объяснить немного больше об этом цикле while(1)? я так потерян, @tako

while(1){ ... } — это бесконечный цикл, он никогда не завершается, поэтому heartrate() никогда не может завершиться и вернуться в цикл. Он просто сидит там и снимает показания — навсегда. Попробуйте вызвать только один из датчиков(), пока он не заработает. Затем попробуйте вызвать только другой, пока _он_ тоже не заработает. Как только каждый из них заработает правильно, только тогда попробуйте позвонить им обоим. Это классический метод отладки по принципу «разделяй и властвуй»., @JRobert

Я выполнил советы, подобные тем, что вы предлагали, и вызывал эти датчики один за другим, и все работает отлично. Какая структура управления мне больше всего подходит для замены while(1)?, @tako


1 ответ


Лучший ответ:

0

Я не тестировал следующий код, поэтому вам придется сделать это и обработать небольшие ошибки. Речь идет скорее о грубом способе изменения программы . И вам придется понимать, что на самом деле делает код, чтобы иметь возможность изменить его так, как вам нужно.

Сначала вам придется преобразовать некоторые переменные в функции heartrate() в глобальные переменные (записав их в верхней части эскиза вне любой функции), чтобы они сохраняли свое значение. значения между различными выполнениями функции. Я также изменил некоторые типы переменных, которые соответствуют типам присвоенных значений.

float reads[samp_siz], sum;
unsigned long now, start, ptr;
float last, before, reader;
unsigned long first, second, third;
bool rising;
int rise_count;
float print_value, heartrate;
unsigned long last_beat;

Вывод датчика должен быть #defined в верхней части программы (по соглашению). Тогда вам следует поместить этот код:

for (int i = 0; i < samp_siz; i++)
    reads[i] = 0;
sum = 0;
ptr = 0;

в функцию setup().

Теперь мы можем взглянуть на цикл while(1). В Arduino значение 0 рассматривается как логическое значение false, а все остальные значения — как true. Это то же самое, что писать while(true). Структура while() выполняется до тех пор, пока выражение внутри скобок принимает значение true. Поскольку здесь это всегда так, это будет повторяться вечно. На этом этапе вы можете просто стереть эту строку (и соответствующую закрывающую скобку ).

После этих изменений функция выполнит только одно чтение (в среднем более 20 мс), затем проверит, было ли обнаружено тактовое сообщение, и, наконец, выполнит выход из функции loop(). Поскольку не каждое чтение является тактовым сигналом, вы получите больше выходных данных от функции sensor() (которая выводит данные при каждом выполнении), чем от функции heartbeat(). И теперь, поскольку ваши функции неблокируются, вы получите очень быстрый результат. Возможно, вы захотите замедлить этот процесс, используя функцию delay() или (лучше) функцию millis() (как в примере с BlinkWithoutDelay). из Arduino IDE).

Обратите внимание, что этот код демонстрирует некоторые плохие стили написания. В сети можно найти как много хорошего кода, так и много плохого кода. Я вижу неправильные типы переменных, использование совершенно ненужных переменных и использование функции millis(), которая не обрабатывает ролловер. Это не значит, что код не работает. Но с их помощью можно получить странные и трудные для отладки ошибки.

,