PC Interrupt doesn't wake up mcicrocontroller

Hi all,

I'm using ATMEGA328P, Nano board and I want to wake up from deep sleep mode when I release a button (Not pressing it). My interrupts are normally closed and grounded if that helps. I've been stuck on this code for a long time now.
I just want to know why the interrupt can't wake it up from sleep.
Now in my code, I have a one-minute watchdog timer waking the board up (and it can read the interrupt after the one-minute delay) , But, I need to know immediately when the interrupt triggers.
Here's the code:

#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>
#include "timer.h"
#include "timerManager.h"
#include <PinChangeInterrupt.h>

#define LEN 32
// Choose a valid PinChangeInterrupt pin of your Arduino board
#define buttonPin0 2
#define buttonPin1 3
#define buttonPin2 4
#define buttonPin3 9
#define buttonPin4 10

// variables will change:
volatile int stud0,stud1,stud2,stud3,stud4= 0;        // variable for reading the pushbutton status

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

const char str0[]= "pair";
const char str1[]= "1";
const char str2[]= "2";
const char str3[]= "3";
const char str4[]= "4";
const char str5[]= "5";
const char str6[]= "b";

byte getstr[LEN];
byte mode = RX_MODE;  
const byte app_syncword[] = { 0x2D, 0xD4, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 } ; 
char output0[25];
char output1[25];
char output2[25];
char output3[25];
char output4[25];
char output5[25];
char output6[25];
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      = SF7;
  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 the new PinChangeInterrupt and enable event function below
  attachPCINT(digitalPinToPCINT(buttonPin0), pin_ISR1, RISING);
  attachPCINT(digitalPinToPCINT(buttonPin1), pin_ISR2, RISING);
  attachPCINT(digitalPinToPCINT(buttonPin2), pin_ISR3, RISING);
  attachPCINT(digitalPinToPCINT(buttonPin3), pin_ISR4, RISING);
  attachPCINT(digitalPinToPCINT(buttonPin4), pin_ISR5, RISING);
  
  strcpy(output0,str0);
    for(byte i = 0; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output0, idStr);}
    
    strcpy(output1,str1);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output1, idStr);}
    
    strcpy(output2,str2);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output2, idStr);}
    
    strcpy(output3,str3);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output3, idStr);}
    
    strcpy(output4,str4);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output4, idStr);}
    
    strcpy(output5,str5);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output5, idStr);}
    
    strcpy(output6,str6);
    for(byte i = 4; i < 8; i++){
    char idStr[4]; //need at least 1 (space) + 2 (id) + 1 (null termination)
    sprintf(idStr, "%02x", UniqueID8[i]);
    strcat(output6, idStr);}
      vInitialize();
      bSendMessage(output0,25);// Output0 is the pair message
      _delay_ms(20);
      bSendMessage(output0,25);
      _delay_ms(20);
      myWatchdogEnable (0b000110);  // 1 second
} 
  void loop(void)
  {  
   vGoSleep();
   myWatchdogEnable (0b000110);  // 1 second 
  static byte last_mode=RX_MODE;
   pin_ISR1();
   pin_ISR2();
   pin_ISR3();
   pin_ISR4();
   pin_ISR5();
 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
     vInitialize();
     _delay_ms(10);   
     LED_HIGH();
      bSendMessage(output1,25);
     _delay_ms(125);
      bSendMessage(output1,25);
     LED_LOW();
     }
     if (stud1==1){ //It takes a long time to start the initial blink
     vInitialize();
     _delay_ms(10);   
     LED_HIGH();
      bSendMessage(output2,25);
     _delay_ms(125);
      bSendMessage(output2,25);
     LED_LOW();
      }
     if (stud2==1){ //It takes a long time to start the initial blink
     vInitialize();
     _delay_ms(10);   
     LED_HIGH();
      bSendMessage(output3,25);
     _delay_ms(125);
      bSendMessage(output3,25);
     LED_LOW();
      }
     if (stud3==1){ //It takes a long time to start the initial blink
     vInitialize();
     _delay_ms(10); 
     LED_HIGH();
      bSendMessage(output4,25);
     _delay_ms(125);
      bSendMessage(output4,25);
     LED_LOW();
     }
    if (stud4==1){ //It takes a long time to start the initial blink
     vInitialize();
     _delay_ms(10); 
     LED_HIGH();
      bSendMessage(output5,25);
     _delay_ms(125);
      bSendMessage(output5,25);
     LED_LOW();
     } 
 /*********************
  * Watchdog timer
  *********************/
// sleep bit patterns:
//  1 second:  0b000110
//  2 seconds: 0b000111
//  4 seconds: 0b100000
//  8 seconds: 0b100001
    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
 } 
 
 void pin_ISR1() {
  stud0 = digitalRead(buttonPin0);
  digitalWrite(LED_PIN, stud0);
 }
  void pin_ISR2() {
  stud0 = digitalRead(buttonPin1);
  digitalWrite(LED_PIN, stud1);
 }
  void pin_ISR3() {
  stud0 = digitalRead(buttonPin2);
  digitalWrite(LED_PIN, stud2);
 }
  void pin_ISR4() {
  stud0 = digitalRead(buttonPin3);
  digitalWrite(LED_PIN, stud3);
 }
  void pin_ISR5() {
  stud0 = digitalRead(buttonPin4);
  digitalWrite(LED_PIN, stud4);
 }
  
  ISR(WDT_vect)
  {
  wdt_disable();  // disable watchdog
  }

void myWatchdogEnable(const byte interval)
  { 
  vGoSleep();
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  wdt_reset();

  // disable ADC
  ADCSRA = 0;  
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  cli();           // timed sequence follows
  sleep_enable();
  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  sei();             // guarantees next instruction executed
  //sleep_cpu ();           // now goes to Sleep and waits for the interrupt
  sleep_mode();     //goes to sleep faster than Sleep_CPU

  }

Does you Arduino KNOW the button is pressed at the time it goes to sleep?
Paul

Paul_KD7HB:
Does you Arduino KNOW the button is pressed at the time it goes to sleep?
Paul

I don't know, it should be triggered by the pc interrupt, shouldn't it? That's how it reads the pins when it wakes up from sleep. Do you mean to read every pin individually like a normal button?

dizzycoder:
I don't know, it should be triggered by the pc interrupt, shouldn't it? That's how it reads the pins when it wakes up from sleep. Do you mean to read every pin individually like a normal button?

Your interrupt seems to be looking for a voltage change. Unless the electronics is aware of the voltage level before the button is released, there is no pin voltage change, is there?
Paul

I suggest to start with a very simple program to test sleeping and wake on pin change interrupts, and get that working first.

No one wants to wade through everything that you posted.

 void pin_ISR1() {
  stud0 = digitalRead(buttonPin0);
  digitalWrite(LED_PIN, stud0);
 }
  void pin_ISR2() {
  stud0 = digitalRead(buttonPin1);
  digitalWrite(LED_PIN, stud1);
 }
  void pin_ISR3() {
  stud0 = digitalRead(buttonPin2);
  digitalWrite(LED_PIN, stud2);
 }
  void pin_ISR4() {
  stud0 = digitalRead(buttonPin3);
  digitalWrite(LED_PIN, stud3);
 }
  void pin_ISR5() {
  stud0 = digitalRead(buttonPin4);
  digitalWrite(LED_PIN, stud4);
 }

Is this intentional? You are reading into stud0 in every function, but writing out from stud#.

Paul_KD7HB:
Your interrupt seems to be looking for a voltage change. Unless the electronics is aware of the voltage level before the button is released, there is no pin voltage change, is there?
Paul

So, my interrupts are normally closed buttons and they're grounded. If any of them opens (Not grounded anymore), the interrupt should be triggered. That's why I used a rising edge. I figured (HIGH,RISING and CHANGE) work almost the same. whereas (FALLING and LOW) don't work because I'm normally grounded.
Please note that they're all pulled up with an external resistor and they're easily read when the CPU is not Asleep.

Jiggy-Ninja:
Is this intentional? You are reading into stud0 in every function, but writing out from stud#.

Oh Jeez, good point, I forgot to fix it, it can now wake up from sleep. Thank you very much. I must've missed it at some point because I changed this code a lot. You're fantastic.

Just to clarify a couple things:

Your code was waking from sleep before. This bug would just prevent it from showing.

Also, the PIn Change interrupt hardware can only detect toggles, it doesn't have any inherent ability to distinguish between RISING and FALLING. That is done in the library's software. So your processor will wake up on ANY change of the pin, even LOW-to-HIGH. Make sure your code is able to handle that properly.

Jiggy-Ninja:
Also, the PIn Change interrupt hardware can only detect toggles,

That's absolutely true. I just check it on the circuit and it's miraculously doing what I wanted.
Now one thing that bothers me is that, when I trigger it, although the microcontroller wakes up, but it doesn't do anything until that one-minute watchdog timer is finished. I mean it stays awake and when it reaches one minute, then it runs the code and goes back to sleep again.
Do you think I should reset the watchdog timer when it wakes up? Or is there anything else to clear watchdog timer as soon as the microcontroller wakes up?

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