[RESOLU] LowPower.h ne fait rien

Salut à tous

Je voudrais économiser du courant sur un montage piloté par un Nano (chinois) qui commande une porte de poulailler, le tout sur batterie.
J'avais commencé par utiliser le watchdog, je suis passé par le souci habituel de bootloader incompatible...je l'ai flashé mais ça ne fonctionnais toujours pas.
Pour ne pas me prendre la tête j'ai décidé d'utiliser la librairie LowPower.h qui simplifie bien les choses.

Mon code fait exactement ce qui est prévu sauf que la mise en Power_down n'arrive jamais, tout fonctionne exactement comme si la librairie et le code qui l'appelle n'existait pas. Quand je met la main sur la cellule qui mesure la luminosité, la porte se ferme instantanément alors que ça ne devrais arriver que lors de la prochaine sortie de veille (max 8s)

Voici le code, l'appel de LowPower est tout à la fin :

/**
 * Controle de la porte automatique de poulailler :
 * Un potentiomètre détermine le seuil d'ouverture, un autre le seuil de fermeture.
 * La cellule photoéléctrique déclenche le moteur dans un sens ou dans l'autre en fonction de ces seuils.
 * Le mouvement de la porte s'arrète dès que 1 des capteurs fin de course est activé (1 haut, 1 bas).
 * Une sécurité arrète tout si le moteur reste en tension plus de 3 secondes.
 **/
 
#include "LowPower.h"  //Librairie servant à la mise en veille

// déclaration des pins utilisés sur la carte :
  const int pinPotarJour = A3;
  const int pinPotarNuit = A4;
  const int pinCel = A1;
  const int pinMoteur1 = 3;
  const int pinMoteur2 = 4;
  const int pinCapteurHaut = 8;
  const int pinCapteurBas = 9;
  const int pinControleVitesse = 6;

// déclaration des différentes variables liées aux composants :
int valeurCel, seuilPotarJour, seuilPotarNuit, vitesse;

// déclaration des variables de timer
unsigned long timerSecu, timer;

//flags porte ouverte/fermée et sécurité :
boolean porteOuverte, porteFermee, moteurOn, secu, timerOn;


//---------------------------------------------------------------------------------------------------------//
// INITIALISATION DES VARIABLES, DES MODES ET DES ETATS //

void setup()
{
  seuilPotarJour = 0;  // Initialisation des variables
  seuilPotarNuit = 0;
  valeurCel = 0;
  vitesse = 170;
  

  porteOuverte = HIGH;                       // les flags sont mis à 0 par sureté (HIGH = pas d'aimant devant le capteur effet Hall)
  porteFermee = HIGH;
  moteurOn = 0;
  timerSecu = 0;
  timer = 0;
  timerOn = 0;
  secu = 0;

  pinMode(pinMoteur1, OUTPUT);             //pin 3 et 4 en mode output, moteur à l'arrét par sureté
  digitalWrite(pinMoteur1, LOW);
  pinMode(pinMoteur2, OUTPUT);
  digitalWrite(pinMoteur2, LOW);

  pinMode(pinCapteurHaut, INPUT);         // pin 8 et 9 en mode input (fin de course)
  pinMode(pinCapteurBas, INPUT);

  pinMode(pinControleVitesse, OUTPUT);      // Le pin 6 active/desactive le pont H qui contrôle le moteur et controle la vitesse de rotation (presentement 170 sur 255)
  digitalWrite(pinControleVitesse, LOW);

 }

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

void loop() 
{
  
  seuilPotarJour = analogRead(pinPotarJour);            //lecture du seuil d'ouverture de la porte
  seuilPotarNuit = analogRead(pinPotarNuit);            //lecture du seuil de fermeture de la porte
  
  if (seuilPotarNuit >= seuilPotarJour)                 //On s'assure que le seuil Nuit est inférieur au seuil Jour, sinon la porte s'ouvre et se ferme
  {                                                     //en boucle. Si ce n'est pas le cas le seuil Nuit est arbitrairement fixé à 10 de moins que le seuil Jour.
  seuilPotarNuit = seuilPotarJour - 10;
  }

  valeurCel = analogRead(pinCel);                       //lecture de la valeur renvoyée par la cellule

  porteOuverte = digitalRead(pinCapteurHaut);           //vérifie si la porte est ouverte
  porteFermee = digitalRead(pinCapteurBas);             //verifie si la porte est fermée
  
  

  //*********************************************************************************************************//
  // OUVERTURE DE LA PORTE //

if (!porteFermee && !secu)                             // Si la porte est fermée et n'est pas en sécurité...
{
  if (valeurCel >= seuilPotarJour)                      // et qu'il fait jour...
  {
      digitalWrite(pinMoteur1, LOW);                    //le moteur tourne et ouvre la porte
      digitalWrite(pinMoteur2, HIGH);
      analogWrite(pinControleVitesse, vitesse);
      moteurOn = 1;
      
          if (!timerOn)                                //Si le timer n'est pas déja en route on note l'instant ou demarre le moteur
          {
          timerSecu = millis();
          timerOn = 1;
          }

  }

  else if (valeurCel <= seuilPotarNuit)                //Sinon, s'il fait nuit...
  {
      analogWrite(pinControleVitesse, 0);              // le moteur est désactivé, le timer s'arrète
      moteurOn = 0;
      timerOn = 0;

  }
}



  //********************************************************************************************************//
  // FERMETURE DE LA PORTE //
  
if (!porteOuverte && !secu)                             // Si la porte est ouverte et n'est pas en sécurité...
{
  if (valeurCel <= seuilPotarNuit)                      // et qu'il fait nuit...
  {
      digitalWrite(pinMoteur1, HIGH);                  //le moteur tourne dans l'autre sens et ferme la porte
      digitalWrite(pinMoteur2, LOW);
      analogWrite(pinControleVitesse, vitesse);
      moteurOn = 1;
        
          if (!timerOn)                                //Si le timer n'est pas déja en route on note l'instant ou demarre le moteur
          {
          timerSecu = millis();
          timerOn = 1;
          }
  }

  else if (valeurCel >= seuilPotarJour)              // Sinon, s'il fait jour...
  {
     analogWrite(pinControleVitesse, 0);             // le moteur est désactivé, le timer s'arrète
     moteurOn = 0;
     timerOn = 0;

  }
}

  //*********************************************************************************************************//
  // SÉCURITÉ  ET MISE EN SOMMEIL //
  
if (moteurOn)
{
  timer = millis();
  if (timer - timerSecu >= 3000)                    // Si le moteur est sous tension depuis plus de 2,5 secondes et que la porte n'est ni ouverte ni fermée
  {                                                 // c'est qu'elle est probablement coincée...
    analogWrite(pinControleVitesse, 0);             // le moteur est désactivé quel que soit l'état de la porte
     moteurOn = 0; 
     secu = 1;                                      // Le système se met en sécurité, la résolution du problème et un reset sont nécessaires.
  }
  
  else if (!moteurOn)                               // Si aucune action d'ouverture/fermeture n'est en cour
  {
   LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);  // Met le système en veille pendant environ 8s 
  }
  

}
  
  //*********************************************************************************************************//
  //FIN DU PROGRAMME
}

Le comportement attendu est le suivant : Toutes les 8s le Nano sort de veille, lit les capteurs, ouvre ou ferme la porte s'il y a lieu, le Nano se remet en veille sauf si le moteur de la porte est en train de tourner.
Il y a une variable moteurOn qui est vérifiée avant la mis en veille pour éviter que celle ci ne survienne pendant que le moteur tourne.
Bref je ne comprend pas pourquoi ça ne fonctionne pas et je suis preneur d'avis sur la question.

Merci

Bonsoir,

je pense que tu as un problème de structure de code :

 if (moteurOn)
    {
        // ...
        if (timer - timerSecu >= 3000)
        {                                                
            // ...
        }

        else if (!moteurOn)                     
        {
            // ...
        }
    }

Le test !moteurOn ne peut être vrai puisque tu es dans le code correspondant à moteurOn vrai.

je pense que tu as un problème de structure de code :

Bien vu!
En plus il suffit d'un else normal.

Quelques autres remarques

Qui empêche seuilPotarNuit d’etre Négatif?
seuilPotarNuit = seuilPotarJour - 10;dans ce cas votre lecture ne sera jamais inférieure.

Les capteurs ne sont pas en INPUT_PULLUP. Vous avez un PULLUP/DOWN externe ? Quid des rebonds ?

C’est pas très intuitif le nom de vos variables if (!porteFermee && !secu)                            // Si la porte est fermée ...ça se lit « si pas porteFermée et... » et le commentaire dit qu’en fait vous testez si la porte est fermée... cette variable devrait donc s’appeler porteOuverte. (En pratique votre porte à trois états, en bas, en haut, quelque part au milieu)

Salut à tous et merci pour vos réponses.

@supercc Merci ! C'est tellement évident... :o :o Je vais corriger ça... Je me doutait que c'etais quelques chose du genre mais la preuve est que je n'ai pas été attentif, j'ai presque honte .
Comme ça ça devrais le faire :

if (moteurOn)
    {
        // ...
        if (timer - timerSecu >= 3000)
        {                                                
            // ...
        }
    }
        else               
        {
            // ...
        }

@J-M-L

  • Oui, j'ai bien fait en sorte que seuilPotarNuit ne puisse être inférieur à seuilPotarJour. Dans une première version je n'avais pas fait ça et selon comment étaient réglés les potars je pouvait me trouver dans une situation ou la valeur lue par la cellule était à la fois supérieure au seuil d'ouverture et inférieure à celui de fermeture. Du coup la porte s'ouvraient et se fermait en boucle... C'est pas très élégant mais ça fonctionne comme ça.

  • Oui j'ai des PULLUP externes.

  • Non ce n'est pas très intuitif mais c'est parce-que que j'utilise des capteurs à effet Hall comme fin-de-course, et c'est capteurs sont à 0 quand excités.

porteFermee == 0
ou
!porteFermee

Indique donc bien que l'aimant est devant le capteur, donc que la porte est fermée. C'est effectivement source de confusion et ça n'aide pas à rendre le code clair...

Yourix:

  • Non ce n'est pas très intuitif mais c'est parce-que que j'utilise des capteurs à effet Hall comme fin-de-course, et c'est capteurs sont à 0 quand excités.
porteFermee == 0

ou
!porteFermee



Indique donc bien que l'aimant est devant le capteur, donc que la porte est fermée. C'est effectivement source de confusion et ça n'aide pas à rendre le code clair...

Dans ce cas on définit une variable etatPorte et des états PORTE_FERMEE et PORTE_OUVERTE comme ça c'est clair et transparent quelque soit le matériel.

#define PORTE_OUVERTE 1
#define PORTE_FERMEE 0
boolean etatPorte;

....
etatPorte = PORTE_OUVERTE;
.....
if (etatPorte==PORTE_FERMEE)
...

Et si demain tu changes le matériel il suffit juste de modifier les 2 define et tu n'as pas d'autre modification de code

fdufnews:
Dans ce cas on définit une variable etatPorte et des états PORTE_FERMEE et PORTE_OUVERTE comme ça c'est clair et transparent quelque soit le matériel.

#define PORTE_OUVERTE 1

#define PORTE_FERMEE 0
boolean etatPorte;

....
etatPorte = PORTE_OUVERTE;
.....
if (etatPorte==PORTE_FERMEE)
...




Et si demain tu changes le matériel il suffit juste de modifier les 2 define et tu n'as pas d'autre modification de code

Ça peut marcher comme
Cela en effet mais si on veut être sémantiquement correct on ne mélange pas les torchons et les serviettes. Un booléen est une valeur de vérité, c'est true ou false, pas 0 ou 1 (qui sont ensuite promu en valeur de vérité). et au lieu d'utiliser des #define, on préfèrera un enum typé ce qui permettra ensuite une vérification d'intégrité des tests par le compilateur.

Ok, mais ça c'est quand on sait coder :wink:
Là c'est mon premier code en dehors de quelques exos genre Blink...