Simulateur d’ascenseur multi-étages avec gestion de file d’attente, priorité de direction, affichage LCD et contrôle Arduino pour optimisation des déplacements.
#include <LiquidCrystal.h>
// Constantes de configuration
const int NUM_PIANI = 5; // Nombre total d'étages
const int pinPulsanti[NUM_PIANI] = {2, 3, 4, 5, 6}; // Broches des boutons pour les étages
const int pinLedSu = 13; // LED direction haut
const int pinLedGiu = A0; // LED direction bas
// Brochage LCD : RS, E, D4, D5, D6, D7
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// Variables d'état
bool richieste[NUM_PIANI] = {false, false, false, false, false}; // État des demandes par étage
int pianoCorrente = 0; // Indice de l'étage actuel (base 0)
bool direzioneSu = true; // Direction actuelle : true = haut, false = bas
// Variables anti-rebond
unsigned long lastDebounceTime[NUM_PIANI] = {0,0,0,0,0};
const unsigned long debounceDelay = 50; // ms
bool lastButtonState[NUM_PIANI] = {HIGH, HIGH, HIGH, HIGH, HIGH};
// Fonction pour lire les boutons avec anti-rebond
void leggiPulsanti() {
for (int i = 0; i < NUM_PIANI; i++) {
int reading = digitalRead(pinPulsanti[i]);
if (reading != lastButtonState[i]) {
lastDebounceTime[i] = millis();
}
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
if (reading == LOW) { // Bouton pressé (INPUT_PULLUP)
richieste[i] = true; // Enregistrer la demande d'étage
}
}
lastButtonState[i] = reading;
}
}
// Fonction pour mettre à jour les LED de direction
void aggiornaLed() {
digitalWrite(pinLedSu, direzioneSu ? HIGH : LOW);
digitalWrite(pinLedGiu, direzioneSu ? LOW : HIGH);
}
// Fonction pour mettre à jour l'affichage LCD
void aggiornaDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Etage : ");
lcd.print(pianoCorrente + 1); // Affiche étage base 1
lcd.setCursor(0, 1);
lcd.print("Direction : ");
lcd.print(direzioneSu ? "Haut" : "Bas");
}
// Fonction pour trouver le prochain étage à servir dans la direction actuelle
// Retourne l'indice de l'étage ou -1 s'il n'y a pas de demandes dans cette direction
int prossimoPiano() {
if (direzioneSu) {
for (int i = pianoCorrente + 1; i < NUM_PIANI; i++) {
if (richieste[i]) return i;
}
} else {
for (int i = pianoCorrente - 1; i >= 0; i--) {
if (richieste[i]) return i;
}
}
return -1;
}
// Fonction pour vérifier s'il y a des demandes sur n'importe quel étage
bool ciSonoRichieste() {
for (int i = 0; i < NUM_PIANI; i++) {
if (richieste[i]) return true;
}
return false;
}
// Configuration initiale
void setup() {
// Configurer les broches des boutons
for (int i = 0; i < NUM_PIANI; i++) {
pinMode(pinPulsanti[i], INPUT_PULLUP);
}
// Configurer les broches des LED
pinMode(pinLedSu, OUTPUT);
pinMode(pinLedGiu, OUTPUT);
// Initialiser le LCD
lcd.begin(16, 2);
aggiornaDisplay();
aggiornaLed();
}
// Boucle principale
void loop() {
leggiPulsanti();
if (ciSonoRichieste()) {
int prossimo = prossimoPiano();
if (prossimo == -1) {
// Aucune demande dans la direction actuelle, inverser la direction
direzioneSu = !direzioneSu;
aggiornaLed();
prossimo = prossimoPiano();
}
if (prossimo != -1) {
// Simuler le déplacement de l'ascenseur vers l'étage demandé
if (pianoCorrente < prossimo) {
pianoCorrente++;
} else if (pianoCorrente > prossimo) {
pianoCorrente--;
}
aggiornaDisplay();
// Si nous sommes arrivés à l'étage demandé
if (pianoCorrente == prossimo) {
// Servir la demande
richieste[pianoCorrente] = false;
// Simuler l'ouverture des portes (delay)
delay(1000);
}
}
} else {
// Aucune demande, ascenseur à l'arrêt
aggiornaDisplay();
delay(200);
}
}