Go Down

Topic: Ideas? How to make arduino sleep & wake up... (Read 2300 times) previous topic - next topic

capo12

Hi everyone!

I am trying to get the "sleep & wake up" function for arduino to work for my outdoor project that uses a photocell to measure light levels, and I think it is getting "closer" to do what I would like it to do, but I'm kind of stuck, and hence, wanted to ask for advise & guidance from those of you out there...

I am hoping that this post can start a good discussion amongst fellow arduinoers, since there isn't that much clear information out there for beginners (like myself!!) on how one could put together a project like this.

In essence, what I would like my project to do is the following:
1. arduino gets ready to go to sleep for 1st time
2. shuts power off to photocell
3. goes to sleep (sleep mode power down) for ~24 seconds
4. after ~24 seconds, wakes up and powers up voltage for photocell
5. begins sending light values to serial output for a duration of 10 seconds
6. shuts power off to photocell
7. goes to sleep for 24 seconds
8. repeat starting at Step #4

I've been working with the "Watchdog Sleepy Bones" as my roadmap and slowly started to edit it, but I am a bit stuck on several of these steps and I'm not sure where & what I am doing wrong. The code runs, but I am not sure how to add the various steps that I would like it to do...

Therefore, any advise out there would be super appreciated!!

Here's the code I have so far (and slowly growing)...:

Code: [Select]

/*
Based on Watchdog Sleepy Bones sketch and very humbly being amended by Capo12...


Notes:
This is what a "mini sketch" for running a photocell would look like:

/////////////////////////////////////////////

// volt pin connected to arduino 5V
// ground pin connected to arduino ground

int photocellPin = 0;     // the cell and 10K pulldown are connected to a0
int photocellReading;     // the analog reading from the analog resistor divider

void setup(void) {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600);   
}

void loop(void) {
  photocellReading = analogRead(photocellPin); 
  Serial.println(photocellReading);     // the raw analog reading
}

/////////////////////////////////////////////

*/


#include <avr/sleep.h>
#include <avr/wdt.h>
#define sleepTime  3                       //number of 8 second sleep cycles (will sleep for ~24 seconds)

volatile byte wdt=0;                       //used to cound number of sleep cycles



void setup(){
  setup_watchdog();                        // set prescaller and enable interrupt                 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);     // sleep mode is set here Power Down uses the least current
                                           // system clock is turned off, so millis won't be reliable!
  delay(10);

  Serial.begin(9600);             //serial baud rate 9600
  //Arduino is just powering up...
}



void loop(){

         // do what you want to before you sleep here
         Serial.println("Ok, going to sleep now... :-)");   
         Serial.println("Step2");   
     
       
       
       
                 
    system_sleep();
        // do what you want to after you sleep here


        Serial.println("Just waking up now...");



}




void system_sleep() {
  ADCSRA |= (0<<ADEN);                     // disable ADC
  sleep_enable();                          // enable sleeping

  while (wdt < sleepTime){                 // sleep for sleepTime * 8sec
        sleep_mode();                            // activate system sleep
      // sleeping ...
      }
      sleep_disable();                         // disable sleep 
      ADCSRA |= (1<<ADEN);                     // switch ADC on
      wdt = 0;                                 // reset wdt for next cycle
  }


void setup_watchdog() {
cli(); //disable global interrupts
  MCUSR = 0x00;  //clear all reset flags
  //set WD_ChangeEnable and WD_resetEnable to alter the register
  WDTCSR |= (1<<WDCE) | (1<<WDE);   // this is a timed sequence to protect WDTCSR
  // set new watchdog timeout value to 1024K cycles (~8.0 sec)
  WDTCSR = (1<<WDP3) | (1<<WDP0);
  //enable watchdog interrupt
  WDTCSR |= (1<<WDIE);   
sei(); //enable global interrupts
}

// Watchdog Interrupt Service Routine.
// Very first thing after sleep wakes with WDT Interrupt
ISR(WDT_vect) {
  wdt++;  // increment the watchdog timer
}




Nick Gammon

See if this helps:

http://www.gammon.com.au/power
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Quote
The code runs, but I am not sure how to add the various steps that I would like it to do...


I'm not sure I see the question here.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

iyahdub


See if this helps:

http://www.gammon.com.au/power

Nick, i came across your sire a while ago and i have to say it has been really helpful . Not to mention the fact that you are quite an active and patient person here in the forum always helping anyone and everyone !!! Thanks for that!!
10 LET Loop=Infinite
20 GO TO 10

PaulS

Quote
Nick, i came across your sire a while ago

Really? What's his dad like?

iyahdub

come one, that was a typo...lol LAWD, how you like !! lol
10 LET Loop=Infinite
20 GO TO 10

capo12

Dear members,

thanks for the very helpful responses. I was able to make a lot of progress in my sketch, but there are a few things that I can't figure out, and hence, was hoping to ask for some advice.

Below is the code that I have so far. I still can't make it define and implement the time during which the data is collected (time X2), and also output the data as needed (see below for details).

Any and all thoughts & suggestions would be greatly appreciated…


Code: [Select]

/* This is the draft sketch for using with an outdoor battery-powered arduino that is meant to collect and record weather information (air temperature,
    humidity, date & time) and create a log file (a data logger is used that automatically records anything sent to the serial output).

The outline of the sketch (which is still not complete...):
1. arduino powers up & goes directly to sleep for X1 seconds
2. after X1 seconds, wakes up for X2 seconds and powers up the various sensors/instruments
3. It prints lines to serial output lines that contain the information from the various sensors (see example further below) for Y amount of times
4. After the X2 seconds pass by, the arduino shuts power off to all sensors/instruments
5. Then, it goes to sleep for X1 seconds
8. repeat starting at Step #2


NOTE: This script is not yet fully functional. So... What is still missing? This sketch still needs to do the following:
- define & implement X2 duration
- make the sketch do #3 & #4


        Many thanks to trendski for the valuable sleep & wake up sketch template

*/


/*===============================================================================*/
// Ok, let's start with some housekeeping...
// Load libraries & variables needed
#include <avr/sleep.h>      // Library for sleeping
#include <avr/wdt.h>        // Library for sleeping
#define ledPINgrn 12       // LED on when logging (yellow)
#define ledPINred 13       // LED on when sleeping (red)
#include <Wire.h>          // Library for time
#include "RTClib.h"        // Library for time
RTC_DS1307 RTC;            // Library for time
#include "DHT.h"            // Library for DHT22 (Temp & Humidity)
#define DHTPIN 2            // pin to which the data cable is connected to
#define DHTTYPE DHT22       // DHT22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);   // Library for DHT22 (Temp & Humidity)


/*===============================================================================*/
// Here we are going to define the power pins for our different instruments
// Power for datalogger:
int p1Pin = 6; // define power pin
float volt_pwr1 = 3.3; // volts for the data logger

// Power for DHT22
int p2Pin = 4;         // define pin (this uses 5v, so no need to use a PWM pin)

// Power for DS1307 RTC clock
//int p3Pin = 8;   // Why don't I get any serial output nor sleep/wakeup activity when I activate the power through this pin????!!!
                   
byte old_ADCSRA;
// watchdog interrupt
ISR (WDT_vect)
{
  wdt_disable();  // disable watchdog
}

/*===============================================================================*/
void setup()    // Here we will do the general SETUP (will run only once!!!!!!)
  {
      Serial.begin(9600);            // Set-up the serial output rate

              pinMode(p1Pin, OUTPUT);        // initialize the digital pin as an output.
              pinMode(p2Pin, OUTPUT);        // initialize the digital pin as an output.
      //      pinMode(p3Pin, OUTPUT);        // initialize the digital pin as an output.
     
      dht.begin();
      Wire.begin();                  // Calling time module
      RTC.begin();                   // Calling time module
     
      if (! RTC.isrunning()) {
        Serial.println("RTC is NOT running!");
        // following line sets the RTC to the date & time this sketch was compiled
        RTC.adjust(DateTime(__DATE__, __TIME__));
      }

  // This will set up the LEDs we will use to track if sleeping or awake
  pinMode(ledPINred, OUTPUT);
  pinMode(ledPINgrn, OUTPUT);
  digitalWrite (ledPINred, LOW);
  digitalWrite (ledPINgrn, LOW);
}



// Start of Datalogger methods**********
void LogData ()    // Here we will run the "LogData" command (and all the things within it) (will run only once!!!!!!)
  {
     
      digitalWrite (ledPINgrn, HIGH);    //Turn the LED on when logging (to show us what's going on)

      // Lets set-up the amount of voltage needed for the data logger   
      int v_num_pwr1 = volt_pwr1 * 51;   // This ranges from 0 (0 volts) to 255 (5 Volts); Example: 3.3v * 51 = 168.3
      analogWrite(p1Pin, v_num_pwr1);    // power up p1Pin
     
      // Lets set-up the amount of voltage needed for the DHT22   
      digitalWrite(p2Pin, HIGH);    // power up p2Pin
      delay(1000);                   // give the sensor a moment to "reset" from the powerup
           
      // Lets set-up 5v on for the clock
//      digitalWrite(p3Pin, HIGH);

      // Let's start printing some stuff to the serial output... 
      Serial.println("Now, time to start printing data...");
     
   
/* ****** Starting at this point, how can I do to send the following "print to serial output" code
                so that it prints "time, humidity & temp" for Y amount of times while the arduino is awake,
                then power things off and go to sleep??? :-(
*/


// start some kind of loop here that runs for XXX times?

     
    // Start printing the info we need
    // Print the date...   
        DateTime now = RTC.now();
     

        Serial.print(now.month(), DEC);
        Serial.print('/');
        Serial.print(now.day(), DEC);
        Serial.print('/');       
        Serial.print(now.year(), DEC);
        Serial.print(' ');
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.print(':');
        Serial.print(now.second(), DEC);
        Serial.print(" %\t");
     
             
    // Start printing Humidity & Temperature...     
     float h = dht.readHumidity();
     float t = dht.readTemperature();

    // check if returns are valid, if they are NaN (not a number) then something went wrong!
    if (isnan(t) || isnan(h)) {
      Serial.println("Failed to read from DHT");
    } else {
      Serial.print("Humidity: ");
      Serial.print(h);
      Serial.print(" %\t");
      Serial.print("DHT Temp C: ");
      Serial.print(t);
      Serial.println();
    }



/*   Basically, what I would like to achieve is to print this::
4/24/2012 18:59:2 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:4 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:6 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:8 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:10 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:12 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:14 % Humidity: 51.20 % DHT Temp C: 25.60
4/24/2012 18:59:16 % Humidity: 51.20 % DHT Temp C: 25.60
  etc. etc.. (this keeps printing Y amount of times and finishes before time X2, so that everything can get logged well and not shut
  down abruptly)
 
  */

// end of a loop here??


 
     
      delay(5000); // Keep the LED and text showing for 5 sec
  }
// End of Datalogger methods*******



// Sleeping routines...
void loop ()
{   
  old_ADCSRA = ADCSRA; //save old status of ADC
 
  //=============SLEEP ROUTINES=============
  for (int myLoop= 0; myLoop < 1; myLoop++) // SLEEP-LOOP loop around and give delay of 1 cycle = 8 sec  (1 cycle = 8 sec)

  {
   
    Serial.println("Going to sleep now...");
    digitalWrite (ledPINred, HIGH); //led on when sleeping

 
    // disable ADC
    ADCSRA = 0; 

    // clear various "reset" flags
    MCUSR = 0;     
    // allow changes, disable reset
    WDTCSR = _BV (WDCE) | _BV (WDE);

    // set interrupt mode and an interval
    WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0);    // set WDIE, and 8 seconds delay

    wdt_reset();  // pat the dog

    set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
    sleep_enable();

    // turn off brown-out enable in software
    MCUCR = _BV (BODS) | _BV (BODSE);
    MCUCR = _BV (BODS);
   
    sleep_cpu ();  //nighty-night :)
  }

  // cancel sleep as a precaution
  sleep_disable();


digitalWrite (ledPINred, LOW); //red led off when awake & logging


  //++++++++++++++++++++WAKE and CALL DATALOGGER+++++++
  ADCSRA = old_ADCSRA; //enable ADC need to enable so ADC can get sensor data


LogData (); // now awake so as to power the sensors up, start logging data, and then go to sleep



digitalWrite (ledPINgrn, LOW);    //indicate finished logging
analogWrite(p1Pin, LOW);          // power down p1Pin
digitalWrite(p2Pin, LOW);         // power down p2Pin
// digitalWrite(p3Pin, LOW);       // power down p2Pin

 
} // end


trendski

Thanks for the messages in my in-box.

Don't worry. I was the same when I started programming. We all have to start somewhere!

I think it would help to go right back to the beginning of the project? Here is a five point plan that may help:

1. Did you get the adafruit DHT sketch to work with your sensors?

2. Did you get a sample sketch for your RTC working? I can't test this properly, as I don't have DS1307, but it looks very straight forward
http://www.henningkarlsen.com/electronics/library.php?id=34

3. Did you get a sketch to serial-print the correct time, date and sensor data to the serial monitor?

4. So now that combined code, once fully working will form the core Data-logger methods eg void DataLog() {...tested code, known to work... }

5. So once that combined code is fully working, try to incorporate the appropriate sleep and interrupt code in void loop() and make call to DataLog()

Cheers
Craig Turner, blog: http://gampageek.blogspot.co.uk/ It helps with my learning if I write things down, esp. for others to follow (constructive comments welcomed to improve)

RandallR

Have you considered a PCF8563 instead of a DS1307?  It has many of the same features but does not have any RAM.  It has clock output, though different frequencies, and an interrupt output that can be set from a few seconds to several hours.

http://arduino.cc/forum/index.php/topic,99588.0.html

Go Up