0
#define TIM2_EN() (TIMSK2 = 0x02)
#define TIM2_DIS() (TIMSK2 = 0x00)

//HEART SENSOR
// Include Libraries
#include "Arduino.h"

class PulseSensor
{
public:
  static void begin(int pulsePin);

  static volatile int BPM;           // used to hold the pulse rate
  static volatile int Signal;        // holds the incoming raw data
  static volatile int IBI;           // holds the time between beats, must be seeded!
  static volatile boolean QS;        // becomes true when Arduoino finds a beat.
};

// Pin Definitions
#define HEARTPULSE_PIN_SIG  A0

// Global variables and defines

// object initialization
PulseSensor heartpulse;

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 = 512;                    // 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
volatile boolean Pulse = false;               // true when pulse wave is high, false when it's low
volatile int pulsePin;

volatile int PulseSensor::IBI = 600;          // holds the time between beats, must be seeded!
volatile int PulseSensor::BPM;                // used to hold the pulse rate
volatile int PulseSensor::Signal;             // holds the incoming raw data
volatile boolean PulseSensor::QS = false;     // becomes true when Arduino finds a beat

void PulseSensor::begin(int pPin)
{
  pinMode(pulsePin, INPUT);
  pulsePin = pPin;

  // Initializes Timer1 to throw an interrupt every 2ms.
  TCCR1A = 0x00;
  TCCR1B = 0x0C;  // CTC (Compare match mode) and ClockIO/256
  OCR1A = 0x7C;   // 2 ms
  TIMSK1 = 0x02;
  sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}

// THIS IS THE TIMER 1 INTERRUPT SERVICE ROUTINE. 
// Timer 1 makes sure that we take a reading every 2 miliseconds
ISR(TIMER1_COMPA_vect)
{                         // triggered when Timer1 counts to 124
  cli();                                      // disable interrupts while we do this
  PulseSensor::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(PulseSensor::Signal < thresh && N > (PulseSensor::IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
    if (PulseSensor::Signal < T){                        // T is the trough
      T = PulseSensor::Signal;                         // keep track of lowest point in pulse wave 
    }
  }

  if(PulseSensor::Signal > thresh && PulseSensor::Signal > P){          // thresh condition helps avoid noise
    P = PulseSensor::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 ( (PulseSensor::Signal > thresh) && (Pulse == false) && (N > (PulseSensor::IBI/5)*3) )
    {        
      Pulse = true;                               // set the Pulse flag when we think there is a pulse
      PulseSensor::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] = PulseSensor::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] = PulseSensor::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 
      PulseSensor::BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
      PulseSensor::QS = true;                              // set Quantified Self flag 
      // QS FLAG IS NOT CLEARED INSIDE THIS ISR
    }                       
  }

  if (PulseSensor::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;                      // set these to avoid noise
    secondBeat = false;                    // when we get the heartbeat back
  }

  sei();                                   // enable interrupts when youre done!
} // end isr

//LDR SENSOR
int sensorPin = A1; // select the input pin for LDR
int sensorValue = 0; // variable to store the value coming from the sensor

//LCD
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

//DHT
#include "dht.h"
int dht_apin = 2;  
dht DHT;

//HEART RATE SENSOR
unsigned long current_time,start_time=0;
int BPM,Interval;

void setup(){

  Serial.begin(115200);
  heartpulse.begin(HEARTPULSE_PIN_SIG);
  delay(1500);
  lcd.init();          // initialize the lcd 
  lcd.backlight();
  lcd.print("  INITIALISING");
  delay(2500);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" CHECKING HEART");
  lcd.setCursor(0,1);
  lcd.print(" RATE NOW......");
  delay(2000);
  lcd.clear();
}

void loop() {

  current_time = millis();
  if ( current_time-start_time < 30000 )  {
    BPM = heartpulse.BPM;
    Interval = heartpulse.IBI; 
    lcd.print(" SYNCHRONIZING  ");
    lcd.setCursor(0,1);
    lcd.print("   BEATS:"); 
    lcd.print(BPM);
    lcd.clear();
  } else  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("BEATS PER MINUTE");
    lcd.setCursor(6,1);
    lcd.print(BPM); 
    Serial.print(BPM);
    Serial.println('b');
    delay(4000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" BEAT INTERVAL  ");
    lcd.setCursor(7,1);
    lcd.print(Interval); 
    Serial.print(Interval);
    Serial.println('p');
    delay(4000);
    TIM2_DIS(); //Enable TIMER2 Interrupt
    DHT.read11(dht_apin); 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("    HUMIDITY    ");
    lcd.setCursor(6,1);
    lcd.print(DHT.humidity);
    lcd.print("%");
    Serial.print(DHT.humidity);
    Serial.println('h');
    delay(4000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  TEMPERATURE  ");
    lcd.setCursor(5,1);
    lcd.print(DHT.temperature);
    lcd.print("C");
    Serial.print(DHT.temperature);
    Serial.println('t');
    TIM2_EN(); //Disable TIMER2 Interrupt
    delay(4000);  
    sensorValue = analogRead(sensorPin); // read the value from the sensor
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LIGHT INTENSITY");
    lcd.setCursor(7,1);
    lcd.print(sensorValue);
    Serial.print(sensorValue);
    Serial.println('l');
    delay(4000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" CHECKING HEART");
    lcd.setCursor(0,1);
    lcd.print(" RATE NOW......");
    delay(2000);  
    lcd.clear();
    start_time = millis();
  }
}

I am trying to run LDR,PULSE AND DHT11 sensor together. DHT11 was not giving out readings along with pulse sensor before so I searched stack exchange and found out this solution.

DHT11 and Pulse sensor incompatibility?

But now the problem is Arduino gets stuck at the line when I disable timer 2 interupt -

TIM2_EN(); //Disable TIMER2 Interrupt

Any solution?

  • 1
    are you sure that TIM2_EN() disables the interrupt? ...... what does TIM2_DIS() do? – jsotola Mar 23 at 19:43
  • I came up with this idea from here. arduino.stackexchange.com/questions/21489/… The code given in this works with this solution but my code is stuck and it is not even reading values from DHT – Rohan Mar 23 at 19:44
  • If i remove this line the code isn't stuck anymore- TIM2_EN(); //Disable TIMER2 Interrupt....But still Arduino is not able to read values from DHT11. – Rohan Mar 23 at 19:53
  • I do not know, can you explain in detail. – Rohan Mar 23 at 19:57
  • 1
    Got the solution, I was accidentally enabling and disabling timer 2 interrupt when actually I was using timer 1 in my program. Now first I am preventing timer 1 interrupts with TIMSK1 = 0 before reading DHT and again enabling timer 1 with TIMSK1 = 0x02 . Thanks #jsotola for telling me to find the failure ! Anyone wants to add anything about interupts ? – Rohan Mar 23 at 20:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.