2

I am reading an ECG signal using a single lead heart rate monitor. What I know is that when I use delay(15) it means that I am getting 66.67 readings in a second which corresponds to the sampling frequency. I want to set the sampling frequency to 250. This can be done by introducing delay(4).

What I really need is to set the sampling frequency to 250 Hz without introducing a delay in the code because I am acquiring ECG data in real time. Also, I am sending the data to python for processing and the delay will affect the sampling frequency in the time domain analysis.

any detailed solution or code ??

PS. I am using Arduino UNO

Code:

#define SERIAL_BUFFER_SIZE 8192
#include <SoftwareSerial.h>
unsigned long Time;
void setup() {

  // initialize the serial communication:

  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -
  Serial.println("CLEARDATA"); //clears up 

  Serial.println("RESETTIMER"); //resets timer to 0

  Serial.begin(115200);

}

void loop() {
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
   Serial.println('!');
  //  continue;
  }
  else{
   /*
     // send the value of analog input 0:
     int idata = analogRead(A0);
  //  float data = (idata*3.3)/1023;
      Serial.println(idata);
*/
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (3.3/1023.0);
  Serial.println(voltage);
  }
  //Wait for a bit
    delay(4);
}
2
  • 1
    You could also use a hardware timer to do this. E.g. use Timer1 to interrupt your code 250 times per second and take ADC measurement there. Also be aware of the ADCs conversion time, which can take about 100 us to execute. (Code see e.g. github.com/PaulStoffregen/TimerOne/blob/master/examples/…) Commented Mar 21, 2018 at 21:35
  • 1
    There are many options, which have varying degrees of accuracy and complexity. The right one for you depends on how much timing accuracy you require. See Getting a fixed sampling rate, which your question is almost a duplicate of. Commented Mar 21, 2018 at 22:16

1 Answer 1

5

Use the concept of blink without delay.

Instead of using delay() to set the timeout you use a timestamp and check micros() against that to see whether your interval has passed:

const unsigned long READ_PERIOD = 4000;  // 4000 us: 250 Hz

void loop() {
    static unsigned long lastRead;
    if (micros() - lastRead >= READ_PERIOD) {
        lastRead += READ_PERIOD;
        if (digitalRead(10) == 1 || digitalRead(11) == 1)
            Serial.println('!');
        else
            Serial.println(analogRead(A0) * (3.3/1024));
    }
}
4
  • 1
    I took the liberty to do a few edits: use micros() instead of millis(), as the latter has 1 ms of jitter; write lastRead += READ_PERIOD instead of lastRead = now to prevent creeping drift; a few simplifications. Commented Mar 21, 2018 at 22:12
  • Thanks for your answer. I have tried the code, however, it gave sampling frequency 125 Hz. I tried playing with the READ_PERIOD and I found that 2000 gave sampling frequency of 250 Hz. What does this number stand for and what concept or equation is being used ? Many thanks !! Commented Mar 22, 2018 at 19:14
  • (1000000 / 4000) == 250 If 2000 works your timing is off.
    – dandavis
    Commented Mar 22, 2018 at 19:50
  • @dandavis can you please specify the units of the baud rate and the reading period. it is (bps / us = hz) ?? Thanks Commented May 17, 2018 at 12:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.