Sleep.h

Bonjour,

Je voudrais mettre en place une mise en veille sur ma Arduino

En utilisant la librairie sleep.h. Or quand je met ce fichier .h dans ma librairie, que je fais “#include <sleep.h>”, le fichier n’est pas reconnu…

J’ai réussi mais j’ai un soucis …

/* Sleep Demo Serial
 * -----------------
 * Example code to demonstrate the sleep functions in a Arduino. Arduino will wake up
 * when new data is received in the serial port USART
 * Based on Sleep Demo Serial from http://www.arduino.cc/playground/Learning/ArduinoSleepCode 
 *
 * Copyright (C) 2006 MacSimski 2006-12-30 
 * Copyright (C) 2007 D. Cuartielles 2007-07-08 - Mexico DF
 * 
 *  With modifications from Ruben Laguna  2008-10-15
 * 
 *  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/>.
 * 
 */
 
#include <avr/power.h>
#include <avr/sleep.h>
#include <TinkerKit.h>
 
 
int sleepStatus = 0;             // variable to store a request for sleep
int count = 0;                   // counter
 
 
TKThermistor therm(I0);       // creating the object 'therm' that belongs to the 'TKThermistor' class 
                              // and giving the value to the desired output pin

float C, F;		      // temperature readings are returned in float format

void setup()
{
  // initialize serial communications at 9600 bps
  Serial.begin(9600);
}


void sleepNow()
{
    /* 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 modus.
     *
     * In the avr/sleep.h file, the call names of these sleep modus 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
     *
     *  the power reduction management <avr/power.h>  is described in 
     *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
     */  
     
  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 
  
  power_adc_disable();
  power_spi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();
  
  
  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...
 
  power_all_enable();
   
}
 
 
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 asleep 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
  }
  if (count >=20)
  {
    Serial.println("Timer :On sort du mode veille");
    delay (100);
    count=0;
    sleep_disable();
  
     
  C = therm.getCelsius();     	// Reading the temperature in Celsius degrees and store in the C variable
  F = therm.getFahrenheit();  	// Reading the temperature in Fahrenheit degrees and store in the F variable

  // Print the collected data in a row on the Serial Monitor
  Serial.print("Analog reading: \t");	// Reading the analog value from the thermistor
  Serial.print(therm.get());
  Serial.print("\tC: \t");
  Serial.print(C);
  Serial.print("\tF: \t");
  Serial.println(F);
  
  

  delay(1000); 
  }
}

J’ai comme résultat :

Awake for 0sec
Awake for 1sec
Awake for 2sec
Awake for 3sec
Awake for 4sec
Awake for 5sec
Awake for 6sec
Awake for 7sec
Awake for 8sec
Awake for 9sec
Timer: Entering Sleep mode

Et il ne se reveille plus pour afficher les valeurs…

Normal, pourquoi voudrais-tu qu’il se réveille ? Tous les timers sont désactivés et tu as choisis le mode de sommeil le plus profond, il n’y a que les interruptions matérielles (bouton typiquement) qui pourrait le réveiller

Donc si je met : SLEEP_MODE_STANDBY Le reveil devrait marché ?..

Et pourquoi avec le code SLEEP_MODE_PWR_DOWN, les LED témoins du capteur de T° sont toujours allumé ? c'est normal ou pas ?

Après j'ai pas exploré la mise en sommeil sur Atmega mais comme j'imagine que c'est analogue à beaucoup de µC je pense que c'est la même chose : la mise en sommeil conserve l'état des sorties (et heureusement !) donc normal que tes LED reste allumé si c'était le cas au moment de la mise en sommeil.

Il ne suffit pas de modifier le mode de mise en sommeil, j'ai pas étudié la lib mais il doit y avoir moyen de faire appel (simplement) à un timer ou au watchdog pour réveiller l'Atmega après un certain temps écoulé.

EDIT : http://www.gammon.com.au/forum/?id=11497 ==> très bien détaillé mais pas forcement simple à comprendre pour les non-initiés ...

Après test, et modification du code (Si besoin je vous le mettrai vendredi), j'ai un petit soucis

Quand j'utilise le sleep mode en "IDLE", aucun soucis niveau réveil. Mais niveau conso, ca change pas énormement

Mais quand je met le mode "STANDBY", il se met bien en vielle, mais ensuite ne se reveille plus.. Là aussi une interruption materielle pour le sortir du sommeille ?

C'est dans la datasheet p38 : http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet.pdf

Apparement le watchdog (WDT) est utilisable quel que soit le niveau de sommeil.

Un article instructif dans le domaine : https://www.sparkfun.com/tutorials/309

Qu'est-ce qu'un watchdog ?..

Le Watchdog est destiné à surveiller l’activité du microcontroleur : dans le programme le watchdog (assimilable à un timer) est régulièrement remis à zéro (à chaque boucle par exemple). Si il reste trop longtemps sans “recevoir” de signal du programme, il lance un reset car on considère qu’il y a eu un soucis dans le programme. D’où le “chien de garde”. Sur arduino il est désactivé pour exécuter cette fonction, mais un WDT est un timer et peut-être utiliser comme tel.

J'ai fais plusieurs test, et avec la fonction "PWR_SAVE" il ne se reveille pas avec juste un delay..

Code ?

J'ai plus cours là, je te le fais parvenir demain a 9h

#include <OneWire.h>
#include <avr/sleep.h>
#include <avr/power.h>
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(7);  // on pin 10 (a 4.7K resistor is necessary)
int sleepStatus = 0;  
int escapingFlag = 0;          
int count = 0; 

void setup(void)
{
  Serial.begin(9600);
}

void loop(void) 
{
  count++;
  delay(100);
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) 
  {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++)
  {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s)
  {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) 
    {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
    else 
    {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
    }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
 
  if (count>=1) 
  {
     Serial.println("Entrée en mode veille");
      delay(100);      // this delay is needed, the sleep 
      set_sleep_mode(SLEEP_MODE_IDLE);
      sleep_mode();
      sleep_enable();  // sleep function called here
      count = 0;
           
     delay (10000);
    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:

      Serial.println("Sortie du mode veille"); // classic dummy message
    }
}

Là j’ai mis en IDLE et il se reveil, mais c’est le seul, sinon il ne se reveil pas…

Up..

Down. Tout le monde a droit à son week-end tranquille.

Et voui :D

Dans ton code je ne vois aucune configuration de timer donc il ne risque pas de se réveiller ...

Re-Up..

B@tto: Dans ton code je ne vois aucune configuration de timer donc il ne risque pas de se réveiller ...

Désolé j'avais pas vu :O

Comment ca configuration ?

Bah configurer les registres, les interruptions ...