Just a simple newbie ISR problem ;-)

Hi,

I have read pretty much in this forum Gammon Forum : Electronics : Microprocessors : Interrupts but still got problem with waking up a sleeping Arduino. Must have missed something in that tutorial.

Here is the code:

#include <avr/sleep.h>                                 

#define SLEEP_PIN	2
#define WAKEUP_PIN	3

void setup()
{
	Serial.begin(115200);

	pinMode(SLEEP_PIN, INPUT_PULLUP);
	pinMode(WAKEUP_PIN, INPUT_PULLUP);

	attachInterrupt(digitalPinToInterrupt(SLEEP_PIN), sleep, FALLING);
}

void wakeUp() {
	sleep_disable();
	noInterrupts();
	detachInterrupt(digitalPinToInterrupt(WAKEUP_PIN));
	attachInterrupt(digitalPinToInterrupt(SLEEP_PIN), sleep, FALLING);
	interrupts();
}

void sleep() {
	noInterrupts();
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	detachInterrupt(digitalPinToInterrupt(SLEEP_PIN));
	attachInterrupt(digitalPinToInterrupt(WAKEUP_PIN), wakeUp, FALLING);
	sleep_enable();
	interrupts();
	sleep_cpu();
	// Sleeping... 
}

void loop()
{
	for (int i = 0; i < 10; i++) {
		Serial.print("idle ");
		Serial.println(i);
		delay(1000);
	}
	sleep();
}

I’m able to do sleep and wakeup interrupts during the first idle 10 sec countdown.
But when sleep is called after the for-loop, the Arduino goes to sleep and I’m not able to wake it up
anymore with the wakeup-interruption.

Thanks

No comments? I thought this issue was a walk in the park for most forum users. :o
Adding a wiring diagram in case that would make things easier.

If you're using something like that shown in image that provides regulated 5v, that should go to the Vcc pin, not Raw. Raw goes through the on-board voltage regulator, so if you feed it 5v, the chip is getting significantly less than 5v.

But yeah, I don't see the problem in the code, and I don't think that that issue would be related, unless those resistors are very low value indeed (the buttons are being pulled up to +5v, but if powered off raw, Vcc is only in the high 3.something range - if the resistor values are high, the protection diodes will save you (you can put 1mA through them and be fine) but if the resistors are lower value, you could put enough current through them to trash the pin.

I'm frankly not used to using attach/detach interrupt. I consider those to be heretical - I prefer manipulating registers and writing proper ISRs instead.

I forgot to mention that the Arduino is a 3.3V version and I connected it to RAW on the diagram because that is exactly how it’s setup when I test the code. I just want to be accurate.

The resistors are 10K.

Wiring is incorrect.

If you supply a voltage to raw, it goes through the regulator, so the voltage the chip runs on is lower. But you are pulling the button pins up to the voltage you're feeding to raw.

This is wrong, they should be pulled up to the chip's operating voltage, not higher.

If that supply is putting out 3.3v, the board is running at well under that; if supply is putting out 5, you should not be pulling the button pins up to the board is likely running at 3.3, but you're trying to pull the button pins up to 5.

Hmm, I'm not sure I understand your point.
The drawing shows 3.3V at upper "power line" and 5V at the lower power line. So I'm feeding the buttons with 3.3V and the RAW with 5V.

Sorry about the mess :confused:

I just tried to remove all the detach-attach code and now it works.
I’m actually fine with that solution since the detach-attach isn’t needed in my full scale project.

This is the working simplified code:

#include <avr/sleep.h>                                 

#define SLEEP_PIN	2
#define WAKEUP_PIN	3

void setup()
{
	Serial.begin(115200);

	pinMode(SLEEP_PIN, INPUT_PULLUP);
	pinMode(WAKEUP_PIN, INPUT_PULLUP);

	attachInterrupt(digitalPinToInterrupt(SLEEP_PIN), sleep, FALLING);
	attachInterrupt(digitalPinToInterrupt(WAKEUP_PIN), wakeUp, FALLING);
}

void wakeUp() {
	sleep_disable();
}

void sleep() {
	noInterrupts();
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	sleep_enable();
	interrupts();
	sleep_cpu();
	// Sleeping... 
}

void loop()
{
	for (int i = 0; i < 10; i++) {
		Serial.print("idle ");
		Serial.println(i);
		delay(1000);
	}
	sleep();
}

But doesn't that make the sleep button be able to wake it up as well (but not landing in wakeUp())?

The idle counter doesn't start when I press sleep button during sleep so it seems like it's still sleeping.
Same thing if I press wake up twice in a row. No problem with unexpected behaviour.