Regarding Increasing the sampling rate Arduino BLE SENSE

Hi everyone,
I have just been using Arduino functions so far. I am now learning how to use peripherals and to read the data sheets. I have been studying about clock cycle, clock speed and a prescaler and I understand those concepts, now I would like to sample every 2ms and if possible perform ADC and display it in the serial monitor. My project is accurately monitoring pulse, I have a pulse sensor. l need to find the interval between two peaks in order to calculate beat's per minute. so the idea is to sample every 2ms and the check if crosses the threshold, if it does then store it in a buffer and send the value every second through serial communication. could you please tell me how can i do it using Arduino BLE sense, should i use a timer every 2ms and ISR to see if it crosses the threshold or is there any other way?

There are a lot of examples using other micro controllers, but not with nordic semiconductor board, I would like to know how to sample every 2ms and find the peaks with in a second and display it to the serial monitor, your help is very much appreciated. thanks.

Hi, welcome to the forum.

Arduino BLE Sense has a nRF52840 processor running at 64MHz.
That processor is not often used, so I don't know if there is a timer library for it.

You could start with a millis-timer of 2ms and use the normal analogRead() function and store the data.
A millis-timer is shown in the Blink Without Delay example. Running a 500Hz millis-timer on a 64MHz processor should be accurate enough, if the other code has no delay.

Can you tell more about the project ? Which pulse sensor is it ? Is it for a heartbeat ? That requires some serious programming. I have seen consumer devices that easily fail to detect the heartbeat in a consistent way.

Welcome to the forum.

If you scroll down a little bit in the forum you will find a post with almost the exact title.

https://forum.arduino.cc/t/increase-the-adc-sample-rate/701813

This contains two examples on how to use the ADC with a timer and the PPI system. One is for one channel and the second example is a modification with 3 channels.

If you want to measure time between pulses an alternative is to create a digital signal outside and use timers with capture/compare functions to measure the time. As Koepel said, it would be useful to get more information about your project and if you could provide a links to the sensor and links to datasheet for all non-Arduino components. That helps us help you. And you can show us you did your homework too. :slight_smile:

2 Likes

Yes sure, sorry for not giving the details about the project. Also sorry for replying late, because i am also writing my master's thesis. Yes I am using the pulse sensor for heart beat which is this one (https://pulsesensor.com/). As I have the Arduino BLE Sense and I am not sure how to use interrupts, I found the code that would calculate the beats per minute with out using the interrupts but not efficient from here (interrupt - pulse sensor + arduino mkr1000 to calculate BPM - Stack Overflow)

#define pulsePin A0

//  VARIABLES
int rate[10];                    
unsigned long sampleCounter = 0; 
unsigned long lastBeatTime = 0;  
unsigned long lastTime = 0, N;
int BPM = 0;
int IBI = 0;
int P = 512;
int T = 512;
int thresh = 512;  
int amp = 100;                   
int Signal;
boolean Pulse = false;
boolean firstBeat = true;          
boolean secondBeat = true;
boolean QS = false;    

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

}

void loop() {

              if (QS == true) {
                Serial.println("BPM: "+ String(BPM));
                QS = false;
              } else if (millis() >= (lastTime + 20)) {
                readPulse(); 
                lastTime = millis();
//                Serial.print("Last time = ");
//                Serial.println(lastTime);
              }     
}



void readPulse() {

  Signal = analogRead(pulsePin);              
  sampleCounter += 20;                                    // keep track of the time in mS 
  int N = sampleCounter - lastBeatTime;                   // monitor the time since the last beat to avoid noise

  detectSetHighLow();

  if (N > 200) {                                                              // avoid high frequency noise
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3) )       
      pulseDetected();
  }

  if (Signal < thresh && Pulse == true) {  // when the values are going down, the beat is over
    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;                           
    secondBeat = true;           
  }

}

void detectSetHighLow() {

  if (Signal < thresh && N > (IBI / 5) * 3) {
    if (Signal < T) {                       
      T = Signal;                // keep track of lowest point in pulse wave          
    }
  }

  if (Signal > thresh && Signal > P) {    
    P = Signal;                  // keep track of highest point in pulse wave         
  }                                       

}

void pulseDetected() {
  Pulse = true;                                   // set the Pulse flag when we think there is a pulse
  IBI = sampleCounter - lastBeatTime;             // measure time between beats in mS
  Serial.print("IBI = ");
  Serial.println(IBI);   
  lastBeatTime = sampleCounter;                   // keep track of time for next pulse

  if (firstBeat) {                                // if it's the first time we found a beat, if firstBeat == TRUE
    firstBeat = false;                            // clear firstBeat flag
    secondBeat = true;
    return;                            
  }
  if (secondBeat) {                                // if it's the secoond time we found a beat, if secondBeat == TRUE
    secondBeat = false;                            // clear SecondBeat flag
    for (int i = 0; i <= 9; i++) {                 
      rate[i] = IBI;
    }
  }

  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 (we detected a beat)
}

but the Interval between beats is not quite correct.

I don't have my finger tip on the sensor and it gives me values, where it should be printing zero.

when i start sensing the value this is the output.

What i want is to be able to detect the interval between two peaks and calculate the beats per minute.

This is the raw output from serial plotter when i sense the pulse.

I tried a lot, like

void loop() {
  
  Input_Voltage = analogRead( A0 ) ;
  sample_counter += 2;
//  Serial.print("sample_counter = ");
//  Serial.println(sample_counter);
//  Serial.print("Input_Voltage = ");
//  Serial.println(Input_Voltage);  
  
  if (Input_Voltage > threshold && Input_Voltage > sampleLast) {
          peak = Input_Voltage;
//          Serial.print("peak = ");
//          Serial.println(peak);  
          ts_1 = sample_counter;
//          delay(2); 
    } 

  
  if( Input_Voltage < sampleLast && Input_Voltage < threshold && (sample_counter - ts_1) > ((IBI / 5) * 3)  ) {
     first_peak = peak_2;
     first_peak_ts = peak_2_ts;

     peak_2 = peak;
     peak_2_ts = ts_1;
     flag = 1;
//     Serial.print("peak_2_ts = ");
//     Serial.println(peak_2_ts);
//     Serial.print("first_peak_ts = ");
//     Serial.println(first_peak_ts);
     IBI = peak_2_ts - first_peak_ts; 
     if (IBI != 0 ){
       Serial.print("IBI = ");
       Serial.println(IBI);
    }
  }
    

when the sample value is greater than threshold and larger than previous value, I note the sensor value, in that case when sample value is lesser than previous value and greater than threshold, i have a peak, I use the same and detect the second peak and calculate the difference, then i replace the second peak as first peak and find new second peak, but it doesn't seem to work.

can someone give me the logic to find the interval between two peaks with quick sampling rate. thank you so much for your help.

sorry for the late reply, I am also writing my master's thesis. could you please look at the reply to @Koepel, there i give the details of my project, ofcourse I did my homework. I found a lot of resources with other boards, it with this arduino ble sense, i could not find the resource for the interrupts with this pulse sensor.