Interrupt stops working after a few cycles

Hi there!

I do have problems getting a wake up from sleep through external interrupt to work on my mini pro, 8mhz.

The sketch works for a few times (going to sleep, waking up again) but after a few wake-and-sleep-cycles the program freezes, nothing happens and the Arduino is sleeping forever. Resetting the Arduino solves the problem but again it freezes after a few times. The external interrupt is triggered by a mini PIR sensor. My scope shows reliable functionality of the PIR so I get a rising edge signal on motion detection but the interrupt on the arduino does not fire. I tried pin 2 and 3 but behavior is the same.

What could be the problem?

Thanks in advance!


#include <avr/sleep.h>
#include <avr/wdt.h>
#include <Wire.h>
#include "src/DS3231/DS3231.h"
#include "src/SCNokia5110/SCNokia5110.h"
#include "src/SCLed/SCLed.h"
#include "src/SCTimer/SCTimer.h"


#define PIN_PIR 3
#define PIN_DISPLAY_LED 10
#define PIN_LDR A0
#define PIN_BTN1 6
#define PIN BTN2 9



bool century = false;
bool h12Flag;
bool pmFlag;

volatile bool interupted = false;
volatile bool isHumanPresent = false;

int maxTimeout = 10; // Seconds

SCNokia5110 nokia(7,5,11,13,6);
SCLed lcdLed(PIN_DISPLAY_LED);
SCTimer timeoutTimer;
DS3231 myRTC;

char dowLookup[7][11] = {"MONTAG", "DIENSTAG", "MITTWOCH", "DONNERSTAG", "FREITAG", "SAMSTAG", "SONNTAG"};
char monthLookup[12][4] = {"JAN", "FEB", "MAR", "APR", "MAI", "JUN", "JUL", "AUG", "SEP", "OKT", "NOV", "DEZ"};


void setup() 
{
  Serial.begin(115200);
  pinMode(PIN_PIR, INPUT_PULLUP);
  Wire.begin();
  setRTC();
  nokia.begin();
  lcdLed.begin();
  timeoutTimer.set(5000);
  nokia.setFont("font_5x3");
  nokia.drawString((char *)"5110 FONT TEST SCREEN",0,16,true); 
  nokia.sendBuffer();
  analogWrite(PIN_DISPLAY_LED, 255);
  delay(150);
  timeoutTimer.start();
}

void loop() 
{
    nokia.clearBuffer();
    char buf[25];
    sprintf(buf,"%02d.%02d.%d", myRTC.getDate(), myRTC.getMonth(century), myRTC.getYear());
    nokia.drawString((char *)buf,0,8,true);
    sprintf(buf,"%02d:%02d:%02d", myRTC.getHour(h12Flag, pmFlag), myRTC.getMinute(), myRTC.getSecond());
    nokia.drawString((char *)buf,0,22,true);
    char temp[5];
    float temperature = myRTC.getTemperature();
    dtostrf(temperature,5,1,temp);
    nokia.drawString((char *)temp,0,32,true);
    nokia.drawString((char *)dowLookup[myRTC.getDoW()],0,0,true);
    char timer[10];
    sprintf(timer,"%i", timeoutTimer.getCurrentTimer());
    nokia.drawString((char *)timer,45,25,true);
    if(digitalRead(PIN_PIR) == HIGH)
    {
      nokia.drawString((char *)"MOTION!",40,0,true);
      lcdLed.fadeOut(1);
      timeoutTimer.start();
    } else {
      nokia.drawString((char *)"NO",40,0,true);
      lcdLed.fadeIn(1);
      timeoutTimer.update();
    }
    nokia.sendBuffer();
    
    if(timeoutTimer.isElapsed())
    {
      Serial.println("Going to sleep!");
      delay(50);
      goToSleep();
      delay(50);
      Serial.println("just woke up!");
    }
}

void setRTC()
{
  myRTC.setYear(24);
  myRTC.setMonth(1);
  myRTC.setDate(12);
  myRTC.setDoW(4);
  myRTC.setHour(21);
  myRTC.setMinute(24);
  myRTC.setSecond(0);
}

void goToSleep()
{
    attachInterrupt(digitalPinToInterrupt(PIN_PIR), wakeUp, RISING);//attaching a interrupt to pin d3
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
    sleep_enable();//Enabling sleep mode
    sleep_cpu(); //activating sleep mode
    sleep_disable(); //Wakeup here, disable sleep mode
  }

void wakeUp()
{
  detachInterrupt(digitalPinToInterrupt(PIN_PIR)); //Removes the interrupt from pin 3;
  interupted = true;
}

Try this before attachInterrupt() to clear any pending interrupts on pin 3:
EIFR |= (1<<INTF1);

Your code is vulnerable anyway to interrups which come in during the execution of your function goToSleep().

You can also look at the example here: arduino nano - Arudino receiving interrupt command BEFORE entering sleep mode causing it not to receive any interrupt commands in order to wake up - Arduino Stack Exchange

EDIT
typo

1 Like

Is 5 chars always enough?

If you already defined a buffer (buf), that you are not using for other purposes, why not use it here? And instead of "char timer[10]"?

What about using the "F" macro in your println()'s?

1 Like

Thanks! Works like a charm now! :slight_smile:

Good points!

You are right, 6 chars is it (-10.6 + termination character). My fault! :slight_smile:

When reusing a buffer should it be cleared with space chars before so I dont print the chars from the previous write operation?

F macro is going to be used! :wink:

Clearing the buffer should not be necessary, because sprintf() and its cousins terminate the string with a null character

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