Watch Dog Timer with IR Sensor as Interrupt

I want to build a small Arduino project where I’m using the following components.

DHT11 Sensor - to measure the temperature and humidity
IR Sensor - to receive IR Signals
Double relay module - to switch on and off electrical components
The Arduino will follow like this, the DHT11 will be watched using the Watch Dog Timer every 24 seconds and based on the value, the relay will be switched on and off. The IR sensor is used to switch the other relay module based on the signal received.

I’m having an error with the DHT11 sensor when using the Watch Dog Timer together with the IR Sensor. When I do monitor console, I’m getting ‘Error’ for the DHT11 Sensor.

#include <SimpleDHT.h>          // library for DHT11 sensor
#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control
#include <IRremote.h>           // library for IR Sensor

SimpleDHT11 dht11;

int pin_relay1 = 8;
int pin_relay2 = 9;
int pin_dht11 = 10;
int pin_irSensor = 2;
int pin_led = 11;

IRrecv irrecv(pin_irSensor);
decode_results results;

//ON relay == LOW
//OFF relay == HIGH

// how many times remain to sleep before wake up
// volatile to be modified in interrupt function
volatile int nbr_remaining;
volatile byte state = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(pin_relay1, OUTPUT);
  pinMode(pin_relay2, OUTPUT);
  pinMode(pin_dht11, INPUT);
  pinMode(pin_irSensor, INPUT);
  pinMode(pin_led, OUTPUT);
  irrecv.enableIRIn(); // Start the receiver
  // configure the watchdog
  configure_wdt();
  attachInterrupt(0, wakeUpNow, FALLING); // use interrupt 0 (pin 2) and run function
  // wakeUpNow when pin 2 gets LOW
}

void loop() {
  getDHTReading();
}


void wakeUpNow()        // here the interrupt is handled after wakeup
{
  //execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
  if (irrecv.decode(&results)) {
    if (results.value == 0xff629d) {
      state = !state;
      digitalWrite(pin_led, state);

    }
    irrecv.resume(); // Receive the next value
  }
}

void getDHTReading() {
  byte temperature = 0.0;
  byte humidity = 0.0;
  int err = SimpleDHTErrSuccess;
  if ((err = dht11.read(pin_dht11, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
    Serial.println("Error");
    return;
  }

  Serial.print((double)temperature); Serial.print(" *C, ");
  Serial.print((double)humidity); Serial.println(" H");
  delay(5000);
  // sleep for a given number of cycles (here, 5 * 8 seconds) in lowest power mode
  sleep(3);
}

// interrupt raised by the watchdog firing
// when the watchdog fires, this function will be executed
// remember that interrupts are disabled in ISR functions
// now we must check if the board is sleeping or if this is a genuine
// interrupt (hanging)
ISR(WDT_vect) {
  // Check if we are in sleep mode or it is a genuine WDR.
  if (nbr_remaining > 0)
  {
    // not hang out, just waiting
    // decrease the number of remaining avail loops
    nbr_remaining = nbr_remaining - 1;
    wdt_reset();
  }
  else
  {
    // must be rebooted
    // configure
    MCUSR = 0;                          // reset flags
    // Put timer in reset-only mode:
    WDTCSR |= 0b00011000;               // Enter config mode.
    WDTCSR =  0b00001000 | 0b000000;    // clr WDIE (interrupt enable...7th from left)
    // set WDE (reset enable...4th from left), and set delay interval
    // reset system in 16 ms...
    // unless wdt_disable() in loop() is reached first

    // reboot
    while (1);
  }
}


// function to configure the watchdog: let it sleep 8 seconds before firing
// when firing, configure it for resuming program execution by default
// hangs will correspond to watchdog fired when nbr_remaining <= 0 and will
// be determined in the ISR function
void configure_wdt(void)
{

  cli();                           // disable interrupts for changing the registers
  MCUSR = 0;                       // reset status register flags
  // Put timer in interrupt-only mode:
  WDTCSR |= 0b00011000;            // Set WDCE (5th from left) and WDE (4th from left) to enter config mode,
  // using bitwise OR assignment (leaves other bits unchanged).
  WDTCSR =  0b01000000 | 0b100001; // set WDIE: interrupt enabled
  // clr WDE: reset disabled
  // and set delay interval (right side of bar) to 8 seconds
  sei();                           // re-enable interrupts
}


// Put the Arduino to deep sleep. Only an interrupt can wake it up.
void sleep(int ncycles)
{
  nbr_remaining = ncycles; // defines how many cycles should sleep
  // Set sleep to full power down.  Only external interrupts or
  // the watchdog timer can wake the CPU!
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  // Turn off the ADC while asleep.
  power_adc_disable();
  while (nbr_remaining > 0) { // while some cycles left, sleep!
    // Enable sleep and enter sleep mode.
    sleep_mode();
    // CPU is now asleep and program execution completely halts!
    // Once awake, execution will resume at this point if the
    // watchdog is configured for resume rather than restart
    // When awake, disable sleep mode
    sleep_disable();
  }
  // put everything on again
  power_all_enable();
}

I would suggest to start by getting it all working within your loop() function, possibly using the delay() function. Once that is working correctly, then incorporate all the WDT and sleep and see if it continues to work or not. Solve the problem one step at a time.

You cannot install an interrupt service routine on the pin that reads the IR code and on the first edge you get read the complete code. Move that code to your loop() routine.

Regarding the DHT sensor: why don’t you print out the error the library returns?

How often do you get that error? Always? At random times?

I get the error concerning the DHT11 when I startup the program. Its not at random

ehteeshaam:
I get the error concerning the DHT11 when I startup the program. Its not at random

Then post that information! Which error code do you get? If it's not random what is it then?

Hi,
I am in a similar case.

Here my code:

#include <IRremote.h>

int receiver = 3; // Signal Pin of IR receiver to Arduino Digital Pin 11

/*-----( Declare objects )-----*/
IRrecv irrecv(receiver);     // create instance of 'irrecv'
decode_results results;      // create instance of 'decode_results'

/*-----( Function )-----*/
void translateIR() // takes action based on IR code received

// describing Remote IR codes

{
 Serial.println(results.value);
  switch(results.value)

  {

  case 0xFF6897: Serial.println("0");    break;
  case 0xFF30CF: Serial.println("1");    break;
  case 0xFF18E7: Serial.println("2");    break;
  case 0xFF7A85: Serial.println("3");    break;
  case 0xFF10EF: Serial.println("4");    break;
  case 0xFF38C7: Serial.println("5");    break;
  case 0xFF5AA5: Serial.println("6");    break;
  case 0xFF42BD: Serial.println("7");    break;
  case 0xFF4AB5: Serial.println("8");    break;
  case 0xFF52AD: Serial.println("9");    break;
  case 0xFFFFFFFF: Serial.println(" REPEAT");break;

  default:
    Serial.println(" other button   ");

  }// End Case

  delay(500); // Do not get immediate repeat
}

/**
 * 
 * Librería para recuperar temperatura y humedad
 * */

#include <SimpleDHT.h>
int pinDHT11 = 2;
SimpleDHT11 dht11;


/**
 * Liberia leds
 *
 * **/
#include <MaxMatrix.h>
#include <avr/pgmspace.h>



PROGMEM const unsigned char CH[] = {
};
int DIN = 12;   // DIN pin of MAX7219 module
int CLK = 10;   // CLK pin of MAX7219 module
int CS = 11;    // CS pin of MAX7219 module
int maxInUse = 2;
MaxMatrix m(DIN, CS, CLK, maxInUse);
byte buffer[10];
//char text[]= "HowToMechatronics.com  "; // Scrolling text
String text="";


void setup() {

  //max7219
  m.init(); // module initialize
  m.setIntensity(15); // dot matix intensity 0-15

  //IR
  
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode"); 
  irrecv.enableIRIn(); // Start the receiver
 /**/
}

// Display=the extracted characters with scrolling
void printCharWithShift(char c, int shift_speed) {
  if (c < 32) return;
  c -= 32;
  memcpy_P(buffer, CH + 7 * c, 7);
  m.writeSprite(32, 0, buffer);
  m.setColumn(32 + buffer[0], 0);
  for (int i = 0; i < buffer[0] + 1; i++)
  {
    delay(shift_speed);
    m.shiftLeft(false, false);
  }
}

// Extract the characters from the text string
void printStringWithShift(char* s, int shift_speed) {
  while (*s != 0) {
    printCharWithShift(*s, shift_speed);
    s++;
  }
}

 // return charArray from a String 
char* string2char(String command){
    if(command.length()!=0){
        char *p = const_cast<char*>(command.c_str());
        return p;
    }
}


void loop() {
 //ir 


  //DHT
  text="";
  byte temperature = 0;
  byte humidity = 0;
  byte data[40] = {0};
  
   if (dht11.read(pinDHT11, &temperature, &humidity, data)) {
    text="Read DHT11 failed";
  }else{
     for (int i = 0; i < 40; i++) {
     text +=(int)data[i];
    if (i > 0 && ((i + 1) % 4) == 0) {
       text +=' ';
    }
  }

  String temp= String(temperature);
  String hum= String(humidity);

   text ="Tem. "+temp+"C.  -  Hum. "+hum+"%    ";
  

    }

  

  printStringWithShift(string2char(text), 200); // (text, scrolling speed Delay)
 
 /*
 if (irrecv.decode(&results)) // have we received an IR signal?

  {
    translateIR();
    irrecv.resume(); // receive the next value
  }
  */
}

When starts receiver
(line 186) irrecv.enableIRIn(); // Start the receiver
…/…
(line 231) dht11.read(pinDHT11, &temperature, &humidity, data)
returns 00
if comment line 186 all works and temp and hum is well readed
Thanks.

enableIRIn() will start a timer with will trigger an interrupt every 50µs. This hurts the timing of the SimpleDHT library. You can put cli() and sei() calls around the dht11.read() call (which disabled reception of IR signals while reading the environmental sensor values) or change to a sensor that doesn't use a timing critical interface (I2C).