Problème de variable avec switch case

Bonjour.

Je suis actuellement en stage et je travaille sur un projet de système d'ouverture et de fermeture pour poulailler. Je dois programmer une porte de type guillotine, qui s'ouvre et qui se ferme selon le sens de rotion du moteur piloté par des relais, en mode automatique.

Des capteurs HAUT et BAS sont intégrés pour désigner les limites d'ouverture et de fermeture de la porte, qui possèdent des contacts normalement ouverts. Ces contacts se ferment lorsqu'il détectent un aimant accroché à la porte, ce qui permet d'arrêter le moteur 1 seconde après que les contacts se ferment et pour arrêter la porte.

Je suis parvenu à programmer le mode manuel de la porte avec l'aide d'un bouton RIGHT inclûs dans l'afficheur LCD qui affiche également des données à l'écran. Dans ce mode manuel, en appuyant sur le bouton:
-la porte se ferme jusqu'au capteur BAS (+1 seconde)
-elle effectue une pause de 3 secondes
-la porte s'ouvre jusqu'au capteur HAUT (+1 seconde)
-fin du test manuel de la porte.

A présent, je cherche à faire ouvrir et fermer automatiquement la porte selon la période de la journée. J'utilise une cellule solaire pour détecter la luminosité ambiante et la convertir en tension.

Ici, j'aimerais programmer un seuil de 1V pour déterminer s'il fait jour ou nuit.

J'ai également ajouté des variables booléennes pour désigner l'état de la porte (fermée, non fermée, ouverte, non ouverte), et j'utilise la fonction millis() pour les temporisations, et des machines à états pour mes programmes.

Voilà ce que j'ai fait:

//moteur + relais + LCD + cellule + capteurs

// LCD Keypad Shield

// Modif 15

#include <LiquidCrystal.h>

// Création de l'objet lcd (avec les différents ports numériques qu'il utilise)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//variables
int lcd_key     = 0;
int adc_key_in  = 0;
int TensionBAS  = 0;
int TensionHAUT  = 0;
float TensionCelluleSolaire = 0;
float TensionMoteur = 0;

//constantes
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5


#define RelayPin1 2 //le port numérique D2 est connecté au relais 1
#define RelayPin2 3 //le port numérique D3 est connecté au relais 2
#define CapteurBAS 11 //le port numérique D11 est connecté au capteur BAS
#define CapteurHAUT 12 //le port numérique D12 est connecté au capteur HAUT

#define debugTxtVar(myParameterText, variableName) \
  Serial.print(#myParameterText " = "); \
  Serial.println(variableName);

#define debugTxtVar2(myParameterText1, variableName1, myParameterText2, variableName2) \
  Serial.print(#myParameterText1 " = "); \
  Serial.print(variableName1); \
  Serial.print(" " #myParameterText2 " = "); \
  Serial.println(variableName2);

int Etat_fonctionnement_manuel = 0;
int Etat_fermeture_auto = 0;
int Etat_ouverture_auto = 0;

unsigned long temps_fonctionnement_manuel = 0;
unsigned long temps_fermeture_auto = 0;
unsigned long temps_ouverture_auto = 0;
unsigned long temps_mesures = 0;
unsigned long temps_serie = 0;
unsigned long temps_actuel;

boolean JourVrai;   // indique si c'est le jour ou la nuit
boolean PorteOuverte = false; // indique si la porte est en position ouverte ou non
boolean PorteFermee = false; // indique si la porte est en position fermee ou non
boolean Test_manuel_demarrage = false; //indique si le test manuel de la porte est en cours ou non
boolean AUTO_Fermeture = false; //indique si la fermeture automatique de la porte est en cours ou non
boolean AUTO_Ouverture = false; //indique si l'ouverture automatique test manuel de la porte est en cours ou non

void setup()
{
  // On met les pin de chaque relais en sortie
  pinMode(RelayPin1, OUTPUT);
  pinMode(RelayPin2, OUTPUT);

  // On met les pin de chaque capteur en entrée
  pinMode(CapteurBAS, INPUT);
  pinMode(CapteurHAUT, INPUT);

  Serial.begin(9600);// ouvre le port série et fixe le debit de communication à 9600 bauds

  lcd.begin(16, 2);              // Démarrage de l'écran
  lcd.setCursor(0, 0);           // Positionnement du curseur au début
  lcd.print("Test porte"); // Message

}

void loop()
{ 
  // Sous traite les différentes tâches
  lcd_key = read_LCD_buttons();  // Lecture des touches
  task_mesure_tensions();
  task_fonctionnement_manuel();
  task_fermeture_auto();

  switch (lcd_key)               // Action en cas de touche pressée
  {
    case btnRIGHT: //en appuyant sur le bouton RIGHT
      {
        if (Etat_fonctionnement_manuel == 0 && PorteOuverte) {
          Etat_fonctionnement_manuel = 1; //on affecte la variable à 1
          Test_manuel_demarrage = true;
        }
        break;
      }
  }

  if ( digitalRead(CapteurBAS) == LOW  )//lorsque le contact du capteur BAS est fermé...
      {
        PorteFermee = true; //la porte est en position fermée
      }
      
  else 
       {
        PorteFermee = false; //la porte n'est pas en position fermée
       }

  if ( digitalRead(CapteurHAUT) == LOW  )//lorsque le contact du capteur HAUT est fermé...
      {
        PorteOuverte = true; //la porte est en position ouverte
      }

  else
      {
        PorteOuverte = false; //la porte n'est pas en position ouverte
      }

  if (TensionCelluleSolaire < 1.0 )
    { // une tension basse signifie qu'il commence à faire sombre
      JourVrai = false; //la variable passe à false lorsqu'il fait nuit
    }

  else 
      //{ // une tension haute signifie que le soleil se lève
      JourVrai = true;  //la variable passe à true lorsqu'il fait jour      
    //}

  if (!JourVrai && !PorteFermee) // s'il fait nuit mais la porte n'est pas en position fermée...
      {
        Etat_fermeture_auto = 1; //on affecte la variable à 1
        Etat_ouverture_auto = 0; //on affecte la variable à 0
      }

  if (!JourVrai && PorteFermee) // s'il fait nuit et la porte est en position fermée...
      {
        Etat_fermeture_auto = 0; //on affecte la variable à 0
        Etat_ouverture_auto = 0; //on affecte la variable à 0
      }

  if (JourVrai && !PorteOuverte) // s'il fait jour mais la porte n'est pas en position ouverte...
      {
        Etat_ouverture_auto = 1; //on affecte la variable à 1
        Etat_fermeture_auto = 0; //on affecte la variable à 0
      }

  if (JourVrai && PorteOuverte) // s'il fait jour et la porte est en position ouverte...
      {
        Etat_ouverture_auto = 0; //on affecte la variable à 0
        Etat_fermeture_auto = 0; //on affecte la variable à 0
      }

  temps_actuel = millis(); //fonction non bloquante qui indique le temps passé en millisecondes

  if ( (temps_actuel - temps_serie) >= 1000ul )//la boucle se réinitialise à chaque seconde
  {
    temps_serie = temps_actuel;

    //affiche les différentes données sur le moniteur série

    debugTxtVar2(TensionCelluleSolaire , TensionCelluleSolaire, TensionMoteur , TensionMoteur);

    debugTxtVar(JourVrai , JourVrai);

    debugTxtVar2(Etat_fonctionnement_manuel , Etat_fonctionnement_manuel, Test_manuel_demarrage , Test_manuel_demarrage);

    debugTxtVar2(AUTO_Fermeture , AUTO_Fermeture, Etat_fermeture_auto , Etat_fermeture_auto);

    debugTxtVar2(AUTO_Ouverture , AUTO_Ouverture, Etat_ouverture_auto , Etat_ouverture_auto);

    debugTxtVar2(PorteOuverte , PorteOuverte, PorteFermee , PorteFermee);

    debugTxtVar(temps_actuel , temps_actuel);
  }
}//loop

void task_mesure_tensions()//permet de prendre des mesures de tensions et d'afficher des données sur l'écran LCD
{
  temps_actuel = millis();//fonction non bloquante qui indique le temps passé en millisecondes

  if ( (temps_actuel - temps_mesures) >= 250ul ) //la boucle se réinitialise toutes les 250 ms
  {
    temps_mesures = temps_actuel;

    // Transforme la mesure (nombre entier) en tension via un produit en croix
    int CelluleSolaireCAN = analogRead(A1); // Mesure la tension aux bornes de la cellule solaire
    int MoteurCAN = analogRead(A2); // Mesure la tension consommée par le moteur

    float TensionV1 = (float)CelluleSolaireCAN * (5.0 / 1023.0);
    float TensionV2 = (float)MoteurCAN * (5.0 / 1023.0);

    lcd.setCursor(0, 1);           // Positionnement du curseur début de ligne

    //affiche les différentes données sur l'écran LCD

    if (JourVrai)
    {
      lcd.print("jour"); //affiche "jour"
    }
    else if (!JourVrai)
    {
      lcd.print("nuit"); //affiche "nuit"
    }

    lcd.print(" M");
    lcd.print(Etat_fonctionnement_manuel); //affiche la valeur de la variable

    lcd.print(" F");
    lcd.print(Etat_fermeture_auto); //affiche la valeur de la variable

    lcd.print(" O");
    lcd.print(Etat_ouverture_auto); //affiche la valeur de la variable

    TensionCelluleSolaire = TensionV1;

    TensionMoteur = TensionV2;

  }//if

}//task_mesure_tensions

void FermerMoteur() {//fait tourner le moteur dans un sens pour fermer la porte
  digitalWrite(RelayPin1, LOW); //le relais 1 est actif
  digitalWrite(RelayPin2, HIGH); //le relais 2 est inactif
}

void ArretMoteur() {//met le moteur en pause et stoppe la porte
  digitalWrite(RelayPin1, HIGH); //le relais 1 est inactif
  digitalWrite(RelayPin2, HIGH); //le relais 2 est inactif
}

void OuvrirMoteur() {//fait tourner le moteur dans l'autre sens pour ouvrir la porte
  digitalWrite(RelayPin1, HIGH); //le relais 1 est inactif
  digitalWrite(RelayPin2, LOW); //le relais 2 est actif
}

void task_fonctionnement_manuel()//permet d'activer le test de fonctionnement manuel de la porte
{
  temps_actuel = millis();//fonction non bloquante qui indique le temps passé en millisecondes

  switch ( Etat_fonctionnement_manuel )
  {
    case    1:
      // Après l'appui du bouton, le moteur tourne dans un sens et la porte commence à se fermer...
      FermerMoteur();
      temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
      Etat_fonctionnement_manuel++;// on incrémente la variable de 1

      break;

    case    2:
      if (PorteFermee) //lorsqu'on détecte la porte en position fermée...
      {
        //on lance une temporisation d'une seconde pour être sûr qu'elle soit bien fermée
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
        Etat_fonctionnement_manuel++;// on incrémente la variable de 1

      }//if

      break;

    case    3:
      if ((temps_actuel - temps_fonctionnement_manuel) >= 1000ul) //une fois la temporisation achevée...
      {
        //...le moteur se met en pause et la porte s'arrête
        ArretMoteur();
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
        Etat_fonctionnement_manuel++;// on incrémente la variable de 1

      }//if

      break;

    case    4:
      if ( (temps_actuel - temps_fonctionnement_manuel) >= 3000ul )
      {
        // une fois les 3 secondes de pause passées, on ouvre la porte
        OuvrirMoteur();
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
        Etat_fonctionnement_manuel++;// on incrémente la variable de 1

      }//if

      break;

    case    5:
      if (PorteOuverte) //lorsqu'on détecte la porte en position ouverte...
      {
        //on lance une temporisation d'une seconde pour être sûr qu'elle soit bien ouverte
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
        Etat_fonctionnement_manuel++;// on incrémente la variable de 1

      }//if

      break;

    case    6:
      if ( (temps_actuel - temps_fonctionnement_manuel) >= 1000ul )//une fois la temporisation achevée...
      {
        //...le moteur se met en pause et la porte s'arrête
        ArretMoteur();
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
        Etat_fonctionnement_manuel = 0;//on affecte la variable à 0
        Test_manuel_demarrage = false; //le test manuel de la porte est terminé

      }//if

      break;  

  }//switch

}//task_fonctionnement_manuel

void task_fermeture_auto//permet de fermer la porte automatiquement
()//permet d'activer le test de fonctionnement manuel de la porte
{
  temps_actuel = millis();//fonction non bloquante qui indique le temps passé en millisecondes

  switch ( Etat_fermeture_auto)
  {
    case    1:
    if ( (temps_actuel - temps_fermeture_auto) >= 10000ul )
    {
      // Au bout de 10 secondes...
      temps_fermeture_auto = temps_actuel;//on réinitialise le temps passé à 0 ms
      Etat_fermeture_auto++;// on incrémente la variable de 1
    }
      break;

    case    2:     
        //on ferme la porte indéfiniment
        FermerMoteur();
        temps_fonctionnement_manuel = temps_actuel;//on réinitialise le temps passé à 0 ms
      break;

  }//switch

}//task_fermeture_auto

// Fonction de lecture des touches
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);   // Lecture du port analogique

  // Les valeurs qui suivent doivent être adaptées au shield
  if (adc_key_in > 1000) return btnNONE;   // En principe 1023 quand aucune touche n'est pressée
  if (adc_key_in < 50)   return btnRIGHT;     // 0
  if (adc_key_in < 195)  return btnUP;        // 99
  if (adc_key_in < 380)  return btnDOWN;      // 255
  if (adc_key_in < 555)  return btnLEFT;      // 409
  if (adc_key_in < 790)  return btnSELECT;    // 640

  return btnNONE;
}

Pour l'instant, j'essaie d'effectuer un test de fermeture automatique, où s'il fait nuit mais que la porte n'est pas complétement fermée, cela lance une temporisation de 10 secondes où, une fois écoulée, permet de faire fermer la porte.

J'utilise également le moniteur série pour faire afficher mes données:

image

Comme prévu, la variable Etat_fermeture_auto passe à 1 lorsqu'il fait nuit mais que la porte n'est pas encore fermée.

image

Cependant, après 10 secondes, la variable reste à 1 au lieu d'être affecté à 2 pour fermer la porte.

J'utilise une switch case pour cette fonction de mon programme, mais également pour la fonction task_fonctionnement_manuel pour le test manuel de la porte, où Etat_fonctionnement_manuel passe bien à 1 à l'appui du bouton, ce qui fait fermer la porte.

Comment ça se fait ?

Aurais-je fait une erreur quelque part ? Est-ce liée à la temporisation de 10 secondes ?

J'ai besoin d'aide SVP

hello
voici ton code un peu revu, je ne sais pas s'il fonctionne,( non uisque je t'ai laissé une fonction à finir) mais en fouillant tu verras une façon de travailler en automatique
les_poules.zip (5,9 Ko)
nota: ta facon de coder n'est pas simple.....

pourquoi convertir le retour de la ldr qui peut etre de 0 à 1023. il suffirait de comparer sa valeur à une valeur seuil, sans faire de conversion vers une tension

j'ai passé les FDC en INPUT_PULLUP

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