OK
c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)
ça pourrait ressembler à cela (tapé ici, non testé). le code devrait afficher dans la console à 115200 bauds les mouvements choisis.
const byte pinMoteurGauche = 2; // sens anti-horaire
const byte pinMoteurDroite = 4; // sens horaire
const byte pinVitesseMoteur = 3; // pour la vitesse
const byte pinLimiteGauche = A0;
const byte pinLimiteDroite = A1;
const byte LIMITE_ACTIVE = LOW; // on utilise un pullup sur les entrées, LOW veut dire apppui
const byte VitesseMin = 25;
const byte VitesseMax = 255;
const int DureeMin = 2000;
const int DureeMax = 5000;
enum t_etat : byte {ARRET, VERS_GAUCHE, VERS_DROITE} etat = ARRET;
unsigned long duree, tempsDebut;
byte vitesse; // PWM
void afficheEtat() {
switch (etat) {
case VERS_GAUCHE: Serial.print(F("VERS_GAUCHE")); break;
case VERS_DROITE: Serial.print(F("VERS_DROITE")); break;
case ARRET: Serial.print(F("ARRET")); break;
default: break;
}
Serial.print(F(" pour "));
Serial.print(duree / 1000.0, 2);
Serial.println(F(" s."));
}
void arret() {
analogWrite(pinVitesseMoteur, 0);
digitalWrite(pinMoteurDroite, LOW);
digitalWrite(pinMoteurGauche, LOW);
etat = ARRET;
afficheEtat();
}
void allerAGauche() {
analogWrite(pinVitesseMoteur, vitesse);
digitalWrite(pinMoteurDroite, LOW);
digitalWrite(pinMoteurGauche, HIGH);
etat = VERS_GAUCHE;
afficheEtat();
}
void allerADroite() {
analogWrite(pinVitesseMoteur, vitesse);
digitalWrite(pinMoteurGauche, LOW);
digitalWrite(pinMoteurDroite, HIGH);
etat = VERS_DROITE;
afficheEtat();
}
void generationAleatoire() {
// on ne veut pas répéter le même mouvement deux fois de suite
t_etat choixPossibles[2];
switch (etat) {
case ARRET: choixPossibles[0] = VERS_GAUCHE; choixPossibles[1] = VERS_DROITE; break;
case VERS_GAUCHE: choixPossibles[0] = ARRET; choixPossibles[1] = VERS_DROITE; break;
case VERS_DROITE: choixPossibles[0] = ARRET; choixPossibles[1] = VERS_GAUCHE; break;
}
t_etat choix = choixPossibles[random(0, 2)]; // on choisit un nouvel état aléatoirement
vitesse = (choix == ARRET) ? 0 : random(VitesseMin, VitesseMax + 1); // vitesse aléatoire si on n'est pas à l'arrêt
duree = random(DureeMin, DureeMax + 1); // durée aléatoire de cette action
tempsDebut = millis();
switch (choix) {
case ARRET: arret(); break;
case VERS_GAUCHE: allerAGauche(); break;
case VERS_DROITE: allerADroite(); break;
}
}
void testDuree() {
if (millis() - tempsDebut >= duree) generationAleatoire(); // il est temps de donner un nouvel ordre
}
void testLimites() {
switch (etat) {
case VERS_GAUCHE: if (digitalRead(pinLimiteGauche) == LIMITE_ACTIVE) allerADroite(); break;
case VERS_DROITE: if (digitalRead(pinLimiteDroite) == LIMITE_ACTIVE) allerAGauche(); break;
case ARRET: break; // rien à faire sinon
}
}
void setup() {
pinMode(pinMoteurGauche, OUTPUT);
pinMode(pinMoteurDroite, OUTPUT);
pinMode(pinVitesseMoteur, OUTPUT);
arret();
pinMode(pinLimiteGauche, INPUT_PULLUP); // pullup interne activé
pinMode(pinLimiteDroite, INPUT_PULLUP); // pullup interne activé
randomSeed(analogRead(A2));
Serial.begin(115200);
Serial.println(F("\nC'EST PARTI !!!"));
generationAleatoire();
}
void loop() {
testDuree();
testLimites();
}
Si on touche un limit switch, le mouvement s'inverse et continue pour le temps restant (puisque c'était aléatoire, ça reste un temps aléatoire)
la structuration en petites fonctions dédiées à une tâche rend le code plus lisible et la définition d'un état du système permet de prendre des décisions sur quoi faire lorsqu'un événement attendu survient (le temps est écoulé ou on touche un fin de course)
vous remarquerez qu'il n'y a aucun appel à delay() dans le code. C'est un appel bloquant et vous ne voulez pas cela sinon vous ne pouvez pas tester si un fin de course et touché pendant ce temps là.
➜ à tester et affiner sans doute