Tempo ON / OFF

Bonjour la communauté !

Je sèche >:(.

Je cherche à allumé ou éteindre une LED avec une temporisation en utilisant millis car je ne veux pas la coupure de mon programme.

J'ai une sonde hygrométrique, un potentiomètres. En gros quand mon humidité est supérieur à ma consigne ma LED s'allume avec un retard de 3 secondes, et lorsque l'humidité devient inférieure elle s'éteint la aussi avec un retard de 3 secondes. J'ai réussi pour l'allumage de ma LED si l'humidité est supérieur, mais pour l'inverse, j'ai beau avoir tourné cette partie du code dans tous les sens, je n'arrive pas à obtenir le résultat voulu...

if (h > ValPotar)

{
tempoActive = 1;
tempoDepart = millis();
}

if (tempoActive == 1 )

if ((millis() - tempoDepart) >= 3000 )
{ digitalWrite (ledTest,HIGH);

delay (10);
tempoActive = 0
else
{ digitalWrite (ledTest,LOW);}

La, le else, je n'arrive pas à obtenir ce que je veux, malgré mes recherches, alors je viens demander un peut d'aide

La prochaine fois, mettre le code dans les balises adéquat, et lire les tutos sur les machines à état.

int ledTest = 3 ;
unsigned long tempoDepart ;
int etat ;
int h , ValPotar ;


void setup() {
    etat = (h>ValPotar) ? 2 : 0 ;
}

void loop() {
    // Gérer la lecture de h et ValPotar
    switch (etat) {
        case 0 : 
            if (h > ValPotar){
                tempoDepart = millis () ;
                etat = 1 ;
            }
            break ;
        case 1 : 
            if (millis()-tempoDepart > 3000) {
                digitalWrite (ledTest,HIGH) ;
                etat = 2 ;
            }
            break ;
        case 2 : 
            if (h < ValPotar) {
                tempoDepart = millis () ;
                etat = 3 ;
            }
            break ;
        case 3 : 
            if (millis()-tempoDepart > 3000) {
                digitalWrite (ledTest,LOW) ;
                etat = 0 ;
            }
            break ;
        default : while (true) ; // harakiri
    }
}

Bonjour

Désolé pour le retard !
Alors merci infiniment ! Cela fonctionne parfaitement. Me reste plus qu'à comprendre switch/case car je n'aime pas ne pas comprendre
Aussi, si je souhaite que le rétro-éclairage de mon LCD en I2C 16.2 s'active pendant X seconde lorsque la valeur du potentiomètres est modifiée, vert quel type de code doit-je m'aiguiller ?

Merci

Sécher sur une sonde hygrométrique, c'est ballot... :slight_smile:
Le switch est décrit ici

Pour l'écran tu peux utiliser millis() qui renvoie le nombre de millisecondes écoulées depuis le lancement du code. Tu crées une variable

unsigned long chrono;

et tu l'initialises juste après avoir activé ton écran:

chrono = millis();

Ensuite tu testes régulièrement s'il faut éteindre l'écran:

if (millis() - chrono > X * 1000) eteindre l'écran

Tu peux améliorer ça en utilisant un booléen qui retiendra l'état de l'écran (allumé ou éteint) afin de ne pas tester / éteindre si ce n'est pas nécessaire. Mais le principe est là.

Alors il me semble comprendre le principe, mais à quel moment mon potentiomètres rentre en jeux dans ce que vous me proposez ? Car je souhaite un rétro éclairage pendant X secondes lorsque physiquement le potentiomètres est touché, une fois ces X secondes passées le LCD s'éteint.

Merci

Tu initialises le chrono

chrono = millis();

lorsque le potentiomètre a changé de valeur.
Pour savoir s'il a changé, tu utilises une variable qui conserve sa valeur (disons valeurPotard) et tu la compares à la mesure

int lecture = analogRead(pinPotard);
if (lecture != valeurPotard) chrono = millis();
valeurPotard = lecture;

Il me semble qu'il manque une information dans le cahier des charges :slight_smile:

Et si l'humidité repasse de l'autre côté de la consigne alors qu'on est dans les trois secondes d'attente, que faut-il faire ?

Si j'ai bien compris le problème, tu veux surveiller deux choses indépendantes l'une de l'autre.
1-La sonde d'hygrométrie, avec allumage / extinction d'une LED au franchissement d'un seuil.
2-Le potentiomètre, avec allumage d'une autre led lorsque l'utilisateur modifie la valeur du potar.

Cela se fait simplement avec deux machines à état M1 et M2, que tu appelles l'une après l'autre dans ton "loop". Chaque machine a sa propre variable d'état, que tu déclares avant le "loop" ou encore en "static" dans chacune des machines.
Tant que tu n'as pas d'interaction entre l'état d'une machine sur l'évolution de l'autre, cette écriture dite "asynchrone" fonctionne bien.

loop () {
  m1 () ; // gère la sonde
  m2 () ; // gère le potentiomètre
}

Bon, la je suis perdu :cold_sweat: le mieux étant de vous partager l'intégralité de mon code, le voici t'elle qu'il était avant de vous demander un peu d'aide :
je sais il est loin d'être parfait, mais je suis qu'un amateur, maintenant je ne vous demande pas non plus de tout faire à ma place, mais de m'aiguiller dans ces briques que je n'arrive pas à integrer.

récapépéton : j’utilise une sonde DHT 22, un potentiomètre, un ecran LCD en I2C 16.2 .

le potentiomètre permet une consigne de 0 à 100%, lorsque l'hygrométrie relative passe au dessus de la consigne choisit, la LED s'éteint avec un retard de X secondes, et si l'humidité relative passe en dessous de la consigne, la LED s'allume avec un retard de X secondes.

le tout affiché sur l'écran, ce même écran dispose d'un retro éclairage "backlight" je ne veux pas que l'écran soit constamment allumé, mais simplement qu'il s'allume X secondes si le potentiomètre de consigne est manipulé (changement de valeur) . puis s'éteint après ces X secondes lorsque plus rien est touché.

/*projet d'hygrostat numérique avec lecture de température. 


/* Différentes bibliothèques */

#include <Wire.h>              //bibliothèque LCD I2C
#include<LiquidCrystal_I2C.h>  //bibliothèque LCD I2C.2
#include "DHT.h"               //bibliothèque capteur H et T.
#define DHTPIN 3               //sortie signal OUT sonde sur Digit 3
#define DHTTYPE DHT22          // DHT 22  (AM2302) définition du type de capteur ici un DHT22
                               // T de -40 à +80° et lecture RH de 0 à 100 avec +- 2% d'erreur.

DHT dht(DHTPIN, DHTTYPE); //le pin signal lié au type de sonde

// Initialisation du capteur pour un Arduino à 16mhz par défaut

LiquidCrystal_I2C lcd(0x27, 16, 2); //définition du LCD utilisé la 2 lignes 16 colonnes, 0*27 correspond a l'adresse BUS de donnée si il y à plusieurs afficheurs


int ValPotar = 0 ;       //déclaration d'une variable au potentiomètre
const int PotarPin = A0; //constante Sortie signal du potar
const int ledTest = 12;  //constante sortie relais commande
const int bouton = 2;    // constante sortie bouton pour rétroeclairage 
int etatBouton;          //lecture de l'état du bouton
int etatRelai;
int bReset = 4;          //constante sortie pour niveau HAUT pour le RESET
unsigned long tempsReset;//Variable pour timer
unsigned long tempoDepart = 0;
int tempoActive = 0;
int ValeurPrecedente;
unsigned long chrono;

void setup() 

{
lcd.init();                         // initialisation de l'afficheur
lcd.backlight ();                   //rétroéclairage ON
lcd.print ("Bonjour");      //message de bienvenue
lcd.setCursor (0, 1);
lcd.print (" initialisation");      // ...
delay (2000);
lcd.clear ();
lcd.print ("Bonjour");
lcd.setCursor (0, 1);
lcd.print ("des parametres...");
dht.begin();                        //initialisation de la sonde
pinMode (ledTest, OUTPUT);          //initialisation de la sortie
Serial.println (ledTest);
pinMode (bouton,INPUT_PULLUP);      //initialisation du bouton en entrée avec RES de PULLUP
etatBouton = HIGH ;                 //par defaut à l'etat haut

Serial.begin(9600);                 //initialisation du moniteur pour débug

delay (4000);
lcd.clear ();                       //reset de l'écran


lcd.noBacklight ();                 //retroeclairage OFF


 

}
 


  void loop()
 
  
  {
    //cette boucle permet de réinitialisé la carte toute les XX heures pour acquitter tout bug d'affichage (en milliseconde)
  tempsReset = millis ();
  Serial.print (".......temps en millisecondes : "); 
  Serial.print(tempsReset);           //timer pour moniteur serie (debug)
  Serial.print (".........");
 

  if (tempsReset > 14400000)             //réinit de la carte toutes les 4 heures
      {
      
       pinMode (bReset, OUTPUT);         //definition du D4 en sortie
       digitalWrite (bReset,HIGH );      //si la condition est respecté le D4 passe à l'état haut et le RESET est oppéré
      }

      
 else
 
 /*temps que le delai de réinitialisation n'est pas aboutie on joue la boucle de fonctionnement normal*/
 {
   {


  float h = dht.readHumidity();            //Lecture du taux d'humidité
  float t = dht.readTemperature();         //Lecture de la température en Celcius

  
  /*Stop le programme et renvoie un message d'erreur si le capteur ne renvoie aucune mesure*/
  if (isnan(h) || isnan(t)) //test de retour du signal sonde
        {
          lcd.clear ();
          lcd.backlight ();
          lcd.setCursor (0, 0);
          lcd.print ("Erreur sonde !");
          lcd.setCursor (0, 1);
          lcd.print (" verifier ");
    delay (2000);
          lcd.setCursor (0, 0);
          lcd.print (" Erreur sonde !");
          lcd.setCursor (0, 1);
          lcd.print (" ou changer ");
   delay (4000);
    return;
         }

  
  
  float hi = dht.computeHeatIndex( h);            // conversion en Celcius 
  
    ValPotar = analogRead(PotarPin);             //lecture de la valeur potentiomètre
    Serial.print(".........Valeur du potentiomètre : ");
        Serial.println(ValPotar);
    ValPotar = map(ValPotar, 0, 1024, 0, 100);   //conversion de la mesure en 1 Ko en un rapport de 0 à 100%
    delay (1);
   
         /*Envoi des mesures sur l'ecran*/
   
     lcd.setCursor(0, 0);
     lcd.print (" ");
     lcd.print ((int)h);
     lcd.print ("RH%     ");

     
     lcd.print((int)t);
     lcd.print((char)223);
     lcd.print ("C");
      
      

     lcd.setCursor(0,1);
     lcd.print (" CONSIGNE : ");
     lcd.print (ValPotar);
     lcd.print ("%");


           /*boucle qui vérifie la condition de la mesure potar comparé à la mesure sonde
           et active l'état haut ou bas du relais (LED)*/
       
         if (h  > ValPotar)

             {
            tempoActive = 1;
            tempoDepart = millis();
             }

             if (tempoActive == 1 )
             
              if ((millis() - tempoDepart) >= 3000 )
              {  digitalWrite (ledTest,HIGH);
             
              delay (10);
              tempoActive = 0;
              }
             

              else

              {  digitalWrite (ledTest,LOW);}

              
     

            
             
             

    
     {
      /*boucle qui vérifie l'etat du potar pour l'activation du retroeclairage*/
    int valActuelle = analogRead (A0);
    ValeurPrecedente = valActuelle;
   
    
        if (valActuelle != ValeurPrecedente -1)

           {
            lcd.backlight ();
           }
           
        else 
           {
            lcd.noBacklight ();
           }
          
    }
   }
  }
  }

merci ! :wink:

Effectivement, présenté comme ça une machine d'états est une bonne solution. Voir le tuto de J-M-L dans la section tutos. Sinon, ça me semble être aussi un bon cas d'utilisation du couteau suisse de Bricoleau, la bibliothèque Easyrun. Mais elle demande un peu d'effort de prise en main.

Une précision : lorsque tu dis

lorsque l'hygrométrie relative passe au dessus de la consigne choisit, la LED s'éteint avec un retard de X secondes

tu veux dire qu'elle s'éteint X secondes après le passage du seuil d'hygrométrie ?

tu veux dire qu'elle s'éteint X secondes après le passage du seuil d'hygrométrie ?

oui, le seuil lui est fixe puisque défini par le potentiomètre, l'hygrométrie est variable, de fait, la LED s'allume et reste allumé ou s'éteint est reste éteinte mais avec un retard de X seconde à chaque passage > ou < du seuil.

je vais regarder ce tuto en détail, j'ai déjà jeter un œil dessus, je ne maitrise par du tout le sujet :o .

Bonjour

Pour illustrer et expliquer, voici comment peut être codée la gestion de la led avec une machine à état easyRun

#include "easyRun.h"

//constantes
const int ledTest = 12; //LOW = allumee, HIGH = eteinte

//variables globales
int h;
int potar; 

//*****************************************************************************
//gestion de la led avec une machine à états

//on commence par pré-déclarer les fonctions qui seront associées à un etat du système
void ledInit();
void ledEteinte();
void allumageLed();
void ledAllumee();
void extinctionLed();

//déclaration de la machine à états, en lui indiquant la fonction associée à l'état initial
//cet objet execute en permanence la fonction associée à l'état en cours
stateMachine machineLed(ledInit);

void ledInit() {
  pinMode(ledTest, OUTPUT);
  digitalWrite(ledTest, HIGH); //éteindre la led
  machineLed.next(ledEteinte); //pour changer de fonction à la prochaine exécution
}

void ledEteinte() {
  if (h > potar) machineLed.next(allumageLed);
}

void allumageLed()
{
  if (h < potar) machineLed.next(ledEteinte); //retour à l'état précédent
  else if (machineLed.timeIsOver(3000)) {     //plus de trois secondes écoulées dans l'état courant
    digitalWrite(ledTest, LOW); //allumer la led
    machineLed.next(ledAllumee);
  }
}

void ledAllumee() {
  if (h < potar) machineLed.next(extinctionLed);
}

void extinctionLed()
{
  if (h > potar) machineLed.next(ledAllumee); //retour à l'état précédent
  else if (machineLed.timeIsOver(3000)) {     //plus de trois secondes écoulées dans l'état courant
    digitalWrite(ledTest, HIGH); //éteindre la led
    machineLed.next(ledEteinte);
  }
}

//*****************************************************************************

void setup()
{
// ...
}

void loop()
{
  easyRun(); //cette fonction se charge d'actualiser tous les objets easyRun, dont machineLed

//  ...et tout ce qu'on veut ensuite, mais sans aucun delay
}

Cette gestion ne contient aucun delay, aucun besoin de manipulation de la fonction millis()
Une fois mise au point, il n'y a plus à y retoucher, et cette gestion ne sera pas altérée par d'autres portions de code qui tourneront "en parallèle", tant que celles-ci ne contiennent aucune séquence bloquante.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.