Réveil du pro mini difficile

Bonsoir,

je rame depuis pas mal de temps pour limiter la conso de mon pro mini 3.3v. Je me suis inspiré du sketch proposé par Fabio Cuomo "wakeup_alarm.ino".

En gros, je souhaite endormir mon arduino à des moments répétitifs donnés. J'utilise pour cela la commande :
tm % interval != 0 où interval prend par exemple la valeur 15 (endormissement toutes les 15 minutes)

Mon sketch ci-dessous endort bien la bête mais le réveil est impossible...Si le programme démarre sur une valeur divise par "interval", ça mesure jusqu'à ce que la condition tm % interval != 0 soit vérifiée. Là le MCU s'endort profondément pour l'éternité.

A noter que le sketch de F. Cuomo fonctionne sans problème (contrôlé sur oscillo).

J'ai besoin de vos conseils.

Merci d'avance.

//sleep-ds32321_301028.ino

#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>

#define wakePin 2    //utilise l'interruption 0 (broche 2) et lance la  fonction wakeUp quand la broche 2 est "LOW"

RTC_DS3231 RTC;      

float RTCtempC;
int interval = 2;  
int tm;
byte AlarmFlagSleep = 0;



//-------------------------------------------------

void wakeUp()        // fonction activant l'interruption
{
}

//------------------------------------------------------------

void setup() {
  //Defini la broche 2 comme INPUT pour accepter le signal d'interruption du DS3231
  pinMode(wakePin, INPUT);
  
    
  //Initialise les fonctions
  Serial.begin(115200);
  Wire.begin();
  RTC.begin();

  //regle l'heure et la date
  RTC.adjust(DateTime(__DATE__, __TIME__));   
  
  // supprime toutes les alarmes en attente
  RTC.armAlarm(1, false);
  RTC.clearAlarm(1);
  RTC.alarmInterrupt(1, false);
  RTC.armAlarm(2, false);
  RTC.clearAlarm(2);
  RTC.alarmInterrupt(2, false);
    
  /*active la broche SQW sur OFF, qui connectee 
  sur la broche 2 du pro mini assurera le reveil*/
  RTC.writeSqwPinMode(DS3231_OFF);

  /*syntaxe de la commande RTC.setAlarm(alarmType, seconds, minutes, hours, dayOrDate);*/
  
  // donne la date, les heures, minutes et secondes RTC.
  RTCtempC = RTC.getTemp();
  DateTime now = RTC.now();
      
  RTC.setAlarm( ALM1_MATCH_MINUTES, 0, tm, 0, 0 ); // commande d'alarme
  RTC.alarmInterrupt(1, true);

   }

void loop() {

   DateTime now = RTC.now();
   tm = now.minute();

   while (tm % interval != 0){ // we enter the sleep mode according to the interval value "tm"
   if (AlarmFlagSleep == 0){
  	attachInterrupt(0, wakeUp, LOW);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  // pro mini enters the sleep mode 
  	detachInterrupt(0); // We detach interrupt

    RTC.armAlarm(1, false); // we clear any pending alarms
    RTC.clearAlarm(1);
    RTC.alarmInterrupt(1, false);
    AlarmFlagSleep ++;
    }
  }
    if (tm % interval == 0){ // we measure the temperature of the RTC module
    Serial.print("temperature du module RTC:");
    Serial.println(RTCtempC);
}
    
}

Combien vaut tm dans le setup() lorsque vous faites RTC.setAlarm( ALM1_MATCH_MINUTES, 0, tm, 0, 0 );

Bonjour,

merci du retour.

Bonne question... tm n'est pas défini tel que placé dans le setup. En lui affectant une valeur ça ne change rien. En vérité, je ne sais pas trop où placer cette ligne de commande. Je l'ai mise dans la boucle, dans la condition, et ça ne change rien ou presque.

C'est clair que je ne comprends pas tout...

voilà une nouvelle version, j'ai placé la commande d'alarm dans la boucle, ce qui semble plus logique puisque tm varie constamment. Si je lance le programme avec un tm pair, correspondant au temps où le MCU doit être actif, le programme tourne, donne la température et stoppe dès que la valeur de tm devient impaire (le MCU doit s'endormir), mais la broche 2 passe de HIGH à LOW et y reste indéfiniment avec un courant plus élevé (entre 2 et 3 mA de plus).

Si je démarre avec une valeur de tm impaire, le système semble rester en sommeil, la broche 2 reste au niveau HIGH indéfiniment.

Je note aussi que dès lors que le processus est bloqué, la valeur de tm reste aussi bloquée alors que sa valeur est donnée dès le début de la boucle. Un téléchargement ne change rien. Pour relancer le processus il faut recompiler.

Je patauge sérieusement...

J'ai revérifier le fonctionnement du programme exemple de Fabio Cuomo. Tout fonctionne, le système se met en sommeil avec une baisse de l'intensité consommée donc la partie hard semble fonctionner. J'ai mis une résistance de pullup entre la broche 2 et le 3.3 volts. Je n'ai pas vu de différence substantielle.

voilà mon programme :

//sleep-ds32321_301028.ino

#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>

#define wakePin 2    //utilise l'interruption 0 (broche 2) and lance la  fonction wakeUp quand la broche 2 est "LOW"

RTC_DS3231 RTC;      

float RTCtempC;
int interval = 2; // 
int tm ;
byte AlarmFlagSleep = 0;

#define ledPin 13 


//-------------------------------------------------

void wakeUp()        // fonction activant l'interruption
{
}

//------------------------------------------------------------

void setup() {
  //Defini la broche 2 comme INPUT pour accepter le signal d'interruption du DS3231
  pinMode(wakePin, INPUT);
  
  //switch-on the on-board led for 1 second for indicating that the sketch is ok and running
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  delay(1000);
  
  //Initialise les fonctions
  Serial.begin(115200);
  Wire.begin();
  RTC.begin();

  //regle l'heure et la date
  RTC.adjust(DateTime(__DATE__, __TIME__));   
  
  // supprime toutes les alarmes en attente
  RTC.armAlarm(1, false);
  RTC.clearAlarm(1);
  RTC.alarmInterrupt(1, false);
  RTC.armAlarm(2, false);
  RTC.clearAlarm(2);
  RTC.alarmInterrupt(2, false);
    
  /*active la broche SQW sur OFF, qui connectee 
  sur la broche 2 du pro mini assurera le reveil*/
  RTC.writeSqwPinMode(DS3231_OFF);

  /*syntaxe de la commande RTC.setAlarm(alarmType, seconds, minutes, hours, dayOrDate);*/
  
  // donne la date, les heures, minutes et secondes RTC.
  RTCtempC = RTC.getTemp();
  DateTime now = RTC.now();   
  RTC.alarmInterrupt(1, true);

   }

void loop() {

   DateTime now = RTC.now(); 
   tm = now.minute();
   Serial.println("minutes :"); 
   Serial.println(tm); 
   while (tm % interval != 0){ // we enter the sleep mode according to interval value 
   if (AlarmFlagSleep == 0){
  	attachInterrupt(0, wakeUp, LOW);
    RTC.setAlarm( ALM1_MATCH_MINUTES, 0, tm, 0, 0 );
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  // pro mini enters the sleep mode 
    detachInterrupt(0); // We detach interrupt
    //delay(1000);
    RTC.armAlarm(1, false); // we clear any pending alarms
    RTC.clearAlarm(1);
    RTC.alarmInterrupt(1, false);
    AlarmFlagSleep ++;
    }
  }
    if (tm % interval == 0){  
    
    Serial.print("temperature du module RTC:");
    Serial.println(RTCtempC);
}
    
}

ALM1_MATCH_MINUTES déclenche l’alarme quand les minutes et secondes sont celles listées... Pouvez vous formuler ce que vous essayez de faire, en français, pas en code ?

Bonsoir,

Je développe un pèse ruche. Il transmet ses données toutes les x minutes pendant une minute via un modules radio rf24l01+. J'utilise un ds3231 comme horloge. Comme ma ruche est dehors, je souhaite fonctionner sur batterie. Donc je souhaite mettre en sommeil le pro mini (et le rf24) pendant tout le temps pendant lequel le rf24 n'emet pas.

Mon sketch est basique sans la partie ėmission qui fonctionne sur le secteur.

Merci de votre aide.

Cordialement

Jetez un œil sur cette discussion pour voir comment régler l’heure de la prochaine alarme à chaque réveil

Bonjour,

merci, je connais effectivement ce fil de discussion, je n'en ai rien tiré pour l'instant , je vais me replonger dedans plus sérieusement et tenter de l'adapter à mon cas.

Cordialement

Bonsoir,

voilà, c'est (presque) bon. Je me suis inspiré du fil en question. Avec pas mal d'adaptations, (les sketches proposés ne compilaient pas) mon programme se déclenche de façon répétitive quand je le souhaite. Maintenant, je vais l'adapter à mes programmes existants.

Merci!

cordialement

Bonsoir

Postez votre code :slight_smile:

Bonsoir,

voilà mon code, nettoyé et francisé :

//sleeping1.ino

/* Compile et teste sur arduino pro mini 3.3V
Dans cet exemple, l'arduino dort une minute et se réveille 5 secondes (environ)
*/

#include <LowPower.h>
#include <RTClibExtended.h>
#include <Wire.h>

RTC_DS3231 RTC;

#define wakePin 2 //  Broche 2 utilisee pour l'interruption
#define ledPin 13 // Led de controle du reveil

float RTCtempC;
int interval = 1; // delai de declenchement, ici en minute 

void setup()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);
  Wire.begin();
  RTC.begin();

  pinMode(wakePin, INPUT); // Declare la broche 2 comme interruption

  /* initialise les alarmes  a des valeurs donnees
   et supprime et nettoie toutes les alarmes en attente*/
  RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
  RTC.armAlarm(1, false);
  RTC.clearAlarm(1);
  RTC.alarmInterrupt(1, false);
  
  /*active la broche SQW sur OFF, qui connectee 
  a la broche 2 du pro mini assurera le reveil*/
  RTC.writeSqwPinMode(DS3231_OFF);
  
  //regle l'heure et la date
  RTC.adjust(DateTime(__DATE__, __TIME__));

  // Declare les parametres de l'alarme
  DateTime now = RTC.now();
  Serial.println(F("Temps actuel : "));
  printDateTime(now);
  DateTime future (now + TimeSpan(0, 0, interval, 0)); //jours, Heures, Minutes, Secondes
  Serial.println(F("L'alarme est programmee a : "));
  printDateTime(future);
  RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
  RTC.alarmInterrupt(1, true); // Active l'interruption 0
}

void loop()
{
  Serial.println("Je m'endors...");
  delay(100);
  sleepNow(); // Fonction activant l'endormissement
  setRTCagain(); // Fonction relançant l'activite du MCU
}
// Fonction "Interrupt Service Routine" (ISR)
void wakeUp ()
{
  detachInterrupt (0); // desactive l'interruption surla broche 2
}

void sleepNow ()
{
  attachInterrupt (0, wakeUp, FALLING);  /* Se reveille sur le front descendant de la tension sur la broche 2*/
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

void setRTCagain() {
  Serial.println("Je me reveille...");   

    // Programmation de l'alarme
    DateTime now = RTC.now(); // donne le temps actuel
    DateTime future (now + TimeSpan(0, 0, interval, 0)); //Jours, Heures, Minutes, Secondes
    Serial.println(F("L'alarme est programmee a : "));
    printDateTime(future);
    RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, HIGH);
    delay(5000); // duree du reveil, la led reste allumee.
    digitalWrite(ledPin, LOW);

}


void printDateTime(DateTime t)
{
  Serial.print((t.day() < 10) ? "0" : ""); Serial.print(t.day(), DEC); Serial.print('/');
  Serial.print((t.month() < 10) ? "0" : ""); Serial.print(t.month(), DEC); Serial.print('/');
  Serial.print(t.year(), DEC); Serial.print(' ');
  Serial.print((t.hour() < 10) ? "0" : ""); Serial.print(t.hour(), DEC); Serial.print(':');
  Serial.print((t.minute() < 10) ? "0" : ""); Serial.print(t.minute(), DEC); Serial.print(':');
  Serial.print((t.second() < 10) ? "0" : ""); Serial.println(t.second(), DEC);
}

J'ai vérifié la consommation. sans l'activation de la led 13, sans l'interface USB. En mode sommeil la conso est de 3.5 mA. En mode réveil ça passe à 7.5mA. avec la led 13 ça grimpe à 9.5mA.

J'avais désactivé le module radio rf24 mais laissé la led verte du pro mini. En la supprimant, je devrais encore gagner au moins 1 mA je pense.

enfin, j'ai supprimé la résistance de pullup sur la broche 2. Est ce une bonne idée ?

Cordialement.