Getting crazy with Mega2560, sleep modes and interrupts

Hi to all.
I'm "almost" new to this forum (I signed up years ago but never used it, before).
I hope that someboidy could give me a hint.
I wrote a big sketch for Arduino UNO a couple of months ago, but very soon I found UNO's limits in terms of memory and avaliable pins. I wrote alot of skecthes for UNO before this moment, and never found that limit until a couple of weeks ago.
So I decided to use a Mega2560 for this specific device, instead.
Installed MEGA on the same box of UNO and connected all the pins.

My sketch was perfectly running on UNO before, and it still works for the new Mega, right now, excepted for its sleep-interrupt-wake-up function.

I got almost crazy, so I wrote a very simple sketch in order to test all the single steps.
I've to put Arduino in sleep mode and then let it wake-up every minute, after a certain amount of time or when a button is pressed (it depends upon certain external events).

All the interrupts seem to work well, when used as simple interrupts, but when the sketch puts Mega in sleep mode... it stops to work forever.
Mega does not wake up anymore.

This sketch works normally if I delete the "sleep mode" related lines, the interrupts are correctly received and the LEDs change their state, but does not, when Arduino is put in sleep mode.
It "dies" literally, in this case, and there is not any chance to wake it up.

I never use the 2560's internal resistors with the "input_pullup" option, as I connect a 47K resistor for each button vs. ground and the button work flawlessly (as always).
All the buttons are connected togheter via diodes in order to obtain an unique HIGH state to be connected to pin 3, and -of course- this solution works perfectly as always with UNO and 2560.


#include <DS3232RTC.h>
#include <Streaming.h>
#include <Wire.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

const byte ledPin = 9;
const byte ledRed = 10;
const byte interruptPin = 3;
const byte interruptRTC = 2;
volatile byte state = LOW;
volatile byte state1 = HIGH;
bool RTCInterruptDetected=false;
int cycleNum=0;

void setup() {

Serial.begin(9600);
Serial.println("Serial port OK");

pinMode(ledPin, OUTPUT);
pinMode(ledRed, OUTPUT);  
pinMode(interruptPin, INPUT);
pinMode(interruptRTC, INPUT);
Serial.println(" starting to set RTC params ");
RTC.alarm(ALARM_1); 
RTC.alarm(ALARM_2);
RTC.squareWave(SQWAVE_NONE);  

RTC.alarmInterrupt(ALARM_1, false); 
RTC.alarmInterrupt(ALARM_2, true);  .
RTC.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0);   
Serial.println(" RTC params set ");  

attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);    
attachInterrupt(digitalPinToInterrupt(interruptRTC), blink1, FALLING); 

}

void loop() {
digitalWrite(ledPin, state);
digitalWrite(ledRed, state1);
if (RTCInterruptDetected) {
RTCInterruptDetected = false;
cycleNum++;
Serial.print(" Entered in IF, cycle #: ");
Serial.println(cycleNum);
Serial.println(" Entered in IF, deleting ALARM1 e ALARM2 in RTC");
RTC.alarm(ALARM_1);
RTC.alarm(ALARM_2);
Serial.println(" Entered in IF resetting RTC parameters");
RTC.squareWave(SQWAVE_NONE); /
RTC.alarmInterrupt(ALARM_1, false);
RTC.alarmInterrupt(ALARM_2, true);
RTC.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0);
Serial.println(" Entered in IF resetting interrupts paramneters");
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptRTC), blink1, FALLING);
}
Serial.println("setting Arduino's params for the sleep mode");
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
delay(100);

Serial.println("next line will put Arduino in sleep mode");
delay(100);
sleep_mode();   

Serial.println("Woke Up");
sleep_disable();
Serial.println("sleep bit disabled");

}

void blink() {
state = !state;
Serial.println(" Button Interrupt detected");

}

void blink1() {
detachInterrupt(digitalPinToInterrupt(interruptRTC));
RTCInterruptDetected = true;
state1 = !state1;
}

The Mega doesn't wake up from power down sleep with every type of interrupt. On pins 2 and 3 only level interrupts can awake the processor from power down sleep.

1 Like

I am doing a low power excursion just now so this caught my eye.

From


I see right away
On UNO, you can wake it with LOW, FALLING, or RISING of external interrupt 0 and 1. 
On MEGA, you can only do LOW, not FALLING or RISING. 

which come as a surprise but file under "good to know".

a7

1 Like

thank you very much both!
Of course these answers stop my headache.

Another, last question: using other pins (excluding 2 and 3 --> interrupts 0 and 1), is it possible to wake up MEGA2560 using the other states (let's say a RISING)?

Because a LOW could work with the RTC section of my circuit (DS3231 goes to LOW activating a whatever alarm) but all the other sections of my circuit send a high level when an interrupt is required.
I'd avoid to make another PCB or just weld a transistor and a couple of resistors to other components, in order to correct this behaviour (implementing a NOT port).

It would be much easier to connect the 2nd interrupt to another pin of Arduino...

...sorry.

I've read the whole thread.
Of course the answer is inside it.
I'm correcting right now.

Thank you again!

Yes, using INT0 to INT3 (attention: that are processor names not Arduino IDE numbers, which are different on the Mega!). So you have to use any of pin 18 to pin 21 and it should work (according to the datasheet).

1 Like

I'm glad my old post is useful. I can't remember the details myself. I'll search the forum if I encounter this problem :wink:

1 Like

thank you all.

Your suggestions and infos are really precious. I installed an Arduino UNO again in my device.
Probably I will keep this project "as is" right now, without implementing other functions (as I already reached UNO's memory limits), studying another version, with NOT ports for the next version, improved with more functions, on MEGA2560 platform.

In any case i will try to use the 18...21 ports with all the possible interrupt states in the afternoon, on MEGA2560 :wink:

thank you all again!

TESTED, they work.

I tested port 18 AND 19 on Arduino MEGA2560, few minutes ago, to see if interrupts generated on those ports work WAKE UP the board with all the states.

I can confirm.
Ports 18 and 19 work correctly, waking up Arduino Mega 2560 with RAISING, LOW, HIGH, CHANGE and FALLING parameters.

Ports 20 and 21 do not (I don't understand why, at the moment).

I don't know the related interrupts numbers right now, but using: attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
the sketch works without problems (maybe that studying the CPU Reference it will be possibile to find the related numbers)

The sleep mode I invoked testing them was SLEEP_MODE_PWR_DOWN
( set_sleep_mode(SLEEP_MODE_PWR_DOWN); )

...my problem ends here.

All the interrupt pins in MEGA2560 work without problems, detecting all the five modes, but they cannot wake up the board from the sleep state with HIGH, RISING, FALLING and CHANGE.
They wake up the board only detecting a LOW state.

As far as I see, only pins 18 and 19 work correctly with all the five parameters.

Hey thanks for following through with tests. I'm sure someone else will find our discussion useful down the road :slight_smile:

FYI, that project that I was working on required pins 18/19 to be serial1 and 20/21 to be I2C so I couldn't use them although they work. Did you have any I2C library included or devices connected when you were testing 20/21?

1 Like

In the real device that I'm building, the 20-21 ports are connected to the SDA/SCL ports of a DS3231 clock.
So I'm already using them exactly like you, but I used another Arduino Mega 2560 (an original board bought from arduino.cc) without any other connection to test all the ports.

I did a test exclusively to confirm the possibility to use the interrupts to wake up Arduino Mega2560 in every possible manner.

wait wait wait...
Yes, the Mega2560 was absolutely dedicated to this test BUT the sketch included these libraries...

#include <DS3232RTC.h> // GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks
#include <Streaming.h> // StreamingĀ |Ā Arduiniana
#include <Wire.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

And -of course- (maybe) the DS3231RTC could have invalidated the test!

I foolishly did a quick&dirty cut/paste from another sketch, modyfing just some lines to make the test!

So without the I2C device library pins 20/21 interrupts are working as they should?

I do a lot of copy pasting. It's so easy you use one thing as a template to create another. But, there's always some unintended copies. Just a couple days ago I was designing a simple breakout board. I decided to start with one of my existing boards and delete all that I don't need. What's wrong with this subtractive approach, in theory?
I ended up with a design that had issues in the file so EAGLE couldn't open it with forward/backward reference between board and schematic. I had to sift through both board and schematic files to delete the inconsistent part. In reality, subtractive approach sucks because theory is just theory. Anything you copy paste has a mileage on it. The more you do it, the more likely it because corrupted.