Temporisation et selection de temps de cycle

Bonjour,

J’ai écrit un programme permettant d’allumer une diode et un moteur à courant continu avec sélection de 3 cycles de temps d'allumage.
Un bouton poussoir est géré par la bibliothèque Onebutton.h. et fonctionne de la façon suivante :

  • un appui court allume la diode et le moteur pendant la durée du cycle présélectionné.
  • un appui long, d’une durée de 2 secondes, arrête le cycle en cours et éteint diode et moteur.

Le programme fonctionne seulement lorsque le cycle a été choisi avec le commutateur ET que les switch sont tous ouverts… s’il en reste un fermé, le compte a rebours ne s’affiche plus…
Pourriez vous éclairer ma chandelle?

Voici le programme :

#include <OneButton.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const byte in1Pin = 4;           // Pin to connect to motor controller board
const byte in2Pin = 5;           // Pin to connect to motor controller board
const byte sleepPin = 6;         // Pin to disable motor controller sleep mode
const byte buttonPin = 2;        // Switch
const byte ledPin = 13;          // Arduino Nano integrated LED
const byte switchPin1 = 8;       // First switch pin for cycle selection
const byte switchPin2 = 9;       // Second switch pin for cycle selection
const byte switchPin3 = 10;      // Third switch pin for cycle selection

const unsigned long seuilTemps = 2000; // Seuil de temps d'appui long

OneButton bouton(buttonPin);      // Set the button to use INPUT_PULLUP

enum {moteurEtatArrete, moteurEtatDoitDemarrer, moteurEtatMarche, moteurEtatCycleArret, moteurEtatDoitArreter};
int moteurEtat = moteurEtatArrete;

// Durées des cycles (en millisecondes)
const unsigned long cycleDurations[] = {2000, 10000, 15000}; // 2s, 10s, 15s
unsigned long moteurMarcheTempo = cycleDurations[0];  // Temps de marche du moteur par défaut
unsigned long moteurMarcheMillis = 0;     // Temps de marche du moteur, chrono

// Dans cette fonction, donc le click simple, on demarre le moteur
void simpleClick() {
    if (moteurEtat == moteurEtatArrete) {
        Serial.println(F("Moteur doit demarrer"));
        moteurEtat = moteurEtatDoitDemarrer;
    } else {
        Serial.println(F("Moteur deja en marche"));
    }
}

// Dans cette fonction, donc le click long, on arrete le moteur et on active le mode sleep
void clickLong() {
    Serial.println(F("Moteur cycle doit arreter"));
    moteurEtat = moteurEtatCycleArret;
}

// Fonction pour mettre à jour la durée du cycle basée sur la sélection du commutateur
void updateCycleDuration() {
    if (digitalRead(switchPin1) == LOW) {
        moteurMarcheTempo = cycleDurations[0];
        Serial.println(F("Cycle: 2 secondes"));
				u8g2.drawStr(0, 10, "2");
    } else if (digitalRead(switchPin2) == LOW) {
        moteurMarcheTempo = cycleDurations[1];
        Serial.println(F("Cycle: 10 secondes"));
				u8g2.drawStr(0, 10, "10");
    } else if (digitalRead(switchPin3) == LOW) {
        moteurMarcheTempo = cycleDurations[2];
        Serial.println(F("Cycle: 15 secondes"));
				u8g2.drawStr(0, 10, "15");
    }
}

void setup() {
    Serial.begin(115200);

		// Initialisation ecran oled
  	u8g2.begin();
		u8g2.clearBuffer();
  	u8g2.setFont(u8g2_font_timB10_tf) ;	// sélection police de caractère

    pinMode(in1Pin, OUTPUT);    // Set the motor control pins as outputs
    pinMode(in2Pin, OUTPUT);    // Set the motor control pins as outputs
    pinMode(sleepPin, OUTPUT);  // Set the motor control sleep pin as output
    pinMode(ledPin, OUTPUT);    // Set the led pin as output
    pinMode(buttonPin, INPUT_PULLUP); // Enable pull-up resistor for the button
    pinMode(switchPin1, INPUT_PULLUP); // Enable pull-up for switch 1
    pinMode(switchPin2, INPUT_PULLUP); // Enable pull-up for switch 2
    pinMode(switchPin3, INPUT_PULLUP); // Enable pull-up for switch 3

    bouton.setPressMs(seuilTemps);                // Set long press time
    bouton.attachClick(simpleClick);               // Function for short press
    bouton.attachLongPressStop(clickLong);         // Function for long press stop

    moteurEtat = moteurEtatDoitArreter;
}

void loop() {
    bouton.tick();  // Keep watching the push button
    updateCycleDuration(); // Update the cycle duration based on switch input

    if (moteurEtat == moteurEtatDoitDemarrer) {
        Serial.println(F("Moteur en marche"));
        Serial.print(F("Durée du cycle: "));
        Serial.print(moteurMarcheTempo / 1000); // Affichage en secondes	
        Serial.println(F(" secondes"));
				u8g2.drawStr(0, 28, "moteurMarcheTempo / 1000");
        moteurMarcheMillis = millis();     // Start the timer
        moteurDemarrage();
        moteurEtat = moteurEtatMarche;
    }

    if (moteurEtat == moteurEtatDoitArreter) {
        Serial.println(F("Moteur Arret"));
        moteurArret();
        moteurEtat = moteurEtatArrete;
    }

    if (moteurEtat == moteurEtatCycleArret) {
        Serial.println(F("Moteur Arret du cycle"));
        moteurArret();
        moteurEtat = moteurEtatDoitArreter;
    }

    if (moteurEtat == moteurEtatMarche) {
    unsigned long currentMillis = millis();
    unsigned long elapsed = currentMillis - moteurMarcheMillis; // Temps écoulé
    unsigned long remaining = moteurMarcheTempo - elapsed;      // Temps restant

    static unsigned long lastUpdateMillis = 0;  // Pour gérer l'affichage une fois par seconde

    // Si le temps restant est supérieur à 0
    if (remaining > 0) {
        // Affichage du compte à rebours toutes les secondes
        if (currentMillis - lastUpdateMillis >= 1000) {
            lastUpdateMillis = currentMillis;  // Mettre à jour le dernier temps d'affichage

            // Afficher le temps restant en secondes
            Serial.print(F("Temps restant: "));
            Serial.print(remaining / 1000);    // Convertir millisecondes en secondes
            Serial.println(F(" secondes"));
						u8g2.drawStr(0, 46, "remaining / 1000");	
        }
    }

    // Vérification de la fin du cycle
    if (elapsed >= moteurMarcheTempo) {
        Serial.println(F("Moteur Fin cycle"));
        moteurEtat = moteurEtatDoitArreter;
    }
}

}

void moteurDemarrage() {
    digitalWrite(ledPin, HIGH);
    digitalWrite(sleepPin, HIGH);   // Disable the motor controller sleep mode
    digitalWrite(in1Pin, HIGH);     // Turn the motor on
    digitalWrite(in2Pin, LOW);      // Turn CW
}

void moteurArret() {
    digitalWrite(ledPin, LOW);
    digitalWrite(sleepPin, LOW);   // Enable the motor controller sleep mode
    digitalWrite(in1Pin, LOW);     // Turn the motor off
    digitalWrite(in2Pin, LOW);     
}

et voici le Wokwi :

A chaque itération de loop() tu repasses dans updateCycleDuration() ce qui réinitialise moteurMarcheTempo. Il ne faudrait passer dans updateCycleDuration() que lorsque moteurEtat == moteurEtatArrete

Merci pour cette info, effectivement j'ai déplacé updateCycleDuration dans la bonne boucle et le compte à rebours s'affiche et la tempo fonctionne bien :smiley:
J'ai encore un problème d'affichage du compte à rebours sur l'écran oled. J'ai essayé plusieurs commandes mais sans succès... Quelqu'un saurait m'aider sur cet autre point?
voici le nouveau programme :


#include <OneButton.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const byte in1Pin = 4;           // Pin to connect to motor controller board
const byte in2Pin = 5;           // Pin to connect to motor controller board
const byte sleepPin = 6;         // Pin to disable motor controller sleep mode
const byte buttonPin = 2;        // Switch
const byte ledPin = 13;          // Arduino Nano integrated LED
const byte switchPin1 = 8;       // First switch pin for cycle selection
const byte switchPin2 = 9;       // Second switch pin for cycle selection
const byte switchPin3 = 10;      // Third switch pin for cycle selection

const unsigned long seuilTemps = 2000; // Seuil de temps d'appui long

OneButton bouton(buttonPin);      // Set the button to use INPUT_PULLUP

enum {moteurEtatArrete, moteurEtatDoitDemarrer, moteurEtatMarche, moteurEtatCycleArret, moteurEtatDoitArreter};
int moteurEtat = moteurEtatArrete;

// Durées des cycles (en millisecondes)
const unsigned long cycleDurations[] = {2000, 10000, 15000}; // 2s, 10s, 15s
unsigned long moteurMarcheTempo = cycleDurations[0];  // Temps de marche du moteur par défaut
unsigned long moteurMarcheMillis = 0;     // Temps de marche du moteur, chrono

// Dans cette fonction, donc le click simple, on demarre le moteur
void simpleClick() {
    if (moteurEtat == moteurEtatArrete) {
        Serial.println(F("Moteur doit demarrer"));
        moteurEtat = moteurEtatDoitDemarrer;
    } else {
        Serial.println(F("Moteur deja en marche"));
    }
}

// Dans cette fonction, donc le click long, on arrete le moteur et on active le mode sleep
void clickLong() {
    Serial.println(F("Moteur cycle doit arreter"));
    moteurEtat = moteurEtatCycleArret;
}

// Fonction pour mettre à jour la durée du cycle basée sur la sélection du commutateur
void updateCycleDuration() {
    if (digitalRead(switchPin1) == LOW) {
        moteurMarcheTempo = cycleDurations[0];
        Serial.println(F("Cycle: 2 secondes"));
				u8g2.drawStr(0, 10, " 2");
    } else if (digitalRead(switchPin2) == LOW) {
        moteurMarcheTempo = cycleDurations[1];
        Serial.println(F("Cycle: 10 secondes"));
				u8g2.drawStr(0, 10, "10");
    } else if (digitalRead(switchPin3) == LOW) {
        moteurMarcheTempo = cycleDurations[2];
        Serial.println(F("Cycle: 15 secondes"));
				u8g2.drawStr(0, 10, "15");
    }
}

void setup() {
    Serial.begin(115200);
		Wire.begin(); //SDA & SDL

		// Initialisation ecran oled
  	u8g2.begin();
		u8g2.clearBuffer();
  	u8g2.setFont(u8g2_font_timB10_tf) ;	// sélection police de caractère

    pinMode(in1Pin, OUTPUT);    // Set the motor control pins as outputs
    pinMode(in2Pin, OUTPUT);    // Set the motor control pins as outputs
    pinMode(sleepPin, OUTPUT);  // Set the motor control sleep pin as output
    pinMode(ledPin, OUTPUT);    // Set the led pin as output
    pinMode(buttonPin, INPUT_PULLUP); // Enable pull-up resistor for the button
    pinMode(switchPin1, INPUT_PULLUP); // Enable pull-up for switch 1
    pinMode(switchPin2, INPUT_PULLUP); // Enable pull-up for switch 2
    pinMode(switchPin3, INPUT_PULLUP); // Enable pull-up for switch 3

    bouton.setPressMs(seuilTemps);                // Set long press time
    bouton.attachClick(simpleClick);               // Function for short press
    bouton.attachLongPressStop(clickLong);         // Function for long press stop

    moteurEtat = moteurEtatDoitArreter;
}

void loop() {
    bouton.tick();  // Keep watching the push button
    
		if (moteurEtat == moteurEtatArrete) {
        Serial.println(F("Arret"));
				u8g2.drawStr(0, 28, "Arret");
        updateCycleDuration(); // Update the cycle duration based on switch input
    }

    if (moteurEtat == moteurEtatDoitDemarrer) {
        Serial.println(F("Marche"));
        Serial.print(F("Durée du cycle: "));
        Serial.print(moteurMarcheTempo / 1000); // Affichage en secondes	
        Serial.println(F(" secondes"));
				u8g2.drawStr(0, 28, "Marche");
        moteurMarcheMillis = millis();     // Start the timer
        moteurDemarrage();
        moteurEtat = moteurEtatMarche;
    }

    if (moteurEtat == moteurEtatDoitArreter) {
        Serial.println(F("Moteur Arret"));
        moteurArret();
        moteurEtat = moteurEtatArrete;
    }

    if (moteurEtat == moteurEtatCycleArret) {
        Serial.println(F("Moteur Arret du cycle"));
        moteurArret();
        moteurEtat = moteurEtatDoitArreter;
    }

    if (moteurEtat == moteurEtatMarche) {
    unsigned long currentMillis = millis();
    unsigned long elapsed = currentMillis - moteurMarcheMillis; // Temps écoulé
    unsigned long remaining = moteurMarcheTempo - elapsed;      // Temps restant

    static unsigned long lastUpdateMillis = 0;  // Pour gérer l'affichage une fois par seconde

    // Si le temps restant est supérieur à 0
    if (remaining > 0) {
        // Affichage du compte à rebours toutes les secondes
        if (currentMillis - lastUpdateMillis >= 1000) {
            lastUpdateMillis = currentMillis;  // Mettre à jour le dernier temps d'affichage

            // Afficher le temps restant en secondes
            Serial.print(F("Temps restant: "));
            Serial.print(remaining / 1000);    // Convertir millisecondes en secondes
            Serial.println(F(" secondes"));
						u8g2.drawStr(0, 46, "remaining / 1000");		
        }
    }

    // Vérification de la fin du cycle
    if (elapsed >= moteurMarcheTempo) {
        Serial.println(F("Moteur Fin cycle"));
        moteurEtat = moteurEtatDoitArreter;
    }
}
u8g2.sendBuffer();		  	        // affichage des infos à l'écran
}

void moteurDemarrage() {
    digitalWrite(ledPin, HIGH);
    digitalWrite(sleepPin, HIGH);   // Disable the motor controller sleep mode
    digitalWrite(in1Pin, HIGH);     // Turn the motor on
    digitalWrite(in2Pin, LOW);      // Turn CW
}

void moteurArret() {
    digitalWrite(ledPin, LOW);
    digitalWrite(sleepPin, LOW);   // Enable the motor controller sleep mode
    digitalWrite(in1Pin, LOW);     // Turn the motor off
    digitalWrite(in2Pin, LOW);     
}

C'est-à-dire? Détaille un peu, s'il te plait.

Je souhaiter afficher :

  • la durée de temporisation (2, 10 ou 15) sur la 1ere ligne
  • l'etat du moteur (marche, arret) sur la 2eme ligne
  • le compte a rebours sur la 3eme ligne

Voici ce que j'ai écrit dans 'if (moteurEtat == moteurEtatMarche)' pour le compte à rebours :

char countdownBuffer[10];
snprintf(countdownBuffer, sizeof(countdownBuffer), "%lu", remaining / 1000);
u8g2.drawStr(0, 46, countdownBuffer);

Cela fonctionne mais l'affichage du compte à rebours garde le deuxieme digit, c'est à dire qu'a 9 il affiche 90, puis à 8 il affiche 80, etc.

Est ce qu'il faut que je fasse un clearbuffer puis re-ecrire toutes les lignes?

Tu peux imposer une longueur à la chaine et/ou faire placer des espaces ou des 0 en tête.
Voir ici comment fonctionne le formatage des chaines de caractères

Super, merci, je vais regarder ca :+1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.