Je travaille présentement sur un projet de barrière de sécurité pour le trafic. En gros, il y a un signaleur qui contrôle la barrière avec une télécommande pour ouvrir et fermer la barrière. Lorsque la barrière est fermée, un feux de signalisation rouge est allumé et lorsqu'elle est ouverte, un feu jaune est allumé. C'est un moteur avec une vis sans fin qui ouvre et ferme la barrière et il y a 2 limit switch pour dire quand la barrière est ouverte et quand elle est fermée.
C'est un relais télécommandé d'Amazon qu'utilise le signaleur.
Comme arduino, j'utilise un Nano. J'ai mis les naratives en pièce jointe ainsis que mon schéma de branchement. Pour le branchement, je l'ai testé et ça fonctionne bien.
Mon problème, c'est que je ne sais pas trop comment coder ça. Avez-vous une idée pour m'aider?
merci
// Code pour Gate de signalisation
// Inclure les différentes librairies
#include <ezButton.h>
// Définir les différentes pins
// Input
const int RemotePin = 2; // Pin du relais de télécommande
const int LimitHaut = 5; // Input de la limit switch haute
const int LimitBas = 6; // Input de la limit switch Basse
// Output
const int Mot1 = 3; // Pin 1 du Pont H du moteur
const int Mot2 = 4; // Pin 2 du Pont H du moteur
const int RLight = 8; // Output de la lumière rouge
const int YLight = 10; // Output de la lumière rouge
const int ledPin = 13; // LED interne du Nano
// Télécommande
ezButton button(RemotePin); // Objet ezButton sur la pin ;
//int RemoteStatus = 0 ;
void setup() {
// Moniteur série pour debug
Serial.begin(9600);
// Définir le type de I/O des pins
pinMode(RemotePin, INPUT_PULLUP);
pinMode(LimitHaut, INPUT_PULLUP);
pinMode(LimitBas, INPUT_PULLUP);
pinMode(Mot1, OUTPUT);
pinMode(Mot2, OUTPUT);
pinMode(RLight, OUTPUT);
pinMode(YLight, OUTPUT);
pinMode(ledPin, OUTPUT);
// Filtre sur le relais de télécommande
button.setDebounceTime(100);// Filtre de 100 milisecondes
}
void gate_monte() {
digitalWrite(Mot1, LOW);
digitalWrite(Mot2, HIGH);
}
void gate_baisse() {
digitalWrite(Mot1, HIGH);
digitalWrite(Mot2, LOW);
}
void gate_stop() {
digitalWrite(Mot1, LOW);
digitalWrite(Mot2, LOW);
}
void Red_on() {
digitalWrite(RLight, HIGH);
}
void Red_off() {
digitalWrite(RLight, LOW);
}
void Yellow_on() {
digitalWrite(RLight, HIGH);
}
void Yellow_off() {
digitalWrite(RLight, LOW);
}
void loop() {
// put your main code here, to run repeatedly:
button.loop(); // MUST call the loop() function first
if(button.isPressed())
Serial.println("The button is pressed");
if(button.isReleased())
Serial.println("The button is released");
}
Un fin de course, c'est comme un bouton donc cela se gère de la même manière.
Avant de parler codage, as-tu un algorithme qui détaille les étapes de ce que tu veux réaliser?
Mettre un moteur en marche, tester un fin de course et agir en conséquence ce n'est pas très complexe, il me semble.
Oui j’ai fait les naratives. Est-ce que tu vois l’image en pièce jointe? J’ai inscrit les différentes étapes.
Lorsque j’alimente la système, la barrière ne bouge pas et la lumière rouge est allumée. On attend que le relais RF s’ouvre.
Un fois le relais RF ouvert, la barrière lève, la lumière est encore rouge. Lorsque la barrière touche la limite switch, le moteur stop et la lumière jaune s’allume. Le système reste comme ça et attend le signal du relais RF.
Une fois le relais RF fermé, la lumière rouge s’allume, la barrière descend et lorsqu’elle touche l’autre limit switch, le moteur stop. Et on attend que le relais RF s’ouvre pour recommencer.
j'ai essayé quelques lignes de code pour partir mon projet. Ça ne marche pas à 100% de ce que je voudrais... Voici la loop.
void loop() {
// put your main code here, to run repeatedly:
button.loop(); // MUST call the loop() function first
Red_on();
Yellow_off();
gate_stop();
if(button.isPressed()) {
while((digitalRead(LimitHaut) == HIGH)) { // Tant que la limit switch haut n'est pas activée, le moteur virre
gate_monte();
}
gate_stop();
Yellow_on();
Red_off();
}
}
Au début, je veux que la barrière ne bouge pas et que la lumière rouge soit allumée. C'est le cas donc j'ai une étape de fait.
Quand j'active mon relais RF, la barrière monte et la lumière rouge est allumée, je suis content. Quand la limit switch est atteinte, le moteur stop, mais la lumière rouge reste allumée et la jaune ne s'allume pas...
En fait, tu passes bien par l'étape Yellow_on(); Red_off(); mais comme le programme retourne aussitôt au début de loop les lignes Red_on(); Yellow_off(); sont immédiatement exécutées et tu ne vois pas l'étape intermédiaire.
En fait, tu n'as implémenté qu'une partie de ton besoin. Après l'étape Yellow_on(); Red_off(); il faudrait ajouter l'attente du relâchement du relais RF comme indiqué dans tes dessins puis le retour de la barrière en position fermée.
Au final, tu essaies de faire une machine à état, voilà un peu de lecture:
Merci pour l'info. J'ai regardé ça pas mal, mais je n'arrive pas du tout à faire bouger mes choses... As-tu une idée où ça pourrait foirer dans mon code?
int etat='a';
void loop() {
if(digitalRead(RemotePin) == LOW){
int etat='a';
}
else if(button.isPressed()) {
int etat='b';
}
else if(digitalRead(LimitHaut) == HIGH) {
int etat='c';
}
else if(button.isReleased()) {
int etat='d';
}
else(digitalRead(LimitHaut) == HIGH); {
int etat='e';
}
// do something different depending on the range value:
switch (etat) {
case 'a': // your hand is on the sensor
Red_on();
Yellow_off();
gate_stop();
break;
case 'b': // your hand is close to the sensor
Red_on();
Yellow_off();
gate_monte();
break;
case 'c': // your hand is a few inches from the sensor
Red_off();
Yellow_on();
gate_stop();
break;
case 'd': // your hand is nowhere near the sensor
Red_on();
Yellow_off();
gate_baisse();
break;
case 'e': // your hand is on the sensor
Red_on();
Yellow_off();
gate_stop();
break;
}
}
C'est probablement que mon code vire en rond et revient toujours à la valeur etat = 'a', mais si je ne le met pas quelque part, le code plante à switch(etat) et dit que la variable etat n'existe pas...
Avez vous une idée? Je sens que je suis près du but, mais je ne trouve pas...
Non pas tout à fait, en fait, tu déclares une variable globale:
int etat='a'; (tout en haut)
Cette variable globale etat est "vue" par switch (etat) {
Par contre si tu fais:
if(digitalRead(RemotePin) == LOW){
int etat='a';
}
else if(button.isPressed()) {
int etat='b';
}
else if(digitalRead(LimitHaut) == HIGH) {
int etat='c';
}
else if(button.isReleased()) {
int etat='d';
}
else(digitalRead(LimitHaut) == HIGH); {
int etat='e';
}
Dans ces 5 test conditionnels, chaque variable etat est différente et est "vue" qu'entre les accolades de l'if donc, forcément, pas par switch (etat) {
C'est pourquoi, etat vaut toujours 'a' puisque rien ne le modifie.
Pour parer à ce problème, changes les int etat= en etat= dans les 5 conditions, ainsi etat deviendra l'etat global donc vu partout.
Dans loop, tu as oublié de lire button button.loop();
Comme expliqué par @jpbbricole Quand vous faites ça vous redeclarez une variable locale qui ne sert à rien et vous n’affectez pas l’état global. Le
Compilateur (enfin l’optimiseur) va même virer tout ce code car il ne fait rien
// Inclure les différentes librairies
#include <ezButton.h>
// Définir les différentes pins
// Input
const int RemotePin = 2; // Pin du relais de télécommande
const int LimitHaut = 5; // Input de la limit switch haute
const int LimitBas = 6; // Input de la limit switch Basse
// Output
const int Mot1 = 3; // Pin 1 du Pont H du moteur
const int Mot2 = 4; // Pin 2 du Pont H du moteur
const int RLight = 8; // Output de la lumière rouge
const int YLight = 10; // Output de la lumière rouge
const int ledPin = 13; // LED interne du Nano
// Télécommande
ezButton button(RemotePin); // Objet ezButton sur la pin ;
void setup() {
// Moniteur série pour debug
Serial.begin(9600);
// Définir le type de I/O des pins
pinMode(RemotePin, INPUT_PULLUP);
pinMode(LimitHaut, INPUT_PULLUP);
pinMode(LimitBas, INPUT_PULLUP);
pinMode(Mot1, OUTPUT);
pinMode(Mot2, OUTPUT);
pinMode(RLight, OUTPUT);
pinMode(YLight, OUTPUT);
pinMode(ledPin, OUTPUT);
// Filtre sur le relais de télécommande
button.setDebounceTime(100);// Filtre de 100 milisecondes
}
void gate_monte() {
digitalWrite(Mot1, LOW);
digitalWrite(Mot2, HIGH);
}
void gate_baisse() {
digitalWrite(Mot1, HIGH);
digitalWrite(Mot2, LOW);
}
void gate_stop() {
digitalWrite(Mot1, HIGH);
digitalWrite(Mot2, HIGH);
}
void Red_on() {
digitalWrite(RLight, LOW);
}
void Red_off() {
digitalWrite(RLight, HIGH);
}
void Yellow_on() {
digitalWrite(YLight, LOW);
}
void Yellow_off() {
digitalWrite(YLight, HIGH);
}
int etat='b';
//enum {a, b, c, d, e} etat;
void loop() {
button.loop();
//Serial.println(etat);
if(digitalRead(RemotePin) == LOW)
etat='a';
if(button.isPressed())
etat='b';
if(digitalRead(LimitHaut) == HIGH)
etat='c';
if(button.isReleased())
etat='d';
if(digitalRead(LimitHaut) == HIGH);
etat='e';
switch (etat) {
case 'a': // your hand is on the sensor
Red_on();
Yellow_off();
gate_stop();
break;
case 'b': // your hand is close to the sensor
Red_on();
Yellow_off();
gate_monte();
break;
case 'c': // your hand is a few inches from the sensor
Red_off();
Yellow_on();
gate_stop();
break;
case 'd': // your hand is nowhere near the sensor
Red_on();
Yellow_off();
gate_baisse();
break;
case 'e': // your hand is on the sensor
Red_on();
Yellow_off();
gate_stop();
break;
}
// do something different depending on the range value:
}
et utiliser des désignateurs explicites dans le code
Si tu as bien lu le tuto sur les machines à état, la structure exposée est plutôt de ce genre là
switch (etat){
case ATTENTE:
if (button.isPressed()){
etat = OUVERTURE;
}
break;
case OUVERTURE:
Red_on();
Yellow_off();
gate_monte();
if (digitalRead(LimitHaut) == LOW){
etat = OUVERT;
}
break;
case OUVERT:
....
break;
case FERMETURE:
....
break;
case FERME:
....
break;
}
Ainsi chaque case correspond à un des états définis et il contient les actions à effectuer et les conditions qui vont le faire passer dans un autre état. Si un état débouche sur plusieurs actions, afin d'alléger le code, il est parfaitement possible de créer des fonctions, par exemple une fonction qui regrouperait la gestion de la barrière et aussi des feux, ce qui dans ton cas ne semble pas indispensable.
Pour la mise au point c'est facile, tu peux ajouter des Serial.print() dans les case ce qui va te permettre de voir comment les états s'enchaînent et si tu as des problèmes il suffit d'ajouter l'impression de quelques variables pour voir pourquoi les enchaînements ne se passent pas comme prévu.
Bonjour allmuf
Que veux tu faire avec tes boutons, il y a des trucs "bizarres" dans ta façon de les lire, en effet, tu fait;
if(digitalRead(RemotePin) == LOW)
etat='a';
et
if(button.isPressed())
etat='b';
ce qui veut dire que tu lis 2 fois la même entrée (RemotePin = 2), une fois en "direct" et une fois via la bibliothèque ezButton.h (ezButton button(RemotePin);)
Ensuite tu lis 2 fois LimitHaut (je suppose que la 2ème est LimitBas)
là n'est pas le problème mais tu lis si l'état est HIGH ce qui est toujours le cas quand le bouton n'est pas pressé vu que tu as initialisé l'entrée pinMode(LimitHaut, INPUT_PULLUP);