Utilisation d'une temporisation de controle sans changement d'état

Bonjour,
Je conçois une machine de comptage via un capteur optique reliée à un moteur. Tout fonctionne bien mais j'aimerais une temporisation qui arrêterai le moteur si mon capteur ne compte plus rien pendant un temps donné.
voici mon code :

void inventaire()
{
    // Fonction d'inventaire
    int cpt = 0;
    unsigned long tempo = millis();
reprise:
    lcd.clear();
    lcd.print("Comptage en cours");
    do
    {
        digitalWrite(MOTOR, HIGH); 
        digitalWrite(BRAKE, LOW);  
        analogWrite(3, 100);      
        int sensorVal = digitalRead(fbrpin);
        while (kpd.getKey() != 'A')
        {
            int sensorVal = digitalRead(fbrpin);
            if (sensorVal == LOW)
            {
                cpt++;
                delay(50);
            }
        };
        goto stop;
    } while (1);
stop:
    digitalWrite(MOTOR, LOW);
    digitalWrite(BRAKE, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Inventaire");
    lcd.setCursor(0, 1);
    lcd.print(cpt);
    char key = kpd.getKey();
    while (key == NO_KEY)
        key = kpd.getKey();
    if (key == 'D')
    {
        goto reprise;
    }
};

J'ai conscience que la fonction millis() peut m'aider mais je ne sais pas trop comment l'utiliser avec mon changement d'état de capteur dans ma boucle infinie!

Merci

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

commencez à récrire le code sans goto :slight_smile: et postez le code complet, on ne sait pas ce qu'il se passe ailleurs. Si vous voulez une boucle infinie, utilisez la loop, elle est faite pour ça

c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

Bonjour et merci pour la réponse,
j'utilise le goto pour sortir de ma boucle infinie car j'utilise dejà la loop pour autre chose.
Ci dessous le code complet :

#include "Keypad_I2C.h"
#include "keypad.h"
#include "Arduino.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define I2CADDR 0x20
LiquidCrystal_I2C lcd(0x27, 16, 2);

const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
    {'1', '2', '3', 'A'},
    {'4', '5', '6', 'B'},
    {'7', '8', '9', 'C'},
    {'*', '0', '#', 'D'}};
byte rowPins[ROWS] = {7, 6, 5, 4};
byte colPins[COLS] = {3, 2, 1, 0};

// intialise une instance de classe NewKeypad
Keypad_I2C kpd(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS, I2CADDR);

// Intialisation des variables
String gel = ""; // Variable d'enregistrement de la quantité de gélules souhaitée
int i = 0;
int oldval = 1;
int cpt = 0;
int nbpot = 0; // Variable contenant le nombre de pot
int val = 0;
unsigned long fbr_time = 0;
unsigned long last_fbr_time = 0;
const int fbrpin = 2; // port digital dedié au signal de la fibre
int MOTOR = 12;       // Port digital pour la mise en marche du moteur
int BRAKE = 9;        // Port digital pour le frein du moteur
int buttonPin = 4;    // Port digital pour le signal du moteur

void setup()
{
    Wire.begin();
    Serial.begin(9600);
    pinMode(MOTOR, OUTPUT); // Initiates Motor Channel A pin
    pinMode(BRAKE, OUTPUT); // Initiates Brake Channel A pin
    pinMode(fbrpin, INPUT_PULLUP);
    unsigned int time_anti_rebond = 100; // 100 ms
    kpd.setDebounceTime(time_anti_rebond);
    pinMode(buttonPin, INPUT);
    lcd.init();
    lcd.backlight();
    kpd.begin();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("   EASYCOUNT   ");
    lcd.setCursor(0, 1);
    lcd.print("  S/N5100201a  ");
    delay(1500);
    lcd.init();
    testinit();
    menu();
}
void menu()
{
    lcd.clear();
    ecrire(0, 0, "Comptage     [A]");
    ecrire(0, 1, "Inventaire   [B]");
    char customKey = kpd.getKey();
    while (customKey == NO_KEY)
        customKey = kpd.getKey();
    switch (customKey)
    {
    case 'A':
        lcd.clear();
        ecrire(0, 0, "Quantite ?");
        loop();
        break;
    case 'B':
        lcd.clear();
        ecrire(0, 0, "Demarrer    [D]");
        ecrire(0, 1, "Arreter     [A]");
        char key = kpd.getKey();

        while (key == NO_KEY)
            key = kpd.getKey();
        switch (key)
        {
        case 'D':
            inventaire();
            break;
        case 'C':
            menu();
            break;
        }

        break;
    }
}
void testinit()
{ // Procédure de test de la bonne alimentation du capteur fibre
    lcd.clear();
    ecrire(0, 0, "  TEST  FIBRE  ");
    delay(1500);
    int sensorVal = digitalRead(fbrpin);
    if (sensorVal == HIGH)
    {
        lcd.clear();
        ecrire(0, 0, "  FIBRE    OK  ");
        delay(1500);
        loop();
    }
    else
    {
        lcd.clear();
        ecrire(0, 0, "  FIBRE  SALE  ");
        ecrire(0, 1, "  Erreur  F01  ");
        char key = kpd.getKey();
        if (key != NO_KEY && key == '#')
        {
            testinit();
        };
    }
}
void loop()
{
    // Enregistrement de la quantité de gélules voulue
    char key = kpd.getKey();

    if (key != NO_KEY && (key == '1' || key == '2' || key == '3' || key == '4' || key == '5' || key == '6' || key == '7' || key == '8' || key == '9' || key == '0'))
    {
        gel = gel + key;
        char nbgel[5] = "";
        ecrire(i, 1, sprintf(nbgel, "%d", key));
        /* lcd.setCursor(i, 1);
         lcd.print(key);*/
        i++;
    }
    else if ((key != NO_KEY && (key == 'D')) || (digitalRead(buttonPin) == LOW))
    {
        comptage();
    }
    else if ((key != NO_KEY && (key == 'C')))
    {
        menu();
    }
}
void ecrire(int COL, int ROW, char txt)
{
    // Microprogramme d'écriture sur l'écran LCD
    lcd.setCursor(COL, ROW);
    lcd.print(txt);
}
void comptage()
{
    // Fonction de comptage de gélules et remplissage de pot
    int cpt = 0;
reprise:
    lcd.clear();
    /*  lcd.setCursor(0, 0);*/
    int sensorVal = digitalRead(fbrpin);
    int nbgel = gel.toInt();
    /* lcd.print("pots de ");
     lcd.print(nbgel);
     lcd.print(" gel");
     lcd.setCursor(0, 1);
     lcd.print("STOP [A]");*/
    char txt[16] = "";
    ecrire(0, 1, sprintf(txt, "pots de %d gel", nbgel));

    do
    {
        int sensorVal = digitalRead(fbrpin);
        digitalWrite(MOTOR, HIGH); // Establishes forward direction of Channel A
        digitalWrite(BRAKE, LOW);  // Disengage the Brake for Channel A
        analogWrite(3, 100);       // Spins the motor on Channel A at 100/255 of his speed
        if (kpd.getKey() == 'A')
        {
            goto stop;
        }
        else if (sensorVal == LOW)
        {
            cpt++;
            delay(50);
        }
    } while (cpt < nbgel - 3);
    // Ralentissement du moteur pour les 3 dernières gélules
    do
    {
        int sensorVal = digitalRead(fbrpin);
        digitalWrite(MOTOR, HIGH); // Establishes forward direction of Channel A
        digitalWrite(BRAKE, LOW);  // Disengage the Brake for Channel A
        analogWrite(3, 50);        // Spins the motor on Channel A at 50/255 of his speed
        if (kpd.getKey() == 'A')
        {
            goto stop;
        }
        else if (sensorVal == LOW)
        {
            cpt++;
            delay(50);
        }
    } while (cpt < nbgel);
stop:
    digitalWrite(MOTOR, LOW);  // Arret du moteur
    digitalWrite(BRAKE, HIGH); // mise en place du frein

    if (cpt == nbgel)
    {
        nbpot++;
        lcd.clear();
        ecrire(0,0,"Continuer   [D]");
        /* lcd.setCursor(0, 1); lcd.print(nbpot);
         lcd.print(" pots");*/
        char txtA[16] = "";
        ecrire(0, 1, sprintf(txtA, "%d pots", nbpot));

        char key = kpd.getKey();
        while (key == NO_KEY && digitalRead(buttonPin) == HIGH)
        {
            key = kpd.getKey();
            if (key == 'D' || (digitalRead(buttonPin) == LOW))
            {
                comptage();
            };
        };
    }
    else if (cpt != nbgel)
    {
        lcd.clear();
        lcd.print("Pot incomplet");
        lcd.setCursor(0, 1);
        lcd.print(cpt);
        lcd.print(" gelules");
        char key = kpd.getKey();
        while (key == NO_KEY && digitalRead(buttonPin) == HIGH)
        {
            key = kpd.getKey();
            if (key == 'D' || (digitalRead(buttonPin) == LOW))
            {
                goto reprise;
            }
        }
    };
}
void inventaire()
{
    // Fonction d'inventaire
    int cpt = 0;
    unsigned long tempo = millis();
reprise:
    lcd.clear();
    lcd.print("Comptage en cours");
    do
    {
        digitalWrite(MOTOR, HIGH); // Establishes forward direction of Channel A
        digitalWrite(BRAKE, LOW);  // Disengage the Brake for Channel A
        analogWrite(3, 100);       // Spins the motor on Channel A at full speed
        int sensorVal = digitalRead(fbrpin);
        while (kpd.getKey() != 'A')
        {
            int sensorVal = digitalRead(fbrpin);
            if (sensorVal == LOW)
            {
                cpt++;
                delay(50);
            }
        };
        goto stop;
    } while (1);
stop:
    digitalWrite(MOTOR, LOW);
    digitalWrite(BRAKE, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Inventaire");
    lcd.setCursor(0, 1);
    lcd.print(cpt);
    char key = kpd.getKey();
    while (key == NO_KEY)
        key = kpd.getKey();
    if (key == 'D')
    {
        goto reprise;
    }
};

on utilise plutôt break pour sortir d'une boucle infinie, le goto est considéré comme 'moche' et source de bugs en programmation en C ou C++
rien n'empêcherait la loop d'appeler la fonction inventaire() en boucle plutôt que de rester dans cette fonction inventaire

si vous voulez gérer un timeout, il faut définit une constante pour le temps d'attente max

tempsMaxSansAction = 5000ul; // 5 secondes

puis initialiser un unsigned long derniereAction; à la valeur de millis avant de rentrer dans votre boucle, le ré-initialiser à millis() à chaque fois qu'il y a de l'activité et tester dans la boucle

if (millis() - derniereAction >= tempsMaxSansAction) {
  // gérer ici le timeout

}

Mais là c'est un peu un plat de spaghetti ce code :slight_smile:

vous gagneriez en lisibilité et maintenabilité à l'organiser en machine à états.

Merci pour votre réponse, je vais tester ça.

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