[Résolu]watchdog et milli();

Bonjour à tous
j’ai un problème
j’endors le µ en mode IDLE en boucle ( ce mode ne dévalide pas les fonctions ) et à chaque réveil, je lui fais afficher la valeur de millis();. c’est ok.
j’endors le µ en mode POWER_DOWN, ( ce mode dévalide toutes les fonctions ) et à chaque réveil, je revalide les fonctions. je pensais pouvoir afficher la fonction millis().
mais force m’est de constater que les chiffres qui s’affichent ont bien une logique, mais ils n’ont rien à voir avec la fonction milli();

en lisant la doc, je ne trouve pas de solution, pour moi "power_all_enable(); valide toutes les fonctions

l’un de vous a t’il une solution???

voici mon code

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile int f_wdt=1;

void setup() {Serial.begin(115200);watchdog_setup();}

ISR(WDT_vect){ if(f_wdt == 0) {f_wdt=1;}}

void watchdog_setup(){
 MCUSR &= ~(1<<WDRF);
 WDTCSR |= (1<<WDCE) | (1<<WDE);
 WDTCSR = 1<<WDP0 | 1<<WDP3; // 8 secondes 
 //WDTCSR = 1<<WDP1 | 1<<WDP2; // 1 seconde 
 WDTCSR |= _BV(WDIE); }
 
 void enterSleep(void)
{
  Serial.print("depart en sommeil  ");Serial.flush();Serial.print("     millis()  ");Serial.println(millis());Serial.flush();
 //set_sleep_mode (SLEEP_MODE_IDLE);
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 sleep_enable();
 sleep_mode();
 }

void loop() 
{if(f_wdt == 1)     //le µ se reveille
{
 sleep_disable();
 power_timer0_enable();
 
 //power_all_enable();//reactive toutes les fonctionnalités, dont USART et les TIMER
 f_wdt = 0;
 for (int f = 0;f<5;f++)
 {
  Serial.print("reveil par le watchdog, ctrl fonction millis()  ");Serial.println(millis());Serial.flush();
 }
 enterSleep();     //le µ retourne dormir
 }
 else
 {}
 }

qu'est-ce que ça affiche?

ton power_down ne réinitialise pas complètement le µC ? d'où un éventuel redémarrage du comptage des millis (?)

bonjour les amis
le prog affiche les millisecondes. il fonctionne correctement en mode “IDLE”
mais si je remplace par POWER_DOWN les millisecondes ne sont pas correctes .
non elles ne redémarrent pas à zéro.
elles semblent le faire, mais elles ne correspondent pas aux millisecondes

en fait, je suis en train de faire un prg qui doit être éveillé 1à 3 secondes et dormir un temps qui correspond à 8 secondes ou un multiple de 8 secondes.

exemple: en éveil, une led sera allumée pendant 1 seconde puis le prg éteint la led endort le µ pour 8 secondes. et ainsi de suite.

bien sur le mode de sommeil le plus économe est le POWER_DOWN et c’est pourquoi il m’intéresse.
mais il endort toutes les fonctions (uart, ADC,timer0, 1, 2, etc…)
en sortant du sommeil il est normalement possible de les remettre en marche.
ce que je croyais faire avec “power all enable” mais ce la ne fonctionne pas correctement ensuite pour l’affichage des millisecondes.

peut importe que les millisecondes ne recommencent pas là ou elles sont sensées etre dans le comptage. l’essentiel étant qu’elles soient correctes en durée ( que 10 millis soient vraiment égales à 10 millis)

comme le fonction millis() est liée au timer 0, j’ai remplace “power all enable” par “power timer 0 enable”, mais le résultat est le meme.

pour résumer ma question: comment récupérer la fonction millis(); après une période de sommeil par le mode POWER DOWN ?

la fonction millis() normalement ne fait que "faire le calcul" de conversion du compteur de cycles µC x le temps d'un cycle. Si ca foire c'est donc que ce calcul devient erroné.
Tu n'aurais pas tout simplement une valeur stockée d'un appel à millis() datant d'avant le POWER_DOWN ?

Sinon, qu'est-ce-qui te fait dire que millis() ne fonctionne pas/plus après le POWER_DOWN ? Ca valeur ne varie plus ? ou elle varie d'une façon "foireuse" ?

Edit :
Si tu regardes le code du main.cpp pour les arduinos, avant l'appel de setup() tu trouves tout ceci :

        init(); 
 
	initVariant(); 
 
 
#if defined(USBCON) 
	USBDevice.attach(); 
#endif

Je pense qu'après le POWER_DOWN tu dois tomber sur un état "non-initialisé" de certaines variables globales, notamment le coef multiplicateur permettant à millis() de faire correctement son calcul...

Je te sugère donc de refaire un appel au moins aux deux premières fonctions (init() & initVariant()) pour réinitialiser ce qui doit l'être en sortie de ton POWER_DOWN...

hello merci de t’interesser à mon problème
j’ai modifié le prg . au reveil, j’attribue millis() à une variable et j’affiche mili tant pendant 5 secondes puis je retourne dormir 8 secondes.

mais le prg fait l’affichage des milli pendant 5 secondes et dort pour les 3 secondes restantes ???

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile int f_wdt=1;

void setup() {Serial.begin(115200);watchdog_setup();}

ISR(WDT_vect){ if(f_wdt == 0) {f_wdt=1;}}

void watchdog_setup(){
 MCUSR &= ~(1<<WDRF);
 WDTCSR |= (1<<WDCE) | (1<<WDE);
 WDTCSR = 1<<WDP0 | 1<<WDP3; // 8 secondes 
 //WDTCSR = 1<<WDP1 | 1<<WDP2; // 1 seconde 
 WDTCSR |= _BV(WDIE); }
  wdt_reset();  // pat the dog
 void enterSleep(void)
{
  Serial.print("depart en sommeil pour 8 secondes  ");Serial.flush();Serial.print("     millis()  ");Serial.println(millis());Serial.flush();
// set_sleep_mode (SLEEP_MODE_IDLE);
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 sleep_enable();
 sleep_mode();
 }

void loop() 
{if(f_wdt == 1)     //le µ se reveille
{
 sleep_disable();
 power_timer0_enable();
 
 power_all_enable();//reactive toutes les fonctionnalités, dont USART et les TIMER
 unsigned long deb=millis();
while (deb+5000>millis()){
  Serial.print("reveil par le watchdog pour 5 secondes, ctrl fonction millis()  ");Serial.println(millis());Serial.flush();}
 f_wdt = 0;
 enterSleep();     //le µ retourne dormir
 }
 else
 {}
 }

c’est bon, il manquait un reset du compteur watchdog
maintenant, je compte bien 5 secondes avec millis() puis je dors 8 secondes et ceci en boucle
merci à vous

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile int f_wdt=1;

void setup() {Serial.begin(115200);watchdog_setup();}

ISR(WDT_vect){ if(f_wdt == 0) {f_wdt=1;}}

void watchdog_setup(){
 MCUSR &= ~(1<<WDRF);
 WDTCSR |= (1<<WDCE) | (1<<WDE);
 WDTCSR = 1<<WDP0 | 1<<WDP3; // 8 secondes 
 //WDTCSR = 1<<WDP1 | 1<<WDP2; // 1 seconde 
 WDTCSR |= _BV(WDIE); }
  wdt_reset();  // pat the dog
 void enterSleep(void)
{
  Serial.print("depart en sommeil pour 8 secondes  ");Serial.flush();Serial.print("     millis()  ");Serial.println(millis());Serial.flush();
// set_sleep_mode (SLEEP_MODE_IDLE);
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 wdt_reset();  // pat the dog
 sleep_enable();
 sleep_mode();
 }

void loop() 
{if(f_wdt == 1)     //le µ se reveille
{
 sleep_disable();
 power_timer0_enable();
 
 power_all_enable();//reactive toutes les fonctionnalités, dont USART et les TIMER
 
 unsigned long deb=millis();
while (deb+5000>millis()){
  Serial.print("reveil par le watchdog pour 5 secondes, ctrl fonction millis()  ");Serial.println(millis());Serial.flush();}
 f_wdt = 0;
 enterSleep();     //le µ retourne dormir
 }
 else
 {}
 }

super ! félicitations ! :slight_smile:

Quelques commentaires se voulant constructifs:

1/ regardez votre indentation (faites un ctrl-T dans l’IDE) votre premier wdt_reset() ne sert à rien vu qu’il n’est pas dans la fonction. Le second fait le job au. Réveil

2/ deb+5000>millis() va bugger (overflow d’entier) si vous faites tourner ça longtemps. Il faut écrire millis()-deb < 5000

3/ Le power_timer0_enable(); devient inutile si vous faites un power_all_enable(); ensuite

4/ le else {} ne sert rien

tout cela est vrai.
merci JML :slight_smile: