WIP: First commit for sleep mode
This commit is contained in:
parent
4e5c8f96e0
commit
0901f93394
|
@ -0,0 +1,110 @@
|
|||
#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();
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
#include <avr/sleep.h>
|
||||
|
||||
/* Sleep Demo Serial
|
||||
* -----------------
|
||||
* Example code to demonstrate the sleep functions in an Arduino.
|
||||
*
|
||||
* use a resistor between RX and pin2. By default RX is pulled up to 5V
|
||||
* therefore, we can use a sequence of Serial data forcing RX to 0, what
|
||||
* will make pin2 go LOW activating INT0 external interrupt, bringing
|
||||
* the MCU back to life
|
||||
*
|
||||
* there is also a time counter that will put the MCU to sleep after 10 secs
|
||||
*
|
||||
* NOTE: when coming back from POWER-DOWN mode, it takes a bit
|
||||
* until the system is functional at 100%!! (typically <1sec)
|
||||
*
|
||||
* Copyright (C) 2006 MacSimski 2006-12-30
|
||||
* Copyright (C) 2007 D. Cuartielles 2007-07-08 - Mexico DF
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
int wakePin = 2; // pin used for waking up
|
||||
int sleepStatus = 0; // variable to store a request for sleep
|
||||
int count = 0; // counter
|
||||
|
||||
void wakeUpNow() // here the interrupt is handled after wakeup
|
||||
{
|
||||
// execute code here after wake-up before returning to the loop() function
|
||||
// timers and code using timers (serial.print and more...) will not work here.
|
||||
// we don't really need to execute any special functions here, since we
|
||||
// just want the thing to wake up
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(wakePin, INPUT);
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
/* Now it is time to enable an interrupt. In the function call
|
||||
* attachInterrupt(A, B, C)
|
||||
* A can be either 0 or 1 for interrupts on pin 2 or 3.
|
||||
*
|
||||
* B Name of a function you want to execute while in interrupt A.
|
||||
*
|
||||
* C Trigger mode of the interrupt pin. can be:
|
||||
* LOW a low level trigger
|
||||
* CHANGE a change in level trigger
|
||||
* RISING a rising edge of a level trigger
|
||||
* FALLING a falling edge of a level trigger
|
||||
*
|
||||
* In all but the IDLE sleep modes only LOW can be used.
|
||||
*/
|
||||
|
||||
attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
|
||||
// wakeUpNow when pin 2 gets LOW
|
||||
}
|
||||
|
||||
void sleepNow() // here we put the arduino to sleep
|
||||
{
|
||||
/* Now is the time to set the sleep mode. In the Atmega8 datasheet
|
||||
* http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
|
||||
* there is a list of sleep modes which explains which clocks and
|
||||
* wake up sources are available in which sleep mode.
|
||||
*
|
||||
* In the avr/sleep.h file, the call names of these sleep modes are to be found:
|
||||
*
|
||||
* The 5 different modes are:
|
||||
* SLEEP_MODE_IDLE -the least power savings
|
||||
* SLEEP_MODE_ADC
|
||||
* SLEEP_MODE_PWR_SAVE
|
||||
* SLEEP_MODE_STANDBY
|
||||
* SLEEP_MODE_PWR_DOWN -the most power savings
|
||||
*
|
||||
* For now, we want as much power savings as possible, so we
|
||||
* choose the according
|
||||
* sleep mode: SLEEP_MODE_PWR_DOWN
|
||||
*
|
||||
*/
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
|
||||
|
||||
sleep_enable(); // enables the sleep bit in the mcucr register
|
||||
// so sleep is possible. just a safety pin
|
||||
|
||||
/* Now it is time to enable an interrupt. We do it here so an
|
||||
* accidentally pushed interrupt button doesn't interrupt
|
||||
* our running program. if you want to be able to run
|
||||
* interrupt code besides the sleep function, place it in
|
||||
* setup() for example.
|
||||
*
|
||||
* In the function call attachInterrupt(A, B, C)
|
||||
* A can be either 0 or 1 for interrupts on pin 2 or 3.
|
||||
*
|
||||
* B Name of a function you want to execute at interrupt for A.
|
||||
*
|
||||
* C Trigger mode of the interrupt pin. can be:
|
||||
* LOW a low level triggers
|
||||
* CHANGE a change in level triggers
|
||||
* RISING a rising edge of a level triggers
|
||||
* FALLING a falling edge of a level triggers
|
||||
*
|
||||
* In all but the IDLE sleep modes only LOW can be used.
|
||||
*/
|
||||
|
||||
attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
|
||||
// wakeUpNow when pin 2 gets LOW
|
||||
|
||||
sleep_mode(); // here the device is actually put to sleep!!
|
||||
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
|
||||
|
||||
sleep_disable(); // first thing after waking from sleep:
|
||||
// disable sleep...
|
||||
detachInterrupt(0); // disables interrupt 0 on pin 2 so the
|
||||
// wakeUpNow code will not be executed
|
||||
// during normal running time.
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// display information about the counter
|
||||
Serial.print("Awake for ");
|
||||
Serial.print(count);
|
||||
Serial.println("sec");
|
||||
count++;
|
||||
delay(1000); // waits for a second
|
||||
|
||||
// compute the serial input
|
||||
if (Serial.available()) {
|
||||
int val = Serial.read();
|
||||
if (val == 'S') {
|
||||
Serial.println("Serial: Entering Sleep mode");
|
||||
delay(100); // this delay is needed, the sleep
|
||||
//function will provoke a Serial error otherwise!!
|
||||
count = 0;
|
||||
sleepNow(); // sleep function called here
|
||||
}
|
||||
if (val == 'A') {
|
||||
Serial.println("Hola Caracola"); // classic dummy message
|
||||
}
|
||||
}
|
||||
|
||||
// check if it should go to sleep because of time
|
||||
if (count >= 10) {
|
||||
Serial.println("Timer: Entering Sleep mode");
|
||||
delay(100); // this delay is needed, the sleep
|
||||
//function will provoke a Serial error otherwise!!
|
||||
count = 0;
|
||||
sleepNow(); // sleep function called here
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue