Skip to content

Suggestion for improving "sleep" time accuracy. #112

@MojaveTom

Description

@MojaveTom

This suggestion is similar to issue #111 in that a flag is to be set when the watch dog timer interrupt service routine is executed, but it this case, it is used to re-sleep the CPU if it is awakened by some other interrupt to ensure that the power saving function does not exit before the WDT interrupt happens. As I see it, the problem is that when the CPU wakes up in powerDown it doesn't know which interrupt awakened it, so it just assumes that it was the WDT. Since the interrupt service routine for the WDT is in that same module, it is easy to add a flag that is set when the WDT interrupt is entered, and cleared when the powerDown function first sleeps the CPU. The CPU is just put back to sleep if it is awakened and the wdtFinished flag is still false. When the wdtFinished flag is true, the powerDown function exits as usual.

With this modification, the time in the powerDown function is not short circuited by an unexpected interrupt.

// add new wdtFinished flag class variable
volatile bool LowPowerClass::wdtFinished;

...

void	LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
{
	if (adc == ADC_OFF)	ADCSRA &= ~(1 << ADEN);

	if (period != SLEEP_FOREVER)
	{
		wdt_enable(period);
		WDTCSR |= (1 << WDIE);
	}
	if (bod == BOD_OFF)
	{
		wdtFinished = false;        //  added code
		while (!wdtFinished)        //  added code
		#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168P__)
			lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
		#else
			lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
		#endif
		wdtFinished = false;        //  added code
	}
	else
	{
		wdtFinished = false;        //  added code
		while (!wdtFinished)        //  added code
			lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
		wdtFinished = false;        //  added code
	}

	if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}

...

 // set wdt finished flag
ISR (WDT_vect)
{
	// WDIE & WDIF is cleared in hardware upon entering this ISR
	wdt_disable();
	LowPowerClass::wdtFinished = true;        //  added code
}

The powerSave, powerStandby, and powerExtStandby functions could be modified in a similar manner.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions