Firstly I am using an Uno as part of my project.
I have a WDT that is used as a long delay (10 minutes) by using an incremental counter every 8 seconds, operating from an ISR.
This reduces the quiescent current for the battery operated circuit, however I want to use a wake switch on pin 2 so that a second ISR wakes the MCU.
Individually both ISR's work fine, but I would like to know what the consequences would be if the second ISR is triggered when in the WDT routine.
Does the second ISR jump into the WDT function at the point where the counter is running ? or does it jump to the main loop after the WDT function call ?
What happens if the second ISR triggers whilst the first ISR has been triggered and is servicing its function ?
Would I have to disable all interrupts when entering an ISR function.
This is a hypothetical question so no code needed.
Off the top of my head, the first ISR will run to completion, interrupts will then be re-enabled, and the second ISR will run.
An added complication if you have several interrupts on the go is priority. The 328P datasheet lists all the interrupts (section 12 of my datasheet). I could be wrong here, but if you are inside an ISR and 2 or more interrupts occur from different sources, then when you come out of the ISR, the order the new interrupts are processed is determined by their position in the vector table - i.e. lowest vector numbers gets handled first, then the next lowest.
The datasheet says:
The lowest addresses in the program memory space are by default defined as the Reset and Interrupt Vectors. The complete list of vectors is shown in ”Interrupts” on page 66. The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level. RESET has the highest priority, and next is INT0 – the External Interrupt Request 0.
An option on the 328P is to configure the WDT to generate an interrupt rather than a system reset. It's used in that configuration, mainly for battery operated setups, (with an 8 sec timeout) to bring the 328P out of sleep mode roughly every 8 seconds.
It is that very independence which is the crucial factor. The WDT has its own clock, so the rest of the MPU can be put into a deep sleep, thus saving power. The interrupt service routine generated from the WDT, with a maximum of 8 seconds, can be used to increment a counter in a while loop, waking the MPU after the count has finished.
I have seen figures of 25 - 30 uA for the WDT, including servicing the interrupt.
Great for battery or solar powered monitors.
I will just be using an Atmega328P with the oscillator crystal and caps, with 10uF cap and 100nF decouplers on the analogue and digital supplies.
Bare minimum.
The WDT can be set up to generate its own interrupt
Snippet of code:
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
while (uiSleepCounter < iPeriod)
{
// Turn of Brown Out Detection (low voltage). This is automatically re-enabled upon timer interrupt
sleep_bod_disable();
noInterrupts(); // Make sure Interrupts are turned off
// clear/set various flags
MCUSR = 0; // disable reset
WDTCSR = bit (WDCE) | bit(WDE); // set interrupt mode
// Now set the time out for the WDT
WDTCSR = bit (WDIE) | bit(WDP3) | bit(WDP0); // set WDIE, and 8 second delay
wdt_reset();
// Allow interrupts now
interrupts();
// And enter sleep mode as set above
sleep_cpu();
}
The sleep counter is incremented in the ISR and the period is set externally for any period of time, multiplied by 8 seconds that is required.