Appuis long et temporisation

Bonjour à tous

Je suis assez nouveau avec la programmation Arduino et je bloque sur un programme.

Le but est de démarrer, à l’aide d’un bouton poussoir, un moteur CC sur une durée de temps prédéfinie de 1 minute donc avec une temporisation. Le moteur est géré par un contrôleur de type HBridge. J’utilise une Arduino Nano ESP32.
Jusque là, pas de problème j’ai fait un programme qui fonctionne.
Le voici:

int in1Pin = D4;           // pin to connect to motor controller board
int in2Pin = D5;           // pin to connect to motor controller board
int sleepPin = D6;         // pin to disable motor controller sleep mode
const int buttonPin = D3;  // switch
const int ledPin = D13;    // Arduino Nano integrated LED

int buttonState = 0;       // variable for reading the button status


void setup() {

  pinMode(buttonPin, INPUT);  // Set the push button pin as input

  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

  digitalWrite(sleepPin, LOW);  // enable the motor controller sleep mode

  digitalWrite(in2Pin, LOW);    // set the motor direction

}


void loop() {

  buttonState = digitalRead(buttonPin); // read the state of the button value

    if (buttonState == HIGH) {
      digitalWrite(sleepPin, HIGH);   // disable the motor controller sleep mode
      delay (500);                    // waits for 500ms
      digitalWrite(in1Pin, HIGH);     // turn the motor on
      digitalWrite(ledPin, HIGH);     // turn the led on
      delay (60000);                  // waits for 60 seconds (0.7 liter)
      digitalWrite(in1Pin, LOW);      // turn the motor off
      digitalWrite(ledPin, LOW);      // turn the led off
      }
    else {
      digitalWrite(in1Pin, LOW);      // if the switch is low, motor will turn off
      digitalWrite(ledPin, LOW);      // turn the led off
      digitalWrite(sleepPin, LOW);    // enable the motor controller sleep mode
      }

}

Je souhaite cependant pouvoir arrêter le cycle à tout moment, en faisant un appuis long sur le bouton poussoir, et c’est là que je butte…
J’ai décidé d’utiliser la bibliothèque Onebutton pour différencier les fonctions ‘appuis court’ et ‘appui long’, mais mon programme un comportement erratique et je n’arrive toujours pas à interrompre le cycle d’une minute…
Pourriez éclairer ma chandelle?
Voici le programme qui compile mais ne fonctionne pas…


#include <OneButton.h>
const byte in1Pin = D4;           // pin to connect to motor controller board
const byte in2Pin = D5;           // pin to connect to motor controller board
const byte sleepPin = D6;         // pin to disable motor controller sleep mode
const byte buttonPin = D3;        // switch
const byte ledPin = D13;          // Arduino Nano integrated LED
const unsigned long seuilTemps = 3000; // seuil de temps d'appui long

OneButton bouton(buttonPin);      // set the IMPUT_PULLUP 

// dans cette fonction, donc le clique simple, on demarre le moteur
void simpleClick() {
  digitalWrite(sleepPin, HIGH);  // disable the motor controller sleep mode
  digitalWrite(ledPin, HIGH);
  digitalWrite(in1Pin, HIGH);     // turn the motor on
  digitalWrite(in2Pin, LOW);      // set the motor direction
  delay (10000);                  // waits for 10 seconds
  digitalWrite(in1Pin, LOW);      // turn the motor off
  digitalWrite(in2Pin, LOW);    
  digitalWrite(sleepPin, LOW);    // enable the motor controller sleep mode
  digitalWrite(ledPin, LOW);
}

// dans cette fonction, donc le click long, on arrete le moteur et on active le mode sleep
void clickLong() {
  digitalWrite(sleepPin, LOW);    // enable the motor controller sleep mode
  digitalWrite(in1Pin, LOW);      // turn the motor off
  digitalWrite(in2Pin, LOW);    
}


void setup() {

  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

  bouton.setPressMs(seuilTemps);                // temps d'appui long 
  bouton.attachClick(simpleClick);               // fonction appelée en cas d'appui court pour lancer le moteur
  bouton.attachLongPressStop(clickLong);         // fonction appelée en cas d'appui long pour le mode veille
}


void loop() {

  bouton.tick();  // keep watching the push button
 
 // You can implement other code in here or just wait a while
  delay (10); 
}

: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

comment est branché le bouton?

Je n'ai pas vu d'attente d'une minute, mais de 10s.
De plus comme tu fais un delay qui est bloquant, tu ne passera plus dans la fonction tick de la librairie qui gère les détections de tes boutons.

Il faudrait plutôt avoir des variables t'indiquant dans quel cas tu es, ce qui te permettra de tout gérer dans la loop et combiner avec la fonction millis gérer le timing des actions.
Idéalement il faudrait faire une machine à état fini, comme aime bien le dire @J-M-L :slight_smile:

dans le second sketch, je l'ai branché : GND - BP - pin D3

j'ai effectivement reduit à 10 secondes le cycle d'allumage du moteur pour les tests. Desolé de m'être mal exprimé...
Si je comprends bien, si un delay est en cours, je ne peux plus faire capter d'action sur le bouton poussoir? Si c'est le cas, il me sera peut etre plus simple de repartir du premier sketch pour gerer differement l'appui long, sans passer par la bibilo Onebutton?

testez votre code en vidant les fonctions (gardez juste un print). ça devrait fonctionner

#include <OneButton.h>
const byte buttonPin = 3;        // switch
const unsigned long seuilTemps = 3000; // seuil de temps d'appui long

OneButton bouton(buttonPin);      // set the IMPUT_PULLUP

// dans cette fonction, donc le clique simple, on demarre le moteur
void simpleClick() {
  Serial.println("SIMPLE CLICK");
}

// dans cette fonction, donc le click long, on arrete le moteur et on active le mode sleep
void clickLong() {
  Serial.println("LONG CLICK");
}

void setup() {
  Serial.begin(115200);
  bouton.setPressMs(seuilTemps);                // temps d'appui long
  bouton.attachClick(simpleClick);               // fonction appelée en cas d'appui court pour lancer le moteur
  bouton.attachLongPressStop(clickLong);         // fonction appelée en cas d'appui long pour le mode veille
}

void loop() {
  bouton.tick();  // keep watching the push button
}

comme le dit @terwal pendant l'attente de 10s rien ne se passera puisque vous ne lisez plus l'état du bouton en passant dans la loop

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

Ce code ne fonctionne pas non plus ...
Je vais essayer avec la machine à etat et le lien vers ton tuto, c'est surement plus adapté :slight_smile:

Non, si j'ose dire ça sera plus compliqué :slight_smile:
L'idéal serait de passer par une machine à état ou du moins quelque chose s'y rapprochant si cela te parait trop compliqué.

Ce que tu as besoin c'est que dans les fonctions de gestion des boutons tu ne bloque pas ton programme.
Donc que tu te contente d'affecter des variables.
Alors tu pourra gérer toute la logique des actions dans ta loop, qui ne doit pas non plus être bloquant, car tu as besoin d'appeler la fonction tick très régulièrement en fonction de la réactivité que tu veux avoir sur tes boutons.
Je ne sais pas si j'était assez claire ?

je l'ai copié dans un wokwi, il me semble qu'il fonctionne très bien ?

Quel Arduino utilisez vous?
Photo du montage ?

Le code devrait fonctionner

Merci pour les reponses. Il faut que je regarde et comprenne effectivement les machines à etat :slight_smile:
J'ai retesté le code en ne laissant que le branchement du BP, mais je n'obiens qu'un retrour LONG CLICK lorsque je debranche la pin3... J'ai pas le message 'program start'... alors que sur le Woki cela fonctionne bien.
J'ai essayé sur une autre PIN de la Nano, meme comportement...

Vous n'avez pas répondu

il faut peut être rajouter un

while(Serial) delay(1); 

dans le setup pour attendre que la liaison série soit établie ou il se peut que D3 soit sur le port série etc...

C'est une Nano ESP32...
Le BP a 6 broches; il est bien branché (et testé) sur deux broches qui se connectent lors de l'appui.

Bonjour sebalaco

Non, ce n'est pas plus simple, et de loin!
OneButton te permet d'avoir un programme beaucoup plus "propre", il te mâche tout le travail.
Il te faut surtout travailler sur les états du moteur, seules choses à changer dans l'action du bouton.
Ainsi, dans mon exemple, il y a ces états:

enum {moteurEtatArrete, moteurEtatDoitDemarrer, moteurEtatMarche, moteurEtatCycleArret, moteurEtatDoitArreter};

Ainsi, tout est traité dans loop().
Dans cet exemple, seul buttonPin = 3 et ledPin = 13 fonctionnent.
La temporisation est:

const unsigned long moteurMarcheTempo = 10000;     // Temps de marche du moteur

Mets ta console à 115200 pour "voir" fonctionner le programme

Le programme:

#include <OneButton.h>
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 = 3;        // switch
const byte ledPin = 13;          // Arduino Nano integrated LED
const unsigned long seuilTemps = 3000; // seuil de temps d'appui long

OneButton bouton(buttonPin);      // set the IMPUT_PULLUP

enum {moteurEtatArrete, moteurEtatDoitDemarrer, moteurEtatMarche, moteurEtatCycleArret, moteurEtatDoitArreter};
int moteurEtat = moteurEtatArrete;
const unsigned long moteurMarcheTempo = 20000;     // Temps de marche du moteur
unsigned long moteurMarcheMillis = 0;     // Temps de marche du moteur, chrono

// dans cette fonction, donc le clique 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;
}


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

	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

	bouton.setPressMs(seuilTemps);                // temps d'appui long
	bouton.attachClick(simpleClick);               // fonction appelée en cas d'appui court pour lancer le moteur
	bouton.attachLongPressStop(clickLong);         // fonction appelée en cas d'appui long pour le mode veille

	moteurEtat = moteurEtatDoitArreter;
}


void loop()
{
	bouton.tick();  // keep watching the push button

	if (moteurEtat == moteurEtatDoitDemarrer)
	{
		Serial.println(F("Moteur en marche"));
		Serial.println("\t" + String(moteurMarcheTempo) + " millisecondes");
		moteurMarcheMillis = millis();     // Démarrage du chrono
		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 && (millis() - moteurMarcheMillis >= moteurMarcheTempo))     // Si fin de cycle
	{
		Serial.println(F("Moteur Fin cycle"));
		moteurEtat = moteurEtatDoitArreter;
	}
}

void moteurDemarrage()
{
	digitalWrite(ledPin, HIGH);
}

void moteurArret()
{
	digitalWrite(ledPin, LOW);
}

A+
Cordialement
jpbbricole

branchez les boutons à cheval sur la ligne centrale (suivant comment vous le tournez vous aurez un court circuit entre ses pins sinon)

On câble les boutons le plus souvent en "croisé" pour éviter de tomber sur les 2 même pins à l'intérieur du bouton

rajoutez le while(Serial) delay(1);

attention aux rails d'alim de votre breadboard qui est coupée au milieu (si vous vous en servez)

Merci pour ces conseils et l'explication détaillée ! je vais essayer de comprendre le programme et de le tester :slight_smile:
Mais avant il faudrait que mon montage fonctionne sur l'exemple de JML, ce qui n'est pas encore le cas...

Bonjour sebalaco

As tu un lien sur le bouton poussoir que tu utilises?

branchez le bouton comme il le faut... vous avez un multimètre ?

Suivant ton niveau et celui-ci est celui d'un débutant, il est généralement plus efficace de faire toi même le programme en rajoutant des fonctionnalités au fur à mesure et en abusant de la sortie sur le moniteur série(Serial.print, Serial.println)

1 Like

meme si la photo ne semble pas l'indiquer, le BP est bien branché :slight_smile:
j'ai essayé en rajoutant ce bout de code dans le set up mais cela ne change rien.
Sur la Nano ESP32 ce sont les pins D0 et D1 qui sont peuvent etre utilisées pour liaison serie
J'ai aussi essayé en rajoutant le while dans le woki et là, le programme ne fonctionne plus...