quelle est le meilleur code Arduino pour diriger le tunnel pour un operateur #include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Configuration panneau solaire
Servo servoSolaire;
#define LDR_GAUCHE A0
#define LDR_DROITE A1
int posPanneau = 90;
const int tolerance = 20;

// Configuration barrière
Servo barriere;
const int pinBarriere = 8;
const int boutonBarriere = 9;
const int angleOuvert = 0;
const int angleFerme = 90;
bool barriereOuverte = true;

// Configuration ventilation
const int ventilateurPin = 10;
const int boutonVentilateur = 11;
bool ventActif = false;

// Configuration LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adresse I2C à vérifier

// Variables anti-rebond
unsigned long dernierDebounceBarriere = 0;
unsigned long dernierDebounceVentil = 0;
const unsigned long debounceDelay = 50;
int etatPrecedentBarriere = HIGH;
int etatPrecedentVentil = HIGH;

void setup() {
  // Initialisation LCD
  lcd.init();
  lcd.backlight();
  afficherEtat();

  // Configuration panneau solaire
  servoSolaire.attach(3);
  pinMode(LDR_GAUCHE, INPUT);
  pinMode(LDR_DROITE, INPUT);
  servoSolaire.write(posPanneau);

  // Configuration barrière
  barriere.attach(pinBarriere);
  pinMode(boutonBarriere, INPUT_PULLUP);
  barriere.write(angleOuvert);

  // Configuration ventilation
  pinMode(ventilateurPin, OUTPUT);
  pinMode(boutonVentilateur, INPUT_PULLUP);
  digitalWrite(ventilateurPin, LOW);
}

void loop() {
  suivreLumiere();
  gererBarriere();
  gererVentilateur();
  delay(50);
}

void suivreLumiere() {
  int lumiereGauche = analogRead(LDR_GAUCHE);
  int lumiereDroite = analogRead(LDR_DROITE);
  int difference = lumiereGauche - lumiereDroite;

  if (abs(difference) > tolerance) {
    if (difference > 0 && posPanneau < 180) posPanneau++;
    else if (difference < 0 && posPanneau > 0) posPanneau--;
    
    servoSolaire.write(posPanneau);
    delay(15);
  }
}

void gererBarriere() {
  int lecture = digitalRead(boutonBarriere);
  
  if (lecture != etatPrecedentBarriere) {
    dernierDebounceBarriere = millis();
  }

  if ((millis() - dernierDebounceBarriere) > debounceDelay) {
    if (lecture == LOW && etatPrecedentBarriere == HIGH) {
      barriereOuverte = !barriereOuverte;
      barriere.write(barriereOuverte ? angleOuvert : angleFerme);
      afficherEtat();
    }
  }
  etatPrecedentBarriere = lecture;
}

void gererVentilateur() {
  int lecture = digitalRead(boutonVentilateur);

  if (lecture != etatPrecedentVentil) {
    dernierDebounceVentil = millis();
  }

  if ((millis() - dernierDebounceVentil) > debounceDelay) {
    if (lecture == LOW && etatPrecedentVentil == HIGH) {
      ventActif = !ventActif;
      digitalWrite(ventilateurPin, ventActif ? HIGH : LOW);
      afficherEtat();
    }
  }
  etatPrecedentVentil = lecture;
}

void afficherEtat() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Barriere: ");
  lcd.print(barriereOuverte ? "Ouverte " : "Fermee  ");
  
  lcd.setCursor(0, 1);
  lcd.print("Ventilo: ");
  lcd.print(ventActif ? "ON " : "OFF");
}/**
 * Code de contrôle unifié pour tunnel
 * Fonctionnalités:
 * - Contrôle de barrière (ouverture/fermeture)
 * - Contrôle de ventilation (marche/arrêt)
 * - Suivi solaire pour panneau photovoltaïque
 * - Affichage LCD pour l'état du système
 */

#include <Servo.h>
#include <LiquidCrystal.h>

// Configuration LCD (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

// Définition des servomoteurs
Servo barriere;      // Servo pour la barrière
Servo servoSolaire;  // Servo pour le panneau solaire

// Définition des broches
#define LDR_GAUCHE A0          // Capteur de lumière gauche
#define LDR_DROITE A1          // Capteur de lumière droite
const int SERVO_BARRIERE = 8;  // Broche pour le servo de la barrière
const int SERVO_SOLAIRE = 9;   // Broche pour le servo du panneau solaire
const int BOUTON_BARRIERE = 10;    // Bouton pour contrôler la barrière
const int BOUTON_VENTILATEUR = 11; // Bouton pour contrôler le ventilateur
const int VENTILATEUR_PIN = 12;    // Contrôle du ventilateur (via relais)

// Constantes pour les angles de la barrière
const int ANGLE_OUVERT = 0;    // Angle barrière ouverte
const int ANGLE_FERME = 90;    // Angle barrière fermée

// Variables pour le suivi solaire
int positionSolaire = 90;      // Position initiale du servo panneau solaire (face au sud)
int toleranceSolaire = 20;     // Tolérance pour éviter les mouvements inutiles

// Variables d'état
bool barriereOuverte = true;   // État initial de la barrière (ouverte)
bool ventOn = false;           // État initial du ventilateur (éteint)

// Variables pour l'anti-rebond des boutons
bool dernierEtatBoutonBarriere = HIGH;
bool dernierEtatBoutonVentilateur = HIGH;
unsigned long dernierDebounceTimeBarriere = 0;
unsigned long dernierDebounceTimeVentilateur = 0;
const unsigned long delaiAntiRebond = 50; // Anti-rebond 50 ms

// Fonction d'initialisation
void setup() {
  // Configuration de l'écran LCD
  lcd.begin(16, 2);
  
  // Configuration des servomoteurs
  barriere.attach(SERVO_BARRIERE);
  servoSolaire.attach(SERVO_SOLAIRE);
  
  // Configuration des entrées/sorties
  pinMode(LDR_GAUCHE, INPUT);
  pinMode(LDR_DROITE, INPUT);
  pinMode(BOUTON_BARRIERE, INPUT_PULLUP);
  pinMode(BOUTON_VENTILATEUR, INPUT_PULLUP);
  pinMode(VENTILATEUR_PIN, OUTPUT);
  
  // Initialisation des actionneurs
  barriere.write(ANGLE_OUVERT);        // Barrière ouverte au démarrage
  servoSolaire.write(positionSolaire); // Panneau solaire en position initiale
  digitalWrite(VENTILATEUR_PIN, LOW);  // Ventilateur éteint au démarrage
  
  // Affichage initial sur LCD
  afficherEtat();
  
  // Initialisation de la communication série (pour debug)
  Serial.begin(9600);
  Serial.println("Système de contrôle tunnel initialisé");
}

// Boucle principale
void loop() {
  // Gestion de la barrière
  gererBarriere();
  
  // Gestion du ventilateur
  gererVentilateur();
  
  // Gestion du suivi solaire
  gererSuiviSolaire();
  
  // Court délai pour limiter la fréquence d'exécution
  delay(10);
}

// Fonction de gestion de la barrière
void gererBarriere() {
  int lectureBoutonBarriere = digitalRead(BOUTON_BARRIERE);
  
  // Détection de changement d'état avec anti-rebond
  if (lectureBoutonBarriere != dernierEtatBoutonBarriere) {
    dernierDebounceTimeBarriere = millis();
  }
  
  if ((millis() - dernierDebounceTimeBarriere) > delaiAntiRebond) {
    // Si le bouton vient d'être pressé
    if (lectureBoutonBarriere == LOW && dernierEtatBoutonBarriere == HIGH) {
      // Inverser l'état de la barrière
      barriereOuverte = !barriereOuverte;
      
      // Positionner le servomoteur selon l'état
      if (barriereOuverte) {
        barriere.write(ANGLE_OUVERT);
        Serial.println("Barrière ouverte");
      } else {
        barriere.write(ANGLE_FERME);
        Serial.println("Barrière fermée");
      }
      
      // Mise à jour de l'affichage LCD
      afficherEtat();
    }
  }
  
  dernierEtatBoutonBarriere = lectureBoutonBarriere;
}

// Fonction de gestion du ventilateur
void gererVentilateur() {
  int lectureBoutonVentilateur = digitalRead(BOUTON_VENTILATEUR);
  
  // Détection de changement d'état avec anti-rebond
  if (lectureBoutonVentilateur != dernierEtatBoutonVentilateur) {
    dernierDebounceTimeVentilateur = millis();
  }
  
  if ((millis() - dernierDebounceTimeVentilateur) > delaiAntiRebond) {
    // Si le bouton vient d'être pressé
    if (lectureBoutonVentilateur == LOW && dernierEtatBoutonVentilateur == HIGH) {
      // Inverser l'état du ventilateur
      ventOn = !ventOn;
      
      // Piloter le relais selon l'état
      digitalWrite(VENTILATEUR_PIN, ventOn ? HIGH : LOW);
      
      Serial.println(ventOn ? "Ventilateur ON" : "Ventilateur OFF");
      
      // Mise à jour de l'affichage LCD
      afficherEtat();
    }
  }
  
  dernierEtatBoutonVentilateur = lectureBoutonVentilateur;
}

// Fonction de gestion du suivi solaire
void gererSuiviSolaire() {
  // Lecture des capteurs de lumière
  int valGauche = analogRead(LDR_GAUCHE);
  int valDroite = analogRead(LDR_DROITE);
  
  // Calcul de la différence de luminosité
  int diff = valGauche - valDroite;
  
  // Ajustement de la position si la différence dépasse la tolérance
  if (abs(diff) > toleranceSolaire) {
    if (diff > 0 && positionSolaire < 180) {
      positionSolaire++; // Tourner vers la gauche
    } else if (diff < 0 && positionSolaire > 0) {
      positionSolaire--; // Tourner vers la droite
    }
    
    // Appliquer la nouvelle position au servo
    servoSolaire.write(positionSolaire);
    delay(15); // Mouvement progressif
  }
}

// Fonction d'affichage sur LCD
void afficherEtat() {
  lcd.clear();
  
  // Ligne 1: État de la barrière
  lcd.setCursor(0, 0);
  lcd.print("Barriere: ");
  lcd.print(barriereOuverte ? "Ouverte" : "Fermee ");
  
  // Ligne 2: État du ventilateur
  lcd.setCursor(0, 1);
  lcd.print("Ventilateur: ");
  lcd.print(ventOn ? "ON  " : "OFF ");
}