Подключение двух датчиков к arduino

Тема в разделе "Arduino & Shields", создана пользователем Aforizm, 8 июн 2020.

Метки:
  1. Aforizm

    Aforizm Нуб

    Здравствуйте, есть плата Arduino uno , датчик пульса Pulse sensor, датчик ЭКГ Ad8232 и дисплей 1602.

    Есть программа, которая принимает данные с СОМ порта. С помощью скетча можно вывести частоту пульса на дисплей и в программу, датчик пульса подключен к А0.
    Датчик экг подключен к А1, но я не знаю как его обработать, чтобы работали 2 датчика по типу снимаю измерения с датчика пульса и вывожу на дисплей и в программу, экг пока что не работает, потом снимаю экг и вывожу на дисплей и экран, пульс не работает. Экг хочу выводить словами хорошо, плохо, в норме, т.к. символьный дисплей, а в программе будет выводиться график. Примеров никаких не нашёл, может кто, что знает и подскажет?
     
  2. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Афоризм - это подразумевает - кратко и исчерпывающе. А по вашему тексту - больше непоняток чем текста. Что за прога на компе, что за скетч на Ардуине, что вы хотите-то ? Вам нужно скетч переделать или прогу на компе. или то и другое ? Перво-наперво прога на компе должна различать данные от датчиков. То есть должна быть опознавательная метка (преамбула) блока данных.
     
  3. Aforizm

    Aforizm Нуб

    Программа принимает данные с порта. Нужно чтобы два датчика работали по одному скетчу. С этим скетчем работает датчик пульса и дисплей, нужно сюда еще датчик экг.
    Код (C++):
    #include <LiquidCrystal.h>

    int pulsePin = 0;              
    int blinkPin = 13;                
    int fadePin = 8;                  
    int fadeRate = 0;                
    LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
    // Volatile Variables, used in the interrupt service routine!
    volatile int BPM;                   // int that holds raw Analog in 0. updated every 2mS
    volatile int Signal;                // holds the incoming raw data
    volatile int IBI = 600;             // int that holds the time interval between beats! Must be seeded!
    volatile boolean Pulse = false;     // "True" when User's live heartbeat is detected. "False" when not a "live beat".
    volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

    // Regards Serial OutPut  -- Set This Up to your needs
    static boolean serialVisual = true;   // Set to 'false' by Default.  Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse

    volatile int rate[10];                      // array to hold last ten IBI values
    volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
    volatile unsigned long lastBeatTime = 0;           // used to find IBI
    volatile int P = 512;                      // used to find peak in pulse wave, seeded
    volatile int T = 512;                     // used to find trough in pulse wave, seeded
    volatile int thresh = 525;                // used to find instant moment of heart beat, seeded
    volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
    volatile boolean firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
    volatile boolean secondBeat = false;      // used to seed rate array so we startup with reasonable BPM

    void setup()
    {
      pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!
      pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!
      Serial.begin(9600);             // we agree to talk fast!
      interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS
     
    }


    //  Where the Magic Happens
    void loop()
    {
       serialOutput();
     
      if (QS == true) // A Heartbeat Was Found
        {    
          // BPM and IBI have been Determined
          // Quantified Self "QS" true when arduino finds a heartbeat
          fadeRate = 255; // Makes the LED Fade Effect Happen, Set 'fadeRate' Variable to 255 to fade LED with pulse
          serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial.    
          QS = false; // reset the Quantified Self flag for next time  
        }
       
      ledFadeToBeat(); // Makes the LED Fade Effect Happen
      delay(20); //  take a break
    }

    void ledFadeToBeat()
    {
       fadeRate -= 15;                         //  set LED fade value
       fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!
       analogWrite(fadePin,fadeRate);          //  fade LED
    }

    void interruptSetup()
    {    
      // Initializes Timer2 to throw an interrupt every 2mS.
      TCCR2A = 0x02;     // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
      TCCR2B = 0x06;     // DON'T FORCE COMPARE, 256 PRESCALER
      OCR2A = 0X7C;      // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
      TIMSK2 = 0x02;     // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
      sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED    
    }

    void serialOutput()
    {   // Decide How To Output Serial.
    if (serialVisual == true)
      {
         arduinoSerialMonitorVisual('-', Signal);   // goes to function that makes Serial Monitor Visualizer
      }
    else
      {
          sendDataToSerial('S', Signal);     // goes to sendDataToSerial function
       }      
    }

    void serialOutputWhenBeatHappens()
    {  
    if (serialVisual == true) //  Code to Make the Serial Monitor Visualizer Work
       {          
         Serial.println(BPM);
         lcd.clear();
         lcd.print("BPM: ");
         lcd.print(BPM);
       }
    else
       {
         sendDataToSerial('B',BPM);   // send heart rate with a 'B' prefix
         sendDataToSerial('Q',IBI);   // send time between beats with a 'Q' prefix
       }  
    }

    void arduinoSerialMonitorVisual(char symbol, int data )
    {  
      const int sensorMin = 0;      // sensor minimum, discovered through experiment
      const int sensorMax = 1024;    // sensor maximum, discovered through experiment
      int sensorReading = data; // map the sensor range to a range of 12 options:
      int range = map(sensorReading, sensorMin, sensorMax, 0, 11);
    }


    void sendDataToSerial(char symbol, int data )
    {
       Serial.print(symbol);
       Serial.println(data);              
    }

    ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts to 124
    {
      cli();                                      // disable interrupts while we do this
      Signal = analogRead(pulsePin);              // read the Pulse Sensor
      sampleCounter += 2;                         // keep track of the time in mS with this variable
      int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise
                                                  //  find the peak and trough of the pulse wave
      if(Signal < thresh && N > (IBI/5)*3) // avoid dichrotic noise by waiting 3/5 of last IBI
        {    
          if (Signal < T) // T is the trough
          {                      
            T = Signal; // keep track of lowest point in pulse wave
          }
        }

      if(Signal > thresh && Signal > P)
        {          // thresh condition helps avoid noise
          P = Signal;                             // P is the peak
        }                                        // keep track of highest point in pulse wave

      //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
      // signal surges up in value every time there is a pulse
      if (N > 250)
      {                                   // avoid high frequency noise
        if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )
          {      
            Pulse = true;                               // set the Pulse flag when we think there is a pulse
            digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
            IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
            lastBeatTime = sampleCounter;               // keep track of time for next pulse
     
            if(secondBeat)
            {                        // if this is the second beat, if secondBeat == TRUE
              secondBeat = false;                  // clear secondBeat flag
              for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup
              {            
                rate[i] = IBI;                    
              }
            }
     
            if(firstBeat) // if it's the first time we found a beat, if firstBeat == TRUE
            {                        
              firstBeat = false;                   // clear firstBeat flag
              secondBeat = true;                   // set the second beat flag
              sei();                               // enable interrupts again
              return;                              // IBI value is unreliable so discard it
            }  
          // keep a running total of the last 10 IBI values
          word runningTotal = 0;                  // clear the runningTotal variable  

          for(int i=0; i<=8; i++)
            {                // shift data in the rate array
              rate[i] = rate[i+1];                  // and drop the oldest IBI value
              runningTotal += rate[i];              // add up the 9 oldest IBI values
            }

          rate[9] = IBI;                          // add the latest IBI to the rate array
          runningTotal += rate[9];                // add the latest IBI to runningTotal
          runningTotal /= 10;                     // average the last 10 IBI values
          BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
          QS = true;                              // set Quantified Self flag
          // QS FLAG IS NOT CLEARED INSIDE THIS ISR
        }                      
      }

      if (Signal < thresh && Pulse == true)
        {   // when the values are going down, the beat is over
          digitalWrite(blinkPin,LOW);            // turn off pin 13 LED
          Pulse = false;                         // reset the Pulse flag so we can do it again
          amp = P - T;                           // get amplitude of the pulse wave
          thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
          P = thresh;                            // reset these for next time
          T = thresh;
        }

      if (N > 2500)
        {                           // if 2.5 seconds go by without a beat
          thresh = 512;                          // set thresh default
          P = 512;                               // set P default
          T = 512;                               // set T default
          lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date      
          firstBeat = true;                      // set these to avoid noise
          secondBeat = false;                    // when we get the heartbeat back
        }

      sei();                                   // enable interrupts when youre done!
    }// end isr
     
  4. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Слава богу. Уже ближе. Ну хорошо, а как вы хотите на НЕграфический LCD вывести кардиограмму ? У вас есть пример скетча работающего с ЭКГ датчиком ?
     
  5. Aforizm

    Aforizm Нуб

    Написал же выше. Экг хочу выводить словами хорошо, плохо, в норме, т.к. символьный дисплей, а в программе будет выводиться график. Примеров никаких не нашёл.
    Можно на английском выводить.
     
  6. akl

    akl Гуру

    я так понял, самообучающийся ИИ на базе ардуино уно будет анализировать кардиограмму и выводить на дисплей непосредственно диагноз "хорошо-плохо"
    мне более непонятно что там за программа на компе. Ведь ее придется сильно переделать чтобы она одновременно и пульс считала и график строила.
     
  7. Aforizm

    Aforizm Нуб

    Первая часть да, именно это и хочется сделать.
    Программа принимает данные с COM порта и выводит их в виде чисел в текстовое поле, дальше я переключаю на плоттер в программе и там строится график. Программу переделывать не нужно. Не могу её сюда загрузить , так бы показал.
     
  8. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Ах - да, чето проглядел. Пардон. У нас сегодня жарко...
    1. То есть Ардуино на основе массива данных сама делает вывод "хорошо/плохо", плюс еще переправляет на комп этот массив и "свои выводы" (а комп, проанализировав всё это - может еще и не согласиться !? ))))))) Так как, что такое хорошо или плохо - вопрос открытый.
    2. Если ИИ Ардуины будет способен на основе данных кардиографа сделать выводы о качестве ритма, то он запросто может вычислить и частоту пульса. Зачем тогда датчик пульса ? Делов-то - измерить временной разнос между двумя пиками.
    3. Программу загрузить "сюда" можно в виде зип-архива..
    4. Надо научиться программировать для компа самому. Хотя бы на Пуре- или Визуал- Бейсике. А то это будет не работа, а костыли.
    5. У вас есть Протеус ? Надо установить.
    ПС. Скачал ваш скетч. Компилируется без проблем. Посмотрю в Протеусе.
     
    Последнее редактирование: 8 июн 2020
  9. Airbus

    Airbus Радиохулиган Модератор

    30 лет прохожу ВЛЭК с пристрастием.Вот щас сижу и чешу репу
    [​IMG]
     
  10. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Подаю прямоугольные импульсы. Ширина -10%, период 1 сек. Начинает показывать при амплитуде 2.5 вольт. Всё путём.
     
  11. Aforizm

    Aforizm Нуб

    1.На комп это не надо отправлять, только в дисплей. На компе хватит графика, который уже есть.
    По значениям определить, хорошая это кардиограмма или плохая.
    2. Не спорю, но нужно именно два датчика, а так можно сделать в программе как дополнительный функционал.
    3. Программу загрузил.
    4. Не знаю к чему это, программа написана на C#
    5. Протеус есть, но он мне не нужен, всё уже собрано.
     

    Вложения:

    • d1.zip
      Размер файла:
      165,2 КБ
      Просмотров:
      190
  12. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Вопросы -
    1. Какой "график на компе уже есть" ? Кроме числа ударов в минуту программа на комп ничего не отправляет. Или я что-то пропустил ?
    2. Программа видимо на какой-то новой операционке. У меня не запускается. Что ей нужно ?
     
    Последнее редактирование: 9 июн 2020
  13. Aforizm

    Aforizm Нуб

    1. График типо как на картинке строится для пульса и экг. Программа больше ничего не отправляет. Данные выводятся как в график , так цифарми.
    2. На вин10.
     

    Вложения:

  14. b707

    b707 Гуру

    Афоризм - читал-читал ветку - так и не понял, в чем у вас проблема? Не умеете работать с двумя датчиками? Не знаете как выести две надписи на дисплей? Или еще в чем?
     
  15. Aforizm

    Aforizm Нуб

    Не умею работать с двумя датчиками
     
  16. Airbus

    Airbus Радиохулиган Модератор

    А шо там уметь?В цыкле измерил обработал вывел с первого датчика потом то же самое со второго. Скажи лучше что такое хорошая кардиограмма а что такое плохая? Как это замутить на Ардуино?Сделаю себе такой прибор пока китайцы не опередили.
     
  17. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Проектов таких на Ардуине - есть. Гуглятся на раз.
    Датчик ЭКГ - инструментальный усилитель, надо уметь "скрещивать" с АЦП. Если умеете - это обычный аналоговый ввод, примеры - в ИДЕ. Достаточна частота оцифровки 1Кс/сек. Для начала сделайте ручной выбор режима. Подвесьте на какой-либо пин подтягивающий резистор на плюс и тумблер на минус. В самом начале цикла выставьте проверку на уровень пина. Ноль-единица будут критерием перехода на соответствующую подпрограмму (ЭКГ/ Пульс). Содержимое цикла теперешнего скетча целиком запихните в подпрограмму Пульс. Подпрограмму ЭКГ пишите на основе примеров аналогового ввода или скачайте с Гугла. Такая автономия подпрограмм займет больше места, зато программно "прозрачна". Потом "устаканите" дубли типа вывода на LCD / Serial. За критерием "хорошо-нормально-плохо" - это только к врачам.
    ПС. Микра еще может выдать сигналы обрыва датчиков и принять "уход в спячку".
     
    Последнее редактирование: 9 июн 2020
    Aforizm нравится это.
  18. Aforizm

    Aforizm Нуб

    В цикле уже сделал, только теперь проблема, что данные поступают в программу с пробелами.
    Ну кардиограмма в норме - значит хорошая. Надо как-то с ней работать , по её зубцам определять, вот не знаю как.
     
  19. Aforizm

    Aforizm Нуб

    Проекты я видел, но все с один датчиком. За мысль спасибо, подумаю об этом.
     
  20. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Медсестра показывала как НЕ должна выглядеть кардиограмма. Примерно так. Видимо "это" и надо переводить в алгоритм оценки кардиограммы.
     

    Вложения:

    • Cardio.JPG
      Cardio.JPG
      Размер файла:
      16,8 КБ
      Просмотров:
      193
    Последнее редактирование: 10 июн 2020
    Aforizm нравится это.