Arduino (nano) hangs on second time of loop when interrupt is intercepted

Hi to all,
I’m using the library MySensors ( https://www.mysensors.org/ ) with an Arduino Nano.
I’m realizing a clock with a 7 segments display, liting if movement from a PIR is detected.

I will port this project on battery, so I need to use sleep and shutdown all peripherals.

There is a PIR, if movement is detected the clock lits on.

All works without problem if I declare HIGH the Arduino PIN for feed 5V to the RTC and I leave HIGH it for all time.

But, I would use the PIN to feed (or no feed at all) power to the RTC, so I put it OFF and when need I put it ON.

After editing my code, Arduio enters without problem in the LOOP. For only one time the loop is executed without problem. At second time (after the second wake up) arduino hangs.

It prints

Request_sync vale 0
Detected movement vale 1
PIN_RTC_VCC è in stato 0

And hangs for ever.

I did put the multimeter. The code when PIR is intercepted, PIN goes to high (about 4.6V) and… stop. Hangs there, with PIN high. But I repeat, only at second loop. First one goes very well.

For the moment I did disable the watchdog. If I restore the watchdog, of course it reset entire Arduino.

This is my code. Could you help me to identify the issue?

/**
 * Clock with DS3231
 * For version, see changelog and / or sketch version
 * 
 * CHANGELOG
 * 
 * * = 0.4 = '
 * Introduced sleep
 * 
 * * = 0.3 = *
 * Introduced PIR
 * 
 * * = 0.2 = *
 * * Introduced MAX7219
 * 
 * * = 0.1 = *
 * * First release
 * 
 */ 

// Enable debug prints
#define MY_DEBUG
//#define MY_DEBUG_VERBOSE_SIGNING
#define MY_SPLASH_SCREEN_DISABLED
#define MY_DISABLE_SIGNAL_REPORT
#define MY_BAUD_RATE 57600

// Enable and select radio type attached
#define MY_RADIO_NRF24
#define MY_RF24_CHANNEL 83
#define MY_TRANSPORT_WAIT_READY_MS (5000)

#define MAX_RETRY_SEND_BEFORE_DELAY 30 // after this try, it will call delay

#define MY_PARENT_NODE_ID 0
#define MY_PARENT_NODE_IS_STATIC


#define MY_NODE_ID 100    //"DS3231 CLOCK"
#define MY_SKETCH_NAME    "DS3231 CLOCK"
// ====================================

#define MY_SKETCH_VERSION "0.5"

#include <MySensors.h>
#include <avr/wdt.h>
#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include <Bounce2.h>
#include "LedControl.h"

// Instantiate a Bounce object
Bounce debouncer = Bounce(); 

const byte interrupt_sync_pin = 2;
const byte interrupt_pir_pin = 3;
volatile bool request_sync = false;
volatile bool detected_movement = false;

#define PIN_DATA_IN 8
#define PIN_CLK     6
#define PIN_LOAD    7
#define NUM_MAX7219 1

#define PIN_RTC_VCC 17

/*
 Now we need a LedControl to work with.
 */
LedControl lc = LedControl(PIN_DATA_IN , PIN_CLK , PIN_LOAD , NUM_MAX7219);


/**
 * Presentation of the sketch.
 * Send name of sketch
 * 
 * @since 0.1
 */

void presentation() {
  // Send the sketch version information to the gateway
  sendSketchInfo(MY_SKETCH_NAME , MY_SKETCH_VERSION);
  
}


/**
 * Setup of sketch.
 * 
 * @since 0.1
 * 
 */

void setup() {

  //wdt_enable(WDTO_2S);

  // activate the interrupt pin
  pinMode(interrupt_sync_pin, INPUT_PULLUP);
  pinMode(interrupt_pir_pin , INPUT_PULLUP);

  // activate vcc pin for RTC
  pinMode(PIN_RTC_VCC , OUTPUT);
  //digitalWrite(PIN_RTC_VCC , HIGH);
  digitalWrite(PIN_RTC_VCC , LOW);

  // After setting up the button, setup Bounce object
  debouncer.attach(interrupt_sync_pin);
  debouncer.interval(500);
  
  // attach the interrupt
  attachInterrupt(digitalPinToInterrupt(interrupt_sync_pin), syncTime, FALLING);
  
}

/**
 * Setup the MAX7219
 * 
 * @since 0.2
 */

void setupMax7219() {

  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,5);
  /* and clear the display */
  lc.clearDisplay(0);
  
}

/**
 * Disable the MAX7219
 * 
 * @since 0.3
 */

void disableMax7219() {

  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,true);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,0);
  /* and clear the display */
  lc.clearDisplay(0);
  
}

/**
 * Our interrupt for syncing time
 * 
 * @since 0.1
 */
void syncTime() {

  request_sync = true;
  
}

/**
 * Our interrupt for movememnt detected
 * 
 * @since 0.3
 */
void detectedMovement() {

  detected_movement = true;
  
}

/**
 * Receive the time and sync the RTC
 * 
 * @param unsigned long the time got from controller
 * 
 * @since 0.1
 */

// This is called when a new time value was received
void receiveTime(unsigned long controller_time) {

  digitalWrite(PIN_RTC_VCC , HIGH);
  wait(1000);
  // Ok, set incoming time 
  Serial.print("Time value received: ");
  Serial.println(controller_time);
  RTC.set(controller_time); // this sets the RTC to the time from controller - which we do want periodically
  digitalWrite(PIN_RTC_VCC , LOW);
  wait(1000);
  
}

/**
 * Our loop.
 * 
 * @since 0.1
 */

void loop() {

  switch ( sleep(digitalPinToInterrupt(interrupt_pir_pin), RISING, 0) ) {
    
    case MY_WAKE_UP_BY_TIMER:
      Serial.println("Svegliato dal tempo...");
      request_sync = true;
      break;
    case MY_SLEEP_NOT_POSSIBLE:
      Serial.println("Unable to sleep ;-(");
      break;
    default:
      detected_movement = true;

  }

  Serial.print("Request_sync vale ");
  Serial.println(request_sync);

  Serial.print("Detected movement vale ");
  Serial.println(detected_movement);

  if ( request_sync == true ) {

    requestTime();
    request_sync = false;
     
  }

  if ( detected_movement == true ) {

    Serial.print("PIN_RTC_VCC è in stato ");
    Serial.println(digitalRead(PIN_RTC_VCC));

    // ARDUINO HANGS HERE AT SECOND TIME!

    // the function to get the time from the RTC
    // we need to get the time 'case we are in sleep
    digitalWrite(PIN_RTC_VCC , HIGH);
    wait(1000);
    wdt_reset();
    setSyncProvider(RTC.get);
    wdt_reset();
    Serial.println("Movimento intercettato!");
    setupMax7219();

    int i = 0;

    for ( i = 0; i < 6; i++ ) {

      printTime();
      wait(1000);
      
    }

    printDate();
    wait(2000);

    disableMax7219();
    
    detected_movement = false;
    digitalWrite(PIN_RTC_VCC , LOW);
      
  }
}

/**
 * Print the hour
 * 
 * @since 0.2
 */
void printTime() {

  static bool dp = false;

  int temp_time , digit_1 , digit_2;

  temp_time = hour();

  digit_2 = temp_time%10;
  digit_1 = (temp_time/10)%10;

  lc.setChar(0 , 6 , digit_1 , dp);
  lc.setChar(0 , 5 , digit_2 , dp);

  temp_time = minute();

  digit_2 = temp_time%10;
  digit_1 = (temp_time/10)%10;

  lc.setChar(0 , 4 , digit_1 , dp);
  lc.setChar(0 , 3 , digit_2 , dp);

  temp_time = second();

  digit_2 = temp_time%10;
  digit_1 = (temp_time/10)%10;

  lc.setChar(0 , 2 , digit_1 , false);
  lc.setChar(0 , 1 , digit_2 , false);

  //dp = !dp;
  
}

/**
 * Print the date
 * 
 * @since 0.3
 */

 void printDate() {

  static bool dp = false;

  int temp_time , digit_1 , digit_2 , digit_3 , digit_4;

  temp_time = day();

  digit_2 = temp_time%10;
  digit_1 = (temp_time/10)%10;

  lc.setChar(0 , 7 , digit_1 , dp);
  lc.setChar(0 , 6 , digit_2 , dp);

  temp_time = month();

  digit_2 = temp_time%10;
  digit_1 = (temp_time/10)%10;

  lc.setChar(0 , 5 , digit_1 , dp);
  lc.setChar(0 , 4 , digit_2 , dp);

  temp_time = year();

  digit_4 = temp_time%10;
  digit_3 = (temp_time/10)%10;
  digit_2 = ((temp_time/10)/10)%10;
  digit_1 = (((temp_time/10)/10)/10)%10;

  lc.setChar(0 , 3 , digit_1 , false);
  lc.setChar(0 , 2 , digit_2 , false);
  lc.setChar(0 , 1 , digit_3 , false);
  lc.setChar(0 , 0 , digit_4 , false);

  //dp = !dp;
  
}

The issue coming from PIN going from LOW to HIGH.

I did not edit the sketch, only give 5V directly to the RTC and all goes as expected.

I did try also adding a CAP between pin and GND (10 and 22uF) but doesn't solve anything.

I'm confused, but one step at a time. Unless I'm missing some of the code I only see one interrupt attached in line 113 and that states FALLING so in theory nothing should happen when the pin goes from low to high. I suspect a switch bounce is responsible for the trigger. Then your ISR just sets a flag. Okay, no problem with that. Immediately after this function is, by your comments, the ISR for another interrupt for detected movement. the function detectedMovement() is not referenced anywhere else in your posted code.

Is the code complete? It appears your problems may reside with unfinished code rather than syntax or logic.

dkw

DKWatson, thank you for your help. Yes, the code is complete.

You are right, the detectedMovement() is not anymore called, cause from MySensors library I can do sleep the ATMEGA until an interrrupt occurs.

I.e.

switch ( sleep(digitalPinToInterrupt(interrupt_pir_pin), RISING, 0) ) {

This is other interrupt. It sleeps until there is an interrupt.

If I push the button, interrupt evoke from this. If I pass my hand on PIR, it works.

The return for sleep is:

case MY_WAKE_UP_BY_TIMER:
      Serial.println("Svegliato dal tempo...");
      request_sync = true;
      break;
    case MY_SLEEP_NOT_POSSIBLE:
      Serial.println("Unable to sleep ;-(");
      break;
    default:
      detected_movement = true;

Btw, I suspect a problem with DS3231 module (ad found in other topics seems it has some issues with sleep or so?). I did try with Chronodot and seems all ok (but I need to buy a CR1632 to test more and more)