From 0901f93394f433c7e2fcb8a8ce1c3e777396ac79 Mon Sep 17 00:00:00 2001 From: Txus Ordorika Date: Tue, 5 Mar 2019 00:04:04 +0100 Subject: [PATCH] WIP: First commit for sleep mode --- sleep/sleep.ino | 110 +++++++++++++++++++++++++++++ sleep/sleep.ino.old | 164 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 sleep/sleep.ino create mode 100644 sleep/sleep.ino.old diff --git a/sleep/sleep.ino b/sleep/sleep.ino new file mode 100644 index 0000000..c3b900f --- /dev/null +++ b/sleep/sleep.ino @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +// 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<= 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(); +} diff --git a/sleep/sleep.ino.old b/sleep/sleep.ino.old new file mode 100644 index 0000000..dd85982 --- /dev/null +++ b/sleep/sleep.ino.old @@ -0,0 +1,164 @@ +#include + +/* 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 . + * + */ + +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 + } +}