Watchdog timer misbehavior in sleep mode

Hi all,

I want to put my Arduino pro Micro (Atmega32U4) to deep sleep mode and wake up every 1 minute checking some alarms, sending a short message and then going back to sleep again using a loop for extending my watchdog timer.
I read about it in the following link:
https://forum.arduino.cc/index.php?topic=173850.0
I used Nick Gammon’s code for this purpose.

My problem is, it sometimes does not enter sleep mode. Keeps sending messages for about a minute (this time varies every time it goes crazy) and then it goes to sleep normally. This bug occurs at least 5 times in an hour and I don’t know what’s wrong.

I’d be really grateful if anyone could help me out.

/******************************************************************************
 * Include files
 ******************************************************************************/
#include <arduino.h>
#include "HopeDuino_LoRa.h"
#include <avr/sleep.h>
#include "ArduinoUniqueID.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <EEPROM.h>
#include <avr/wdt.h>
#include <avr/power.h>
/******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/
#define   RX_MODE         1
#define   TX_MODE        (!RX_MODE)

#define LEN 32
const int buttonPin0 = 0;  // the number of the pushbutton pin
const int buttonPin1 = 1;
const int buttonPin2 = 2;
const int buttonPin3 = 3;
const int buttonPin4 = 7;
// variables will change:
volatile int stud0,stud1,stud2,stud3,stud4= 0;        // variable for reading the pushbutton status

#define LED_PIN    6
#define LED_PORT()         pinMode(LED_PIN,OUTPUT)
#define LED_HIGH()         digitalWrite(LED_PIN,HIGH)
#define LED_LOW()          digitalWrite(LED_PIN,LOW)

byte str[LEN]={'H','o','p','e','R','F',' ','R','F','M',' ','C','O','B','R','F','M','9','5','W','A','+','+','+'};
//byte mac[]={UniqueID8};
byte str0[]= "stud11";
byte str1[]= "stud21";
byte str2[]= "stud31";
byte str3[]= "stud41";
byte str4[]= "stud51";
byte str5[]={"batt"};
byte getstr[LEN];
byte mode = RX_MODE;  
const byte app_syncword[] = { 0x2D, 0xD4, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 } ;  

void setup(void)
{ 
  LED_PORT(); 
  Modulation     = LORA;            ///Was FSK
  COB            = RFM95;           // Was RFM95
  Frequency      = 915000;          // was 866000
  OutputPower    = 3;              //17dBm OutputPower
  PreambleLength = 8;               //8Byte preamble
  FixedPktLength = true;            //explicit header mode for LoRa
  PayloadLength  = 21;
  CrcDisable     = true ;
  
  //for LORA parameter
  SFSel      = SF9;
  BWSel      = BW125K;
  CRSel      = CR4_5;

 // initialize the pushbutton pin as an input:
  pinMode(buttonPin0, INPUT);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  // Attach an interrupt to the ISR vector
  attachInterrupt(digitalPinToInterrupt(buttonPin0|buttonPin1|buttonPin2|buttonPin3|buttonPin4), pin_ISR, HIGH);
      vInitialize();
      bSendMessage(UniqueID8,9);
} 
  void loop(void)
  { 
   power_Down();  //Low-Power mode
   vGoSleep(); 
  static byte last_mode=RX_MODE;
 pin_ISR();
 stud0 = digitalRead(buttonPin0);
 stud1 = digitalRead(buttonPin1);
 stud2 = digitalRead(buttonPin2);
 stud3 = digitalRead(buttonPin3);
 stud4 = digitalRead(buttonPin4);
     
     if (stud0==1){ //It takes a long time to start the initial blink
     //vReset();
     vInitialize();
     _delay_ms(10);
     mode = TX_MODE;   
     LED_HIGH();
     _delay_ms(25);
     bSendMessage(str0,8);
     _delay_ms(50);
     bSendMessage(UniqueID8,9);
     LED_LOW();
     }
     else if (stud1==1){ //It takes a long time to start the initial blink
     //vReset();
     vInitialize();
     _delay_ms(10);
     mode = TX_MODE;   
     LED_HIGH();
     _delay_ms(25);
     bSendMessage(str1,8);
     _delay_ms(50);
     bSendMessage(UniqueID8,9);
     LED_LOW();
     _delay_ms(100);
      }
     else if (stud2==1){ //It takes a long time to start the initial blink
     //vReset();
     vInitialize();
     _delay_ms(10);
     mode = TX_MODE;   
     LED_HIGH();
     _delay_ms(25);
     bSendMessage(str2,8);
     _delay_ms(50);
     bSendMessage(UniqueID8,9);
     LED_LOW();
     _delay_ms(100);
      }
     else if (stud3==1){ //It takes a long time to start the initial blink
     //vReset();
     vInitialize();
     _delay_ms(10);
     mode = TX_MODE;   
     LED_HIGH();
     _delay_ms(25);
     bSendMessage(str3,8);
     _delay_ms(50);
     bSendMessage(UniqueID8,9);
     LED_LOW();
     _delay_ms(100);
     }
   else if (stud4==1){ //It takes a long time to start the initial blink
     vInitialize();
     _delay_ms(10);
     mode = TX_MODE;   
     LED_HIGH();
     _delay_ms(25);
     bSendMessage(str4,8);
     _delay_ms(50);
     bSendMessage(UniqueID8,9);
     LED_LOW();
     _delay_ms(100);
     }
    else{  
 /*
  * Watchdog timer
  */
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
    myWatchdogEnable (0b100001);  // 8 seconds
    myWatchdogEnable (0b000111);  // 2 seconds
      vInitialize();                 //Turn on RFM95
      _delay_ms(50);
      bSendMessage(UniqueID8,9);   // after every 1 minute send a message
 }} 
 void pin_ISR() {
  stud0 = digitalRead(buttonPin0);
  stud1 = digitalRead(buttonPin1);
  stud2 = digitalRead(buttonPin2);
  stud3 = digitalRead(buttonPin3);
  stud4 = digitalRead(buttonPin4);
  digitalWrite(LED_PIN, stud0);
  digitalWrite(LED_PIN, stud1);
  digitalWrite(LED_PIN, stud2);
  digitalWrite(LED_PIN, stud3);
  digitalWrite(LED_PIN, stud4);
 }
ISR(WDT_vect)
  {
  wdt_disable();  // disable watchdog
  }
void myWatchdogEnable(const byte interval)
  { 
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  MCUCR |= (1<<JTD);
  MCUCR |= (1<<JTD);                  // Disable JTAG
  vGoSleep();                         // turn off RFM95
  DDRF = 0x00;                       //Disable portF
  PORTF = 0x00;
  MCUCR = 1;
  wdt_reset();
  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_mode();            // now goes to Sleep and waits for the interrupt
  }
void power_Down()
{
        vGoSleep(); // turn off RFM95
        ADCSRA = 0; 
        delay(1);   //IMPORTANT!!! Allow time for changing firmware, or otherwise if we disable the USB too soon we are stuck and only a re-flash of the bootloader may help   
        power_adc_disable();
        delay(1);
        power_usart0_disable();
        delay(1);
        power_spi_disable();
        delay(1);
        power_twi_disable();
        delay(1);
        power_timer1_disable();
        delay(1);
        power_timer2_disable();
        delay(1);
        power_timer3_disable();
        delay(1);
        power_usart1_disable();
        delay(1);
        power_usb_disable();
        delay(1);
        USBCON |= (1 << FRZCLK);             // Freeze the USB Clock              
        PLLCSR &= ~(1 << PLLE);              // Disable the USB Clock (PPL) 
        USBCON &=  ~(1 << USBE  );           // Disable the USB  
        delay(1);
        // Switch to RC Clock 
        UDINT  &= ~(1 << SUSPI); // UDINT.SUSPI = 0; Usb_ack_suspend
        USBCON |= ( 1 <<FRZCLK); // USBCON.FRZCLK = 1; Usb_freeze_clock
        PLLCSR &= ~(1 << PLLE); // PLLCSR.PLLE = 0; Disable_pll
       CLKSEL0 |= (1 << RCE); // CLKSEL0.RCE = 1; Enable_RC_clock()
        while ( (CLKSTA & (1 << RCON)) == 0){}    // while (CLKSTA.RCON != 1);  while (!RC_clock_ready())
        CLKSEL0 &= ~(1 << CLKS);  // CLKSEL0.CLKS = 0; Select_RC_clock()
        CLKSEL0 &= ~(1 << EXTE);  // CLKSEL0.EXTE = 0; Disable_external_clock
        delay(1);  
        }
  attachInterrupt(digitalPinToInterrupt(buttonPin0|buttonPin1|buttonPin2|buttonPin3|buttonPin4), pin_ISR, HIGH);

I'm sure this line does not what you expected it to do.

If there is one of these pins is high the described behavior is what you programmed. As you failed to provide a wiring diagram we have no clue what this code does and why.

pylon:

  attachInterrupt(digitalPinToInterrupt(buttonPin0|buttonPin1|buttonPin2|buttonPin3|buttonPin4), pin_ISR, HIGH);

I'm sure this line does not what you expected it to do.

If there is one of these pins is high the described behavior is what you programmed. As you failed to provide a wiring diagram we have no clue what this code does and why.

Thanks for the reply, to be honest, this line actually does the intended work.
About the code,
this is supposed to detect if an interrupt is triggered and send two messages back to a Receiver. buttonPin 0 to 4 are the five interrupt lines. Every 1 minute, the device turns on using the watch dog timer and sends a message to say it's alive and then goes to sleep for another minute. Now, sometimes when it wakes up from sleeping, it never goes back to sleep again and starts sending crazy number of messages every second. You need to restart it manually to work well again. I was looking for a way to fix it.
Like setting up another timer for when it's on and say if you don't sleep within a second, you force restart the code. Maybe using a second watchdog timer.?

Thanks for the reply, to be honest, this line actually does the intended work.

I doubt that. It does enable exactly one interrupt. If that was the intention you have a rather strange way to code it.

Please format your code (the AutoFormat option in the Tools menu may help you) and post it again.

Why do you call your interrupt handler from the loop?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.