AeroTempo : Différence entre versions
Ligne 25 : | Ligne 25 : | ||
Le code source commenté à héberger sur une carte Arduino Uno ou Duomilanove : | Le code source commenté à héberger sur une carte Arduino Uno ou Duomilanove : | ||
− | < | + | <code> |
− | AeroTempo. | + | /****************************************************** |
− | </ | + | AeroTempo : Temporisateur pour aérateur de toilettes |
+ | Principe : 1) A la détection de l'apparition de la lumière dans les toilettes : | ||
+ | 2) - mise en route d'une première temporisation t1, | ||
+ | 3) - mise en route du ventilagteur/extracteur via un relai 220v | ||
+ | 4) A la disparition de la lumière : | ||
+ | 5) - mise en route d'une seconde temporisation t2, | ||
+ | 6) - extinction du ventilateur. | ||
+ | |||
+ | Version V0 : Montage initial pour test(POC), t1 = 1 min., t2 = 2 min. fixées en dur dans le code | ||
+ | Utilisation d'un écran LCD inspiré de l'exemple Hello Word de la librairie LyquidCryqtal de l'ID Arduino | ||
+ | |||
+ | The circuit: | ||
+ | * LCD VSS pin (1) to ground | ||
+ | * LCD Vdd pin (2) to 5V | ||
+ | * 10K resistor (j'ai mis un potentiomètre pour régler le contraste : | ||
+ | * ends to +5V and ground | ||
+ | * wiper to LCD VO pin (3) | ||
+ | * LCD RS pin (4) to digital pin 12 Arduino | ||
+ | * LCD R/W pin (5) to ground | ||
+ | * LCD Enable pin (6) to digital pin 11 | ||
+ | * LCD DB4 pin (11) to digital pin 5 | ||
+ | * LCD DB5 pin (12) to digital pin 4 | ||
+ | * LCD DB6 pin (13) to digital pin 3 | ||
+ | * LCD DB7 pin (14) to digital pin 2 | ||
+ | |||
+ | |||
+ | Version V0a : Reprise du code de l'exemple Hello Word de la librairie LyquidCryqtal de l'IDE Arduino | ||
+ | Version V0b : Intégraion de la LDR (selon mon cours au MDC) et intégration du relai | ||
+ | Le Circuit : | ||
+ | * LDR en série avec R1k entre +5v et Gnd | ||
+ | * Point milieu avec A0 | ||
+ | * Relay +5v et Gnd et In1 avec broche 7 | ||
+ | Version V0c : Mise en place des deux temporisations (en dur dans le code) | ||
+ | * t1 => délai d'attente après l'établissement de la lumière avant déclenchement de l'aérateur | ||
+ | * (pour éviter le déclenchement sur une simple ouverture de porte de courte durée) | ||
+ | * t2 => temps de fonctionnement de l'aérateur après l'extinction de la lumière | ||
+ | * Recours à un automate d'états finis cf. | ||
+ | * https://forum.arduino.cc/t/programmation-automate-fini-machine-a-etat/452532/5 | ||
+ | Version V0d : | ||
+ | - Mise en place d'un reset matériel | ||
+ | * Le circuit : | ||
+ | * R2k entre la broche 8 et le Reset | ||
+ | * /!\ Attention à ne pas utiliser la broche 13 qui est en PullUp et repasse à 0 à chaque Reset, | ||
+ | * donc le premier Soft Reset déclenche une infinité de Reset => la carte reste bloquée et ne redémarre pas ! | ||
+ | - Passage de l'affichage en pourcentage de luminosité : | ||
+ | 0% Nuit noire (1023 lu sur la LDR) | ||
+ | 100% Pleine lumière (0 lu sur la LDR) | ||
+ | - Mise en place d'un mode Run et d'un mode Test : | ||
+ | qui permet une modification des valeurs des tempos | ||
+ | Changement de mode par un PushButton à bascule sur la broche 9 | ||
+ | Version V0e : | ||
+ | - Le mode initial et après chaque reset est Run | ||
+ | - Renommage du mode Test en mode Test (t) | ||
+ | - Affichage de la tempo à rebours (décompte) pendant les états etT1 et etT2 | ||
+ | *******************************************************************************/ | ||
+ | |||
+ | // include the library code: | ||
+ | #include <LiquidCrystal.h> | ||
+ | |||
+ | // initialize the library by associating any needed LCD interface pin | ||
+ | // with the arduino pin number it is connected to | ||
+ | const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; | ||
+ | const int LdrAnalogIn = A0; | ||
+ | const int RelayPin = 7; // Broche IN1 du relay qui pilote l'aérateur | ||
+ | const int ModePin = 9; // Broche du PushButton de changement de Mode | ||
+ | const String FirmWareVersion = "v0e"; // Version du FirmWare pour l'affichage | ||
+ | |||
+ | int LdrValue = 0; // Valeur lue sur la LDR (Valeur faible = forte luminosité) | ||
+ | int Col = 0; // Numéro de la colonne pour l'écriture sur l'écran LCD (entre 0 et 15) | ||
+ | unsigned long TimeStamp = 0; // Top Chrono pour suivre l'écoulement des délais t1 et t2 | ||
+ | unsigned long timer = 0; // Permet l'affichage du temps qui s'écoule | ||
+ | |||
+ | int t1; // Tempo (en secondes) entre détection de la lumière et mise en route de l'aérateur | ||
+ | int t2; // Tempo (en secondes) entre extinction de la lumière et arrêt de l'aérateur | ||
+ | unsigned long T; // Tempo (en secondes) entre deux Reset de la carte | ||
+ | |||
+ | // Création de l'afficheur LCD1604 | ||
+ | LiquidCrystal lcd(rs, en, d4, d5, d6, d7); | ||
+ | |||
+ | // Définition des deux modes de fonctionnement | ||
+ | enum :boolean {Test, Run} mode; | ||
+ | |||
+ | // Définition des 4 états de l'automate | ||
+ | enum :byte {etOff,etT1,etOn,etT2} etat; | ||
+ | |||
+ | // Définition des 4 événements | ||
+ | boolean evLightOn() { // Apparition de la lumière | ||
+ | // Lecture de la luminosité | ||
+ | LdrValue = analogRead(LdrAnalogIn); | ||
+ | lcd.setCursor(0,1); // On place le curseur en début de ligne 1 | ||
+ | lcd.print(100-int(LdrValue/10.23)); // On affiche le pourcentage de luminosité à partir de la valeur lue sur la LDR : (0<LDR<1023) | ||
+ | lcd.print("% "); // Pour effacer l'unité au cas où la valeur diminue d'un ordre de grandeur. | ||
+ | if (LdrValue < 500) { | ||
+ | return true; | ||
+ | } else { | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | boolean evLightOff() { // Disparition de la lumière | ||
+ | return !evLightOn(); | ||
+ | } | ||
+ | |||
+ | boolean evT1Out() { // Fin de la tempo T1 | ||
+ | if (millis()/1000 - TimeStamp > t1) { | ||
+ | return true; | ||
+ | } else { | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | boolean evT2Out() { // Fin de la tempo T2 | ||
+ | if (millis()/1000 - TimeStamp > t2) { | ||
+ | return true; | ||
+ | } else { | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Cette fonction effectue un effaçage du Timer | ||
+ | // quelque soit sa longueur ( entre 1 et 5 caractères) | ||
+ | void effaceTimer() { | ||
+ | lcd.setCursor(11,1); | ||
+ | lcd.print(" "); | ||
+ | } | ||
+ | |||
+ | // Cette fonction effectue un Reset matériel | ||
+ | void pushReset() { | ||
+ | int resetPin = 8; //!\\ ne pas utiliser la broche 13 cf. commentaires en intro | ||
+ | pinMode(resetPin, OUTPUT); // active la broche en sortie (OUTPUT) ce qui déclenche le reset | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | // Détermination des modes pour les broches | ||
+ | pinMode(LdrAnalogIn,INPUT); | ||
+ | pinMode(RelayPin,OUTPUT); | ||
+ | pinMode(ModePin,INPUT); | ||
+ | |||
+ | // Initialisation de la liaison série | ||
+ | Serial.begin(115200); | ||
+ | |||
+ | // Paramétrage du LCD : Nb de colonnes, Nb de lignes | ||
+ | lcd.begin(16, 2); | ||
+ | // Affichage de la version du FirmWare. | ||
+ | lcd.print("AeroTempo"); | ||
+ | lcd.setCursor(7,1); | ||
+ | lcd.print(FirmWareVersion); | ||
+ | |||
+ | // Initialisation de l'automate | ||
+ | etat = etOff; | ||
+ | TimeStamp = 0; | ||
+ | mode = Run; | ||
+ | Serial.println("AeroTempo"); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | // Reglage du Bug d'affichage : Cetrainment un parasite sur la broche 11 (Enable) qui reset l'afficheur | ||
+ | digitalWrite(11,LOW); | ||
+ | |||
+ | // Détection du changement de mode entre Run et Test | ||
+ | if (digitalRead(ModePin) == HIGH) { | ||
+ | Serial.print(mode + " Bip "); | ||
+ | |||
+ | if (mode == Test) { | ||
+ | mode = Run; | ||
+ | } else { | ||
+ | mode = Test; | ||
+ | } | ||
+ | Serial.println(mode); | ||
+ | } | ||
+ | |||
+ | // Détermination des paramètres de tempo selon le mode (Run ou Test) | ||
+ | switch (mode) { | ||
+ | case Test : | ||
+ | t1 = 5; | ||
+ | t2 = 10; | ||
+ | T = 50; | ||
+ | break; | ||
+ | |||
+ | case Run : | ||
+ | t1 = 60; | ||
+ | t2 = 300; | ||
+ | T = 86400; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | // Coeur de l'automate d'états finis | ||
+ | switch (etat) { | ||
+ | case etOff : | ||
+ | lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 | ||
+ | lcd.print("Off"); // On affiche l'état | ||
+ | digitalWrite(RelayPin,HIGH); // On arrète l'aérateur | ||
+ | if (evLightOn()) { // la lumière est-elle allumée ? | ||
+ | TimeStamp = millis()/1000; // On note le top départ de t1 | ||
+ | etat = etT1; // l'automate change d'état | ||
+ | } | ||
+ | timer = (millis()/1000 - TimeStamp); | ||
+ | break; | ||
+ | |||
+ | case etT1 : | ||
+ | lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 | ||
+ | lcd.print(" T1"); // On affiche l'état | ||
+ | if (evLightOff()) { // la lumière est-elle éteinte ? | ||
+ | TimeStamp = 0; | ||
+ | etat = etOff; // l'automate change d'état | ||
+ | } else if (evT1Out()){ // le délai de t1 est-il expiré ? | ||
+ | // (i.e. la lumière est-elle établie depuis suffisamment longtemps (t1 secondes) | ||
+ | TimeStamp = 0; | ||
+ | etat = etOn; // l'automate change d'état | ||
+ | } | ||
+ | timer = t1-(millis()/1000 - TimeStamp); | ||
+ | break; | ||
+ | |||
+ | case etOn : | ||
+ | lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 | ||
+ | lcd.print(" On"); // On affiche l'état | ||
+ | digitalWrite(RelayPin,LOW); // On met en route l'aérateur | ||
+ | if (evLightOff()) { // la lumière est-elle éteinte ? | ||
+ | TimeStamp = millis()/1000; // On note le top départ de t2 | ||
+ | etat = etT2; // l'automate change d'état | ||
+ | } | ||
+ | timer = (millis()/1000 - TimeStamp); | ||
+ | break; | ||
+ | |||
+ | case etT2 : | ||
+ | lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 | ||
+ | lcd.print(" T2"); // On affiche l'état | ||
+ | if (evT2Out()) { // le délai T2 est-il expiré ? | ||
+ | // (i.e. la lumière est-elle éteinte depuis suffisamment longtemps (t2 secondes) | ||
+ | TimeStamp = 0; | ||
+ | etat = etOff; // l'automate change d'état | ||
+ | } else if (evLightOn()) { | ||
+ | TimeStamp = 0; // On reset le TimeStamp | ||
+ | etat = etOn; | ||
+ | } | ||
+ | timer = t2 - (millis()/1000 - TimeStamp); | ||
+ | break; | ||
+ | } // fin du switch case sur l'état de l'automate | ||
+ | |||
+ | // Détermination de la colone où débute l'affichage du Timer | ||
+ | //timer = (millis()/1000 - TimeStamp); | ||
+ | if (timer < 10) { | ||
+ | Col = 15; | ||
+ | } else if (timer < 100) { | ||
+ | Col = 14; | ||
+ | } else if (timer < 1000) { | ||
+ | Col = 13; | ||
+ | } else if (timer < 10000) { | ||
+ | Col = 12; | ||
+ | } else if (timer < 100000) { | ||
+ | Col = 11; | ||
+ | } | ||
+ | |||
+ | // Affichage du mode | ||
+ | lcd.setCursor(12,0); | ||
+ | if (mode == Test) { | ||
+ | lcd.print("t"); | ||
+ | } else { | ||
+ | lcd.print("r"); | ||
+ | } | ||
+ | |||
+ | // Affichage du timer | ||
+ | effaceTimer(); | ||
+ | lcd.setCursor(Col,1); | ||
+ | lcd.print(timer); | ||
+ | |||
+ | // Reset régulier bout T secondes | ||
+ | if (millis()/1000 > T) { | ||
+ | pushReset(); | ||
+ | } | ||
+ | |||
+ | Serial.println(digitalRead(ModePin)); | ||
+ | } | ||
+ | </code> |
Version du 26 décembre 2021 à 19:17
Temporisateur d'aérateur de toilettes
Contributeur·ice·s
Statut du projet
Fonctionnel
Statut de la publication
Brouillon
License
CC-by-sa-3.0 - Creative Commons Attribution CC-by-sa-3.0 France
Inspiration
Fichiers source
AeroTempoV0e.ino
Machines
Matériaux
Lien
Cet article décrit la réalisation d'un temporisateur pour aération de toilettes. Le principe est de détecter l'entrée dans les toilettes pas l'allumage de la lumière. Cet allumage déclenche une première temporisation à l'issue de laquelle, si la lumière ne s'éteint pas, l'aérateur se déclenche pour une seconde temporisation. A l'issue de cette seconde temporisation, si la lumière ne se rallume pas, l'aérateur s'éteint.
Techniquement, l'AéroTempo est basé sur un automate d'états finis à 4 états et 4 transitions.
Les 4 états : Off, T1, On, T2
Les 4 transitions : LightOn, LightOff, FinT1, FinT2
Le schéma de l'automate est le suivant :
Le code source commenté à héberger sur une carte Arduino Uno ou Duomilanove :
/******************************************************
AeroTempo : Temporisateur pour aérateur de toilettes Principe : 1) A la détection de l'apparition de la lumière dans les toilettes : 2) - mise en route d'une première temporisation t1, 3) - mise en route du ventilagteur/extracteur via un relai 220v 4) A la disparition de la lumière : 5) - mise en route d'une seconde temporisation t2, 6) - extinction du ventilateur. Version V0 : Montage initial pour test(POC), t1 = 1 min., t2 = 2 min. fixées en dur dans le code Utilisation d'un écran LCD inspiré de l'exemple Hello Word de la librairie LyquidCryqtal de l'ID Arduino
The circuit: * LCD VSS pin (1) to ground * LCD Vdd pin (2) to 5V * 10K resistor (j'ai mis un potentiomètre pour régler le contraste : * ends to +5V and ground * wiper to LCD VO pin (3) * LCD RS pin (4) to digital pin 12 Arduino * LCD R/W pin (5) to ground * LCD Enable pin (6) to digital pin 11 * LCD DB4 pin (11) to digital pin 5 * LCD DB5 pin (12) to digital pin 4 * LCD DB6 pin (13) to digital pin 3 * LCD DB7 pin (14) to digital pin 2
Version V0a : Reprise du code de l'exemple Hello Word de la librairie LyquidCryqtal de l'IDE Arduino Version V0b : Intégraion de la LDR (selon mon cours au MDC) et intégration du relai Le Circuit : * LDR en série avec R1k entre +5v et Gnd * Point milieu avec A0 * Relay +5v et Gnd et In1 avec broche 7 Version V0c : Mise en place des deux temporisations (en dur dans le code) * t1 => délai d'attente après l'établissement de la lumière avant déclenchement de l'aérateur * (pour éviter le déclenchement sur une simple ouverture de porte de courte durée) * t2 => temps de fonctionnement de l'aérateur après l'extinction de la lumière * Recours à un automate d'états finis cf. * https://forum.arduino.cc/t/programmation-automate-fini-machine-a-etat/452532/5 Version V0d : - Mise en place d'un reset matériel * Le circuit : * R2k entre la broche 8 et le Reset * /!\ Attention à ne pas utiliser la broche 13 qui est en PullUp et repasse à 0 à chaque Reset, * donc le premier Soft Reset déclenche une infinité de Reset => la carte reste bloquée et ne redémarre pas ! - Passage de l'affichage en pourcentage de luminosité : 0% Nuit noire (1023 lu sur la LDR) 100% Pleine lumière (0 lu sur la LDR) - Mise en place d'un mode Run et d'un mode Test : qui permet une modification des valeurs des tempos Changement de mode par un PushButton à bascule sur la broche 9 Version V0e : - Le mode initial et après chaque reset est Run - Renommage du mode Test en mode Test (t) - Affichage de la tempo à rebours (décompte) pendant les états etT1 et etT2 *******************************************************************************/
// include the library code:
- include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin // with the arduino pin number it is connected to const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; const int LdrAnalogIn = A0; const int RelayPin = 7; // Broche IN1 du relay qui pilote l'aérateur const int ModePin = 9; // Broche du PushButton de changement de Mode const String FirmWareVersion = "v0e"; // Version du FirmWare pour l'affichage
int LdrValue = 0; // Valeur lue sur la LDR (Valeur faible = forte luminosité) int Col = 0; // Numéro de la colonne pour l'écriture sur l'écran LCD (entre 0 et 15) unsigned long TimeStamp = 0; // Top Chrono pour suivre l'écoulement des délais t1 et t2 unsigned long timer = 0; // Permet l'affichage du temps qui s'écoule
int t1; // Tempo (en secondes) entre détection de la lumière et mise en route de l'aérateur int t2; // Tempo (en secondes) entre extinction de la lumière et arrêt de l'aérateur unsigned long T; // Tempo (en secondes) entre deux Reset de la carte
// Création de l'afficheur LCD1604 LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Définition des deux modes de fonctionnement enum :boolean {Test, Run} mode;
// Définition des 4 états de l'automate enum :byte {etOff,etT1,etOn,etT2} etat;
// Définition des 4 événements boolean evLightOn() { // Apparition de la lumière
// Lecture de la luminosité LdrValue = analogRead(LdrAnalogIn); lcd.setCursor(0,1); // On place le curseur en début de ligne 1 lcd.print(100-int(LdrValue/10.23)); // On affiche le pourcentage de luminosité à partir de la valeur lue sur la LDR : (0<LDR<1023) lcd.print("% "); // Pour effacer l'unité au cas où la valeur diminue d'un ordre de grandeur. if (LdrValue < 500) { return true; } else { return false; }
}
boolean evLightOff() { // Disparition de la lumière
return !evLightOn();
}
boolean evT1Out() { // Fin de la tempo T1
if (millis()/1000 - TimeStamp > t1) { return true; } else { return false; }
}
boolean evT2Out() { // Fin de la tempo T2
if (millis()/1000 - TimeStamp > t2) { return true; } else { return false; }
}
// Cette fonction effectue un effaçage du Timer // quelque soit sa longueur ( entre 1 et 5 caractères) void effaceTimer() {
lcd.setCursor(11,1); lcd.print(" ");
}
// Cette fonction effectue un Reset matériel void pushReset() {
int resetPin = 8; //!\\ ne pas utiliser la broche 13 cf. commentaires en intro pinMode(resetPin, OUTPUT); // active la broche en sortie (OUTPUT) ce qui déclenche le reset
}
void setup() {
// Détermination des modes pour les broches pinMode(LdrAnalogIn,INPUT); pinMode(RelayPin,OUTPUT); pinMode(ModePin,INPUT);
// Initialisation de la liaison série Serial.begin(115200); // Paramétrage du LCD : Nb de colonnes, Nb de lignes lcd.begin(16, 2); // Affichage de la version du FirmWare. lcd.print("AeroTempo"); lcd.setCursor(7,1); lcd.print(FirmWareVersion);
// Initialisation de l'automate etat = etOff; TimeStamp = 0; mode = Run; Serial.println("AeroTempo");
}
void loop() {
// Reglage du Bug d'affichage : Cetrainment un parasite sur la broche 11 (Enable) qui reset l'afficheur digitalWrite(11,LOW); // Détection du changement de mode entre Run et Test if (digitalRead(ModePin) == HIGH) { Serial.print(mode + " Bip ");
if (mode == Test) { mode = Run; } else { mode = Test; } Serial.println(mode); }
// Détermination des paramètres de tempo selon le mode (Run ou Test) switch (mode) { case Test : t1 = 5; t2 = 10; T = 50; break; case Run : t1 = 60; t2 = 300; T = 86400; break; } // Coeur de l'automate d'états finis switch (etat) { case etOff : lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 lcd.print("Off"); // On affiche l'état digitalWrite(RelayPin,HIGH); // On arrète l'aérateur if (evLightOn()) { // la lumière est-elle allumée ? TimeStamp = millis()/1000; // On note le top départ de t1 etat = etT1; // l'automate change d'état } timer = (millis()/1000 - TimeStamp); break; case etT1 : lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 lcd.print(" T1"); // On affiche l'état if (evLightOff()) { // la lumière est-elle éteinte ? TimeStamp = 0; etat = etOff; // l'automate change d'état } else if (evT1Out()){ // le délai de t1 est-il expiré ? // (i.e. la lumière est-elle établie depuis suffisamment longtemps (t1 secondes) TimeStamp = 0; etat = etOn; // l'automate change d'état } timer = t1-(millis()/1000 - TimeStamp); break; case etOn : lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 lcd.print(" On"); // On affiche l'état digitalWrite(RelayPin,LOW); // On met en route l'aérateur if (evLightOff()) { // la lumière est-elle éteinte ? TimeStamp = millis()/1000; // On note le top départ de t2 etat = etT2; // l'automate change d'état } timer = (millis()/1000 - TimeStamp); break; case etT2 : lcd.setCursor(13,0); // On place le curseur en bout de ligne 0 lcd.print(" T2"); // On affiche l'état if (evT2Out()) { // le délai T2 est-il expiré ? // (i.e. la lumière est-elle éteinte depuis suffisamment longtemps (t2 secondes) TimeStamp = 0; etat = etOff; // l'automate change d'état } else if (evLightOn()) { TimeStamp = 0; // On reset le TimeStamp etat = etOn; } timer = t2 - (millis()/1000 - TimeStamp); break; } // fin du switch case sur l'état de l'automate // Détermination de la colone où débute l'affichage du Timer //timer = (millis()/1000 - TimeStamp); if (timer < 10) { Col = 15; } else if (timer < 100) { Col = 14; } else if (timer < 1000) { Col = 13; } else if (timer < 10000) { Col = 12; } else if (timer < 100000) { Col = 11; } // Affichage du mode lcd.setCursor(12,0); if (mode == Test) { lcd.print("t"); } else { lcd.print("r"); } // Affichage du timer effaceTimer(); lcd.setCursor(Col,1); lcd.print(timer);
// Reset régulier bout T secondes if (millis()/1000 > T) { pushReset(); }
Serial.println(digitalRead(ModePin));
}