Temporisation Aération Serre

Bonsoir à Tous,
Avec les différents projets similaires sur le forum, j'ai pompé des parties de code, ce qui me permet d'apprendre la programmation (un vrai débutant de quelques semaines), mais j'avance à petits pas.
Mon projet est de faire fonctionner l'aération d'une serre en fonction de la T° et de la position du toit (ouvert / fermé ) piloté par des capteurs fin de course, avec un affichage de la T° sur un Oled (qui fonctionne).
Avec des leds, je vois bien le fonctionnement de l'ensemble.
Je fais appel à vos lumières car je butte sur la programmation d'une temporisation de fonctionnement du moteur (en ouverture ou en fermeture) au cas où il y ait un dysfonctionnements mécanique ( arbre de transmission cassé) ou électrique (défaut des capteurs fin de course)
J'ai bien essayé plusieurs option mais sans succès, la dernière version est à la ligne 137 du code
Je vous joins mon fichier .ino
Merci par avance de vos propositions

Aeration_lcd_20_4.ino (5.45 KB)

vous devriez initialiser tempsdebutferme au moment du déclenchement de la fermeture et il manque le digitalRead sans doute sur (MotFerme == HIGH)

  if (((T <= 25)  &&  etatcapteurbas == HIGH && etatcapteurhaut == LOW) || (([color=red]digitalRead[/color](MotFerme) == HIGH)  && (( millis() - [color=red]tempsdebutferme[/color]) >= 20000)))

c'est bien de prendre l'habitude de rajouter le mon pin dans les noms de constantes qui contiennent des pins. Comme ça on se rend compte tout de suite quand on compare un N° de pin avec HIGH ou LOW, ça met la puce à l'oreille, donc au lieu de

int MotOuvre = 8; // moteur ouverture
int MotFerme = 9; // moteur fermeture
int fin_coursebas = 10; // bouton pin 2 !!!!
int fin_coursehaut = 4; // bouton pin 4
int ledbas = 6;
int ledhaut = 5;
int buzzer = 7;

faites plutôt (en les classant dans l'ordre, ça facilite le câblage aussi)

const byte pinFinCourseHaut = 4; // bouton pin 4
const byte pinLedHaut = 5;
const byte pinLedBas = 6;
const byte pinBuzzer = 7;
const byte pinMotOuvre = 8; // moteur ouverture
const byte pinMotFerme = 9; // moteur fermeture
const byte pinFinCourseBas = 10; // bouton pin 2 !!!! <<== COMMENTAIRE IDIOT....

Bonsoir
Merci pour votre réponse rapide
Pour initialiser " tempsdebutferme " , je dois le faire dans le SETUP ou dans le LOOP après le IF (T>25) ?

PS : Le commentaire idiot ( Pin 2 !!!) est pour me rappeler à modifier mon schéma électrique initial depuis que j'ai changé ma sonde de T°...c'est vrai que cela ne fait pas "PRO", mais je suis là pour m'améliorer

Il faut mettre tempsdebutferme à jour au moment du déclenchement de la fermeture

J'ai bien essayé quelques solutions, mais je me suis perdu pour formuler la mise à jour de "tempsdebutferme"
Est-ce possible de me guider pour me remettre sur les rails ?

J'ai essayé cela qui ne fonctionne qu'une seule fois après téléversement

  // SI il fait FROID et le toit est ouvert

  if ((T <= 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)

  {

    digitalWrite(MotFerme, HIGH); // le moteur est actionné en fermeture
    tempsdebutferme = 0;

  }
  // Arret Fermeture avec capteur bas


  if ((T <= 25)  && (( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW) || (digitalRead(MotFerme == HIGH)  && (( millis() - tempsdebutferme) >= 20000))))

{

  digitalWrite(MotFerme, LOW); // le moteur est arreté en fermeture

il faut mémoriser le moment de départ, pas mettre arbitrairement 0 -> donc faire

    tempsdebutferme = millis();

puisqu'ensuite vous allez testez la durée avec

millis() - tempsdebutferme >= 20000

bien sûr il ne faut pas repasser dans l'activation moteur à chaque loop si les conditions sont validées. On active une seule fois, ensuite on laisse tourner jusqu'à ce qu'une de vos conditions d'extinction du moteur soit activée

c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)`

Bonjour
Merci pour mise sur les rails
J’ai lu votre post sur les machines à états que je comprends, mais j’ai encore du mal à le traduire dans mon projet
A savoir que le fonctionnement est lié à une valeur (température ) qui déclenche une fermeture ou une ouverture, avec des fins de course, en ajoutant une sécurité sur le moteur pour éviter une destruction mécanique du montage .
C’est similaire à un volet roulant avec une sécurité moteur.
J’avais lu un de vos échanges sur le forum avec une personne qui contrôlait son arrosage automatique et ses volets roulants sur smartphone (je n’ai pas retrouvé le post qui se situait en mai 2020), c’est là que vous indiquiez des codes pour machines à état avec mémorisation de la course parcourue. A lire cela fait rêver...mais à traduire dans mon projet c’est une autre paire de manche
J’ai encore beaucoup de travail et de lecture à faire
Vos suggestions et conseils sont les bienvenus
Merci

ce n'est pas si compliqué que cela, la machine à état pourrait ressembler à cela


On commence à l'état FERMÉ

S'il fait chaud ou qu'on reçoit la commande d'ouverture, on note l'heure et on lance le moteur. On passe dans l'état EN OUVERTURE

Dans cet état EN OUVERTURE, on attend soit un certain temps ∆t, soit que le capteur de fin de course nous dise qu'on est ouvert. Si une des 2 conditions est vue, alors on arrête le moteur et on est dans l'état OUVERT

Dans cet état OUVERT, S'il fait froid ou qu'on reçoit la commande de fermeture, on note l'heure et on lance le moteur. On passe dans l'état EN FERMETURE

Dans cet état EN FERMETURE, on attend soit un certain temps ∆t, soit que le capteur de fin de course nous dise qu'on est fermé. Si une des 2 conditions est vue, alors on arrête le moteur et on est dans l'état FERME.

On peut envisager de supporter les commandes manuelles de "contre-ordre": pendant qu'on est en mouvement on demande le mouvement inverse. Ce sont les flèches du milieu du diagramme. Dans ce cas on note l'heure, on stoppe le moteur et on le lance dans l'autre sens.

Si vous avez suivi le tuto vous devriez pouvoir créer un bout de code où vous définissez ces états et testez les transitions / exécutez les actions au bon moment.

Merci de vos suggestions, cela donne envie d'aller plus, et j'ai essayé
Avec ceci :
Votre avis ?

  enum : byte {Fermé, EnOuverture, Ouvert, EnFermeture} EtatToit;
  ...

  switch (EtatToit) {
    case Fermé:
      if ((T < 25)  && (( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW) || (millis() - tempsdebutferme >= 20000)))
      {
        digitalWrite(MotFerme, LOW); // le moteur est arreté en fermeture

      break;

    case EnOuverture:
      if ((T > 28)  &&  EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)
      {
        digitalWrite(MotOuvre, HIGH); // le moteur est actionné en ouverture
        tempsdebutouvre = millis();
      }

      break;
    case Ouvert:

      if ((T > 28)  && (( EtatCapteurBas == LOW && EtatCapteurHaut == HIGH) || (millis() - tempsdebutouvre >= 20000)))
      {
        digitalWrite(MotOuvre, LOW); // le moteur est arreté en ouverture
      }
      break;
          case EnFermeture:
      if ((T < 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)
      {
        digitalWrite(MotFerme, HIGH); // le moteur est actionné en fermeture
        tempsdebutferme = millis();
      }

      break;
  }

Bonsoir,
J'ai lu et relu votre tuto, mais je dois prendre une fausse route en effectuant la transplantation dans la codification de mon projet
Est-il possible de m'aider en examinant mon code, et en m'expliquant mes erreurs ?
En tant que retraité, je me suis lancé dans Arduino pour effectuer le remplacement de mes platines électriques qui ne fonctionnaient qu'avec des relais en cascade.
C'est un univers que souhaite découvrir
Merci par avance

Aeration_lcd_20_4_essai_swich.ino (7.58 KB)

Désolé j’avais raté la réponse
Je suis juste sur mon smartphone, je ne peux pas lire le .ino
Il a l’air suffisamment petit pour mettre le code directement ici (avec les balises de code)

Le voici :

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 // Broche de données du bus oneWire connécté sur la broche 2
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

unsigned long tempsdebutouvre  = 0;
unsigned long tempsdebutferme = 0;
OneWire oneWire_DS18B20(ONE_WIRE_BUS);// Créer une instance d'objet oneWire pour communiquer avec tous les périphériques OneWire
//OneWire oneWire(ONE_WIRE_BUS); // Instanciation de l'objet ‘oneWire’
DallasTemperature sensors(&oneWire_DS18B20);//Transmettre notre référence oneWire au
//capteur de température Dallas
#define Trans 8
float T;

const byte FinCourseHaut = 4; // bouton pin 4
const byte LedHaut = 5;
const byte LedBas = 6;
const byte Buzzer = 7;
const byte MotOuvre = 8; // moteur ouverture
const byte MotFerme = 9; // moteur fermeture
const byte FinCourseBas = 10; // bouton pin 2 !!!!
//int MotOuvre = 8; // moteur ouverture
//int MotFerme = 9; // moteur fermeture
//int fin_coursebas = 10; // bouton pin 2 !!!!
//int fin_coursehaut = 4; // bouton pin 4
//int ledbas = 6;
//int ledhaut = 5;
int EtatCapteurBas = LOW; // etat du capteur bas
int EtatCapteurHaut = LOW; // etat du capteur haut
//int buzzer = 7;
int EtatMoteur = 0; // 0=MoteurArret, 1= MoteurFerme,2= MoteurOuvre

boolean toit_ferme ;
boolean toit_ouvert;
boolean toit_milieu_course;

enum : byte {Fermer, EnOuverture, Ouvert, EnFermeture} EtatToit;

  switch (EtatToit) {
    case Fermer:
      if ((T > 28)  &&  EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)
      {
        tempsdebutouvre = millis();
        digitalWrite(MotOuvre, HIGH); // le moteur est actionné en ouverture
      }
      EtatToit = EnOuverture; //c'est le nouvel état du toit qui devient EnOuverture
      break;
    case EnOuverture:
      if ( EtatCapteurBas == LOW && EtatCapteurHaut == HIGH) //||(digitalRead(MotOuvre == HIGH) && (millis() - tempsdebutouvre >= 20000))
      {
        digitalWrite(MotOuvre, LOW); // le moteur est arreté en ouverture
      }
      EtatToit = Ouvert;
      break;
      case Ouvert:
      if ((T < 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)
      {
        tempsdebutferme = millis();
        digitalWrite(MotFerme, HIGH); // le moteur est actionné en fermeture

      }
      EtatToit = EnFermeture;
      break;

    case EnFermeture:
      if ((T < 25)  && ( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)) //|| (digitalRead(MotFerme == HIGH) && (millis() - tempsdebutferme >= 20000))))

      {
        digitalWrite(MotFerme, LOW); // le moteur est arreté en fermeture
      }
      EtatToit = Fermer;
      break;

  
  }
void mettreFermer()
{
  digitalWrite(MotFerme,LOW);
  digitalWrite(MotOuvre,LOW);
  digitalRead(EtatCapteurBas,HIGH);
  digitalRead(EtatCapteurHaut,LOW);
  EtatToit=FERMER;
}

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

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(2000);

  Serial.begin(9600);//Connection série à 9600 baud
  sensors.begin(); //Initialiser le capteur DS18B20



  pinMode(MotOuvre, OUTPUT);
  pinMode(MotFerme, OUTPUT);
  pinMode(FinCourseBas, INPUT);
  pinMode(FinCourseHaut, INPUT);
  pinMode(LedBas, OUTPUT);
  pinMode(LedHaut, OUTPUT);
  pinMode(Buzzer, OUTPUT);
  // conditions initiales
  mettreFermer();
}

void loop() { //boucle principale
  /*5-Mesure de température avec le capteur DS18B20*/
  sensors.requestTemperatures(); // Demande de mesure de température
  /*6-Affichage des mesures de température */
  Serial.print("temperature DS18b20: ");
  Serial.print(sensors.getTempCByIndex(0)); //Afficher la température mesurée par DS18B20,
  //vous pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur
  //(DS18B20) sur le bus
  Serial.println(" °C");
  Serial.println(" ");
  delay(1000);

  getTemp(); //Apelle de la fonction ‘getTemp’ mesurer la température
  AfficherTlcd(); //Apelle de la fonction ‘AfficherTlcd’ pour afficher la température sur le LCD
  EtatCapteurBas = digitalRead(FinCourseBas);
  EtatCapteurHaut = digitalRead(FinCourseHaut);
  delay (400);

  //---------------------------------------------------//  VERIF de l'état du Toit
  // verif si toit fermé

  /*if (EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)
    { toit_ferme = true;

    digitalWrite(LedBas, HIGH);

    }  // le toit est fermé
    else {
    digitalWrite(LedBas, LOW);
    toit_ferme = false;
    }


    // Vérif si toit ouvert

    if (EtatCapteurHaut == HIGH && EtatCapteurBas == LOW)
    { toit_ouvert = true;


    digitalWrite(LedHaut, HIGH);

    }  // le toit est ouvert

    else {
    digitalWrite(LedHaut, LOW);
    toit_ouvert = false;
    }


    // si le toit se trouve à mi-course

    if (EtatCapteurHaut == LOW  && EtatCapteurBas == LOW)
    { toit_milieu_course = true;

    digitalWrite (Buzzer, HIGH);  // buzzer en route
    delay (1000);
    digitalWrite (Buzzer, LOW);
    delay (10);
    }
  */

    /*  if (( EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)||(digitalRead(MotOuvre == HIGH) && (millis() - tempsdebutouvre >= 20000)))
      {
        digitalWrite(MotOuvre,LOW);
      }
    */


}


/* //____________________________________________________//   ACTIONNEMENT DU MOTEUR en Ouverture ou en Fermeture

  // SI il fait FROID et le toit est ouvert

  if ((T <= 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)

  {

   digitalWrite(MotFerme, HIGH); // le moteur est actionné en fermeture
   tempsdebutferme = 0;

  }
  // Arret Fermeture avec capteur bas


  if ((T <= 25)  && (( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW) || (digitalRead(MotFerme == HIGH)  && (( millis() - tempsdebutferme) >= 20000))))

  {

  digitalWrite(MotFerme, LOW); // le moteur est arreté en fermeture
  digitalWrite(MotOuvre,LOW); // le moteur est arrêté en Ouverture

  }

  // SI il fait CHAUD et le toit est fermé

  if ((T > 28) &&  EtatCapteurHaut == LOW && EtatCapteurBas == HIGH)
  {

  digitalWrite(MotOuvre, HIGH); // le moteur est actionné en ouverture

  }
  // Arret Ouverture avec capteur haut

  if ((T > 28)  &&  EtatCapteurHaut == HIGH && EtatCapteurBas == LOW)
  {

  digitalWrite(MotOuvre, LOW); // le moteur est arreté en ouverture

  }
*/
//____________________________________________________ GESTION PROBLEME MOTEUR

// blocage pendant la fermeture

/* if ((MotFerme == HIGH)  && (( millis() - tempsdebutferme) >= 20000))
  {
  digitalWrite(MotFerme, LOW);
  }
*/




/*5-Définition de la fonction ‘getTemp’ qui mesure la température */
void getTemp() {
  sensors.requestTemperatures(); // Demande de mesure de température
  T = sensors.getTempCByIndex(0); //Stocker la valeur de mesure dans la variable ’T’, vous
  //pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur (DS18B20)
  //sur le bus
}
void AfficherTlcd()
{
  display.clearDisplay();
  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0, 5);
  // Display static text
  display.print(T);
  display.print(" ");
  display.setTextSize(1);
  display.write(167);
  display.setTextSize(2);
  display.print("C");
  display.display();

}

Le switch doit être mis à l'intérieur d'une fonction, ou dans la boucle loop

Bonsoir,
Merci pour votre aide,
J'ai mis le Switch dans le void Loop, et maintenant avec mes contacteurs pour simuler les fins de course et les leds pour vérifier les actions du moteur en ouverture ou fermeture, cela fonctionne
J'ai nettoyé complètement le code de ce que je pensais être polluant
Avec votre œil d'expert, vous allez pouvoir me conseiller sur des modifications à envisager (suppression ou ajout)
A noter que le moteur met environ 3 secondes pour s'arrêter (en ouverture ou fermeture) après avoir basculer le fin de course : est-ce normal ?
Voici le code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 // Broche de données du bus oneWire connécté sur la broche 2
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

unsigned long tempsdebutouvre  = 0;
unsigned long tempsdebutferme = 0;
OneWire oneWire_DS18B20(ONE_WIRE_BUS);// Créer une instance d'objet oneWire pour communiquer avec tous les périphériques OneWire
//OneWire oneWire(ONE_WIRE_BUS); // Instanciation de l'objet ‘oneWire’
DallasTemperature sensors(&oneWire_DS18B20);//Transmettre notre référence oneWire au
//capteur de température Dallas
#define Trans 8
float T;

const byte pinFinCourseHaut = 4; // bouton pin 4
const byte pinLedHaut = 5;
const byte pinLedBas = 6;
const byte pinMotOuvre = 8; // moteur ouverture
const byte pinMotFerme = 9; // moteur fermeture
const byte pinFinCourseBas = 10; // bouton pin 10

int EtatCapteurBas = LOW; // etat du capteur bas
int EtatCapteurHaut = LOW; // etat du capteur haut

enum : byte {Fermer, EnOuverture, Ouvert, EnFermeture} EtatToit;

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

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(2000);

  Serial.begin(9600);//Connection série à 9600 baud
  sensors.begin(); //Initialiser le capteur DS18B20



  pinMode(pinMotOuvre, OUTPUT);
  pinMode(pinMotFerme, OUTPUT);
  pinMode(pinFinCourseBas, INPUT);
  pinMode(pinFinCourseHaut, INPUT);
  pinMode(pinLedBas, OUTPUT);
  pinMode(pinLedHaut, OUTPUT);
   // conditions initiales
  mettreFermer();
}

void loop() { //boucle principale
  /*1-Mesure de température avec le capteur DS18B20*/
  sensors.requestTemperatures(); // Demande de mesure de température
  /*2-Affichage des mesures de température */
  Serial.print("temperature DS18b20: ");
  Serial.print(sensors.getTempCByIndex(0)); //Afficher la température mesurée par DS18B20,
  //vous pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur
  //(DS18B20) sur le bus
  Serial.println(" °C");
  Serial.println(" ");
  delay(1000);

  getTemp(); //Apelle de la fonction ‘getTemp’ mesurer la température
  AfficherTlcd(); //Apelle de la fonction ‘AfficherTlcd’ pour afficher la température sur le LCD
  EtatCapteurBas = digitalRead(pinFinCourseBas);
  EtatCapteurHaut = digitalRead(pinFinCourseHaut);
  delay (400);


  switch (EtatToit) {
    case Fermer:
      if ((T > 28)  &&  EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)
      {
        
        digitalWrite(pinMotOuvre, HIGH); // le moteur est actionné en ouverture
      }
        EtatToit = EnOuverture; //c'est le nouvel état du toit qui devient EnOuverture
        break;
      case EnOuverture:
        if ( EtatCapteurBas == LOW && EtatCapteurHaut == HIGH) 
        {
          digitalWrite(pinMotOuvre, LOW); // le moteur est arreté en ouverture
        }
        EtatToit = Ouvert;
        break;
      case Ouvert:
        if ((T < 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)
        {
          
          digitalWrite(pinMotFerme, HIGH); // le moteur est actionné en fermeture

        }
        EtatToit = EnFermeture;
        break;

      case EnFermeture:
        if ((T < 25)  && ( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)) 

        {
          digitalWrite(pinMotFerme, LOW); // le moteur est arreté en fermeture
        }
        EtatToit = Fermer;
        break;

      }
  }

  void mettreFermer()
  {
    digitalWrite(pinMotFerme, LOW);
    digitalWrite(pinMotOuvre, LOW);
    EtatToit = Fermer;
  }



  /*5-Définition de la fonction ‘getTemp’ qui mesure la température */
  void getTemp() {
    sensors.requestTemperatures(); // Demande de mesure de température
    T = sensors.getTempCByIndex(0); //Stocker la valeur de mesure dans la variable ’T’, vous
    //pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur (DS18B20)
    //sur le bus
  }
  void AfficherTlcd()
  {
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(0, 5);
    // Display static text
    display.print(T);
    display.print(" ");
    display.setTextSize(1);
    display.write(167);
    display.setTextSize(2);
    display.print("C");
    display.display();

  }

Virez les delay() pour un code réactif

Bonsoir
J'ai viré tous les delay() mais cela n'a rien changé
Ai-je fais une erreur dans le code du Switch ou ailleurs ?

Oui ce n’est sans doute pas votre faute
L’appel à sensors.getTempCByIndex(0)doit prendre longtemps (750ms de mémoire à la résolution complète)

Ah ok, bon je vais m'en contenter
Par contre sans être trop pénible, je n'arrive pas à positionner correctement "tempsdebutferme = millis();" pour faire démarrer un chrono afin d'arrêter le fonctionnement du moteur après 20 seconde
J'ai essayé dans le Setup, mais cela donne un fonctionnement alternatif High et Low de 1 seconde

Je viens d'essayer autre chose qui prend bien en compte les 20 secondes, mais qui génère toujours une autre boucle sans avoir aucune autre action sur la machine à état
voici le code de mon projet

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 // Broche de données du bus oneWire connécté sur la broche 2
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

unsigned long tempsdebutouvre  = 0;
unsigned long tempsdebutferme = 0;
OneWire oneWire_DS18B20(ONE_WIRE_BUS);// Créer une instance d'objet oneWire pour communiquer avec tous les périphériques OneWire
//OneWire oneWire(ONE_WIRE_BUS); // Instanciation de l'objet ‘oneWire’
DallasTemperature sensors(&oneWire_DS18B20);//Transmettre notre référence oneWire au
//capteur de température Dallas
#define Trans 8
float T;

const byte pinFinCourseHaut = 4; // bouton pin 4
const byte pinLedHaut = 5;
const byte pinLedBas = 6;
const byte pinMotOuvre = 8; // moteur ouverture
const byte pinMotFerme = 9; // moteur fermeture
const byte pinFinCourseBas = 10; // bouton pin 10

int EtatCapteurBas = LOW; // etat du capteur bas
int EtatCapteurHaut = LOW; // etat du capteur haut

enum : byte {Fermer, EnOuverture, Ouvert, EnFermeture} EtatToit;

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

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  //delay(2000);

  Serial.begin(9600);//Connection série à 9600 baud
  sensors.begin(); //Initialiser le capteur DS18B20



  pinMode(pinMotOuvre, OUTPUT);
  pinMode(pinMotFerme, OUTPUT);
  pinMode(pinFinCourseBas, INPUT);
  pinMode(pinFinCourseHaut, INPUT);
  pinMode(pinLedBas, OUTPUT);
  pinMode(pinLedHaut, OUTPUT);
  // conditions initiales
  mettreFermer();
  tempsdebutferme = millis();
}

void loop() { //boucle principale
  /*1-Mesure de température avec le capteur DS18B20*/
  sensors.requestTemperatures(); // Demande de mesure de température
  /*2-Affichage des mesures de température */
  Serial.print("temperature DS18b20: ");
  Serial.print(sensors.getTempCByIndex(0)); //Afficher la température mesurée par DS18B20,
  //vous pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur
  //(DS18B20) sur le bus
  Serial.println(" °C");
  Serial.println(" ");
  //delay(1000);

  getTemp(); //Apelle de la fonction ‘getTemp’ mesurer la température
  AfficherTlcd(); //Apelle de la fonction ‘AfficherTlcd’ pour afficher la température sur le LCD
  EtatCapteurBas = digitalRead(pinFinCourseBas);
  EtatCapteurHaut = digitalRead(pinFinCourseHaut);
 // delay (400);


  switch (EtatToit) {
    case Fermer:
      if ((T > 28)  &&  EtatCapteurBas == HIGH && EtatCapteurHaut == LOW)
      {

        digitalWrite(pinMotOuvre, HIGH); // le moteur est actionné en ouverture
      }
      EtatToit = EnOuverture; //c'est le nouvel état du toit qui devient EnOuverture
      break;
    case EnOuverture:
      if ( EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)
      {
        digitalWrite(pinMotOuvre, LOW); // le moteur est arreté en ouverture
      }
      EtatToit = Ouvert;
      break;
    case Ouvert:
      if ((T < 25)  &&  EtatCapteurBas == LOW && EtatCapteurHaut == HIGH)
      {

        digitalWrite(pinMotFerme, HIGH); // le moteur est actionné en fermeture
        
      }
            EtatToit = EnFermeture;
      break;

    case EnFermeture:
    
      if ((T < 25)  && (( EtatCapteurBas == HIGH && EtatCapteurHaut == LOW) || ((digitalRead(pinMotFerme) == HIGH)  && (( millis() - tempsdebutferme) >= 20000))))

      {
        digitalWrite(pinMotFerme, LOW); // le moteur est arreté en fermeture
        tempsdebutferme = millis();
      }
      EtatToit = Fermer;
      break;

  }
}

void mettreFermer()
{
  digitalWrite(pinMotFerme, LOW);
  digitalWrite(pinMotOuvre, LOW);
  EtatToit = Fermer;
}



/*5-Définition de la fonction ‘getTemp’ qui mesure la température */
void getTemp() {
  sensors.requestTemperatures(); // Demande de mesure de température
  T = sensors.getTempCByIndex(0); //Stocker la valeur de mesure dans la variable ’T’, vous
  //pouvez avoir plus d'un capteur sur le même bus. 0 se réfère au premier capteur (DS18B20)
  //sur le bus
}
void AfficherTlcd()
{
  display.clearDisplay();
  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0, 5);
  // Display static text
  display.print(T);
  display.print(" ");
  display.setTextSize(1);
  display.write(167);
  display.setTextSize(2);

Il faut mettre tempsdebutferme = millis(); au moment où vous déclenchez la fermeture donc dans le case Ouvert:

Comme ça pendant toute la durée de EnFermeture vous avez dans millis()-tempsdebutferme la durée depuis le lancement de la dite fermeture

Sinon est-ce bien utile de tester à chaque fois les 2 fins de course?EtatCapteurBas == HIGH && EtatCapteurHaut == LOW=>Si un est HIGH l’autre est forcément LOW non ? Autant de tester que celui que l’on attend de toucher.