arduino_projects/sleep/sleep.ino

111 lines
2.9 KiB
C++

#include <SPI.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
// Seconds to wait before a new sensor reading is logged.
#define LOGGING_FREQ_SECONDS 60
// Number of times to sleep (for 8 seconds) before
// a sensor reading is taken and sent to the server.
// Don't change this unless you also change the
// watchdog timer configuration.
#define MAX_SLEEP_ITERATIONS LOGGING_FREQ_SECONDS / 8
int sleepIterations = 0;
volatile bool watchdogActivated = false;
// Define watchdog timer interrupt.
ISR(WDT_vect) {
// Set the watchdog activated flag.
// Note that you shouldn't do much work inside an interrupt handler.
watchdogActivated = true;
}
// Put the Arduino to sleep.
void sleep() {
// Set sleep to full power down. Only external interrupts or
// the watchdog timer can wake the CPU!
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Turn off the ADC while asleep.
power_adc_disable();
// Enable sleep and enter sleep mode.
sleep_mode();
// CPU is now asleep and program execution completely halts!
// Once awake, execution will resume at this point.
// When awake, disable sleep mode and turn on all devices.
sleep_disable();
power_all_enable();
}
// Take a sensor reading and send it to the server.
void logSensorReading() {
// Take a sensor reading
int reading = 99999;
// Connect to the server and send the reading.
Serial.print(F("Sending measurement: ")); Serial.println(reading, DEC);
}
void setup_interrupts(void) {
// Setup the watchdog timer to run an interrupt which
// wakes the Arduino from sleep every 8 seconds.
// Note that the default behavior of resetting the Arduino
// with the watchdog will be disabled.
// This next section of code is timing critical, so interrupts are disabled.
// See more details of how to change the watchdog in the ATmega328P datasheet
// around page 50, Watchdog Timer.
noInterrupts();
// Set the watchdog reset bit in the MCU status register to 0.
MCUSR &= ~(1<<WDRF);
// Set WDCE and WDE bits in the watchdog control register.
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Set watchdog clock prescaler bits to a value of 8 seconds.
WDTCSR = (1<<WDP0) | (1<<WDP3);
// Enable watchdog as interrupt only (no reset).
WDTCSR |= (1<<WDIE);
// Enable interrupts again.
interrupts();
Serial.println(F("Setup complete."));
}
void setup(void) {
Serial.begin(115200);
setup_interrupts();
}
void loop(void)
{
// Don't do anything unless the watchdog timer interrupt has fired.
if (watchdogActivated)
{
watchdogActivated = false;
// Increase the count of sleep iterations and take a sensor
// reading once the max number of iterations has been hit.
sleepIterations += 1;
if (sleepIterations >= MAX_SLEEP_ITERATIONS) {
// Reset the number of sleep iterations.
sleepIterations = 0;
// Log the sensor data (waking the CC3000, etc. as needed)
logSensorReading();
}
}
// Go to sleep!
sleep();
}