[EDIT]
I found a work-around that does what I need, see next reply
[/EDIT]
It's been a while but I have a result. It's not perfect though.
I'm using an Arduino Pro Mini and the Narcoleptic library. I removed the power regulator and power LED from the Mini.
By using a cycle and awake time I can power my "external system" up and down at fairly precise intervals. This drastically reduces the average power consumption. See images below for results.
So it seems to be working just fine like this. However as you can see in my code below I'm setting a cycle start time:
cycle_starttime = millis() + Narcoleptic.millis();
The Arduino millis increment during awake time and narcoleptic millis are calculated by the library based on the sleep time. So when adding these toghether the result is close to millis in real time.
The thing is that (first) 'millis() + Narcoleptic.millis()' wil be greater then 4294967295 at some point and a rollover will occur. At some point millis() and Narcoleptic.millis() will also rollover.
I have a strong feeling this is going to seriously mess things up.
To avoid rollovers altogether I tried to invoke a watchdog timeout by:
if(millis() + Narcoleptic.millis() > 100000) // 24*60*60*1000 = 86 400 000 for 24 hours
{
//wdt_disable(); // Disabling and delaying
//delay(3000); // doesn't work either
wdt_enable(WDTO_1S);
while(1){};
}
So my questions at this point:
-- Can I even use the watchdog timer, might there be a conflict with the Narcoleptic library?
-- If I can use the WDT, how?
-- If I can't use the WDT, what could be another approach in this case?
Thanks for reading!
Code:
#include <avr/wdt.h>
#include <Narcoleptic.h>
#define led 13 // Onboard LED
#define external_system_power 2 // Pin connected to a transistor that switches external system on/off
#define external_system_signal 3 // As long as the external system keeps this pin high the module will not go into sleep mode
//===============================
// CYCLE AND WAKE TIME
const int cycle_time_min = 1; // Cycle time in minutes, system will be awake at every start of new cycle
const int awake_time_sec = 20; // Time in seconds that the system will be awake at the start of a new cycle
// Cycle time correction:
// There is a +4.8333% error on the cycle time, so if 100 sec is calculated, the cycle takes 104.8 seconds.
// So the correction factor is 100 / 104.8333 = 0,95389537484749597694625658068572
// The error seems to depend on temperature, +4.8333% @ 22°C and probably supply voltage(?)
// The lower the temperature, the smaller the error. Not significant enough to program for
const unsigned long cycle_time_ms = 1000UL * 60 * cycle_time_min * 0.95389537; // Cycle time in milliseconds, addition UL needed to calculate as unsigned long
const unsigned long awake_time_ms = 1000UL * awake_time_sec; // Awake time in milliseconds, no correction needed: awake is time relatively short
unsigned long cycle_starttime; // Marks the start time of a new cycle in milliseconds
void setup()
{
Narcoleptic.disableTimer1();
Narcoleptic.disableTimer2();
Narcoleptic.disableWire();
Narcoleptic.disableSPI();
ADCSRA &= ~(1<<ADEN); // Disable ADC
ACSR = (1<<ACD); // Disable the analog comparator
// ATmega48/88/168/328
DIDR0 = B00111111; // Disable digital input buffers on all ADC0-ADC5 pins
DIDR1 = (1<<AIN1D)|(1<<AIN0D); // Disable digital input buffer on AIN1/0
pinMode(external_system_power, OUTPUT); // Switches external power via transistor
digitalWrite(external_system_power, 0);
pinMode(external_system_signal, INPUT); // Reads stay awake signal from external system
pinMode(led, OUTPUT);
digitalWrite(led,LOW);
}
void loop()
{
cycle_starttime = millis() + Narcoleptic.millis(); // Mark the starttime of the cycle
// Wake ========================================================================
digitalWrite(led, 1); // Indicate power ON
digitalWrite(external_system_power, 1); // Switch ON external system
while( ((millis() + Narcoleptic.millis()) - cycle_starttime) < awake_time_ms // Stay awake for the awake time
|| digitalRead(external_system_signal)) // OR Stay awake as long as external_system_signal is high
{
// Stay awake
}
digitalWrite(led, 0); // Indicate power OFF
digitalWrite(external_system_power, 0); // Switch OFF external system
// Sleep =======================================================================
while( ((millis() + Narcoleptic.millis()) - cycle_starttime) < cycle_time_ms ) // Sleep until the end of the cycle time
{
Narcoleptic.delay(1000);
}
} // End loop