faut pas faire pinMode(buttonPin, INPUT);
sinon vous cassez la classe de @bricoleau.. la pin du bouton est mise en INPUT_PULLUP lors de l'instanciation.
@bricoleau le bouton poussoir est la seulement pour simuler une variable interne, dans la finaliter c'est pas pour utiliser des BP, non seulement une tempo de basculement, une seul impulsion sur un relais.
si vous n'avez pas de vrai bouton que quelqu'un appui, ça ne va pas marcher avec la classe de @bricoleau...
ce dont vous avez besoin éventuellement si vous ne voulez pas gérer millis() vous même c'est une approche par gestion d'évènements.
J'avais posté pour @iznobe une classe AsyncTask qu'il utilise dans la gestion des ses volets
En gros quand vous voulez envoyer une impulsion au relais vous appelez une fonction qui active le relais et enregistre pour plus tard un callback (appel de fonction) qui se chargera d'éteindre le relais ce qui fabriquera donc la bonne impulsion. la classe AsyncTask permet de gérer tout cela, il suffit d'avoir dans la loop() un appel à updateQueue() assez fréquent
le callback prend un paramètre (un type particulier appelé t_commandID
qui est un nombre) et donc vous pouvez enregistrer le N° de pin dans la tâche comme cela le callback pourrait gérer plusieurs relais.
voici un code d'exemple, dans le setup() je demande une impulsion au relais et cette fonction enregistre le callback pour 2 secondes plus tard (en pratique vous mettriez 100ms pour un télérupteur). La console à 115200 bauds affichera aussi un petit message. Vous devriez voir la LED de la carte s'allumer, puis par magie s'éteindre 2 secondes plus tard.
le .ino
#include "AsyncTask.h"
AsyncTask<10> gestionnaireDeTache; // max 10 tâches en cours
const byte ledPin = LED_BUILTIN; // commande du relai (test avec LED de la carte)
void finImpulsion(t_commandID identifier)
{
Serial.print(F("FIN IMPULSION SUR PIN"));
Serial.println(identifier);
digitalWrite(ledPin, LOW);
}
void impulsionRelais(byte numPin)
{
Serial.print(F("IMPULSION SUR PIN #"));
Serial.println(numPin);
digitalWrite(numPin, HIGH);
// on enregistre de se faire notifier 2000ms plus tard pour éteindre le relais
// en pratique mettre 100ms
gestionnaireDeTache.registerAsyncCommand(numPin, 2000UL, finImpulsion);
}
void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
// on balance une impulsion
impulsionRelais(ledPin);
}
void loop()
{
gestionnaireDeTache.updateQueue(); // va gérer automatiquement le callback
// ici on peut faire autre chose si pas bloquant
}
le fichier AsyncTask.h à mettre dans le même répertoire que le .ino
#ifndef ASYNCTASK_H
#define ASYNCTASK_H
#include <Arduino.h>
typedef uint16_t t_commandID; // command idendifier is on 2 bytes (0x00 to 0xFFFF).
typedef void (*t_callback)(t_commandID); // same as "using t_callback = void (*)(t_commandID);"
template <uint16_t queueLength>
class AsyncTask
{
private:
struct t_queueCommand
{
t_callback callback; // a pointer to the function you want to execute after the delay is expired
t_commandID commandID; // An ID for this command, used in callBack
uint32_t maxWait; // how long to wait before the callback
uint32_t startTime;
bool active;
};
uint16_t _count;
t_queueCommand _queueCommandList[queueLength];
static const uint16_t _maxCommands = queueLength;
public:
// constructor
AsyncTask()
{
_count = 0;
for (uint16_t i = 0; i < _maxCommands; i++)
_queueCommandList[i].active = false;
}
bool registerAsyncCommand(t_commandID id, uint32_t deltaT, t_callback cb) {
// find the next empty slot
int32_t nextSlot = -1;
for (int32_t i = 0; i < _maxCommands; i++) {
if (! _queueCommandList[i].active) {
nextSlot = i; // found a position
break;
}
}
// register the command in that slot
if (nextSlot != -1) {
_queueCommandList[nextSlot].startTime = millis();
_queueCommandList[nextSlot].commandID = id;
_queueCommandList[nextSlot].callback = cb;
_queueCommandList[nextSlot].maxWait = deltaT;
_queueCommandList[nextSlot].active = true;
_count++;
} // else // error no room left
return (nextSlot != -1);
}
bool unregisterAsyncCommand(t_commandID id) {
bool commandRemoved = false;
for (int32_t i = 0; i < _maxCommands; i++) {
if ((_queueCommandList[i].active) && (_queueCommandList[i].commandID == id)) {
// on l'a trouvée
_queueCommandList[i].active = false;
_count--;
commandRemoved = true;
break;
}
}
return commandRemoved;
}
bool forceAsyncCommand(t_commandID id) {
bool commandExecuted = false;
for (int32_t i = 0; i < _maxCommands; i++) {
if ((_queueCommandList[i].active) && (_queueCommandList[i].commandID == id)) {
// trigger the callback
_queueCommandList[i].callback(_queueCommandList[i].commandID);
// mark it as done
_queueCommandList[i].active = false;
_count--;
commandExecuted = true;
break;
}
}
return commandExecuted;
}
bool findAsyncCommand(t_commandID id) {
bool commandFound = false;
for (int32_t i = 0; i < _maxCommands; i++) {
if ((_queueCommandList[i].active) && (_queueCommandList[i].commandID == id)) {
commandFound = true; // we found it !
break;
}
}
return commandFound;
}
uint16_t updateQueue()
{
uint16_t taskExpired = 0;
if (_count == 0) return false; // no command to execute
for (uint16_t i = 0; i < _maxCommands; i++) {
if (_queueCommandList[i].active) {
if (millis() - _queueCommandList[i].startTime >= _queueCommandList[i].maxWait) {
// trigger the callback
_queueCommandList[i].callback(_queueCommandList[i].commandID);
// mark it as done
_queueCommandList[i].active = false;
_count--;
taskExpired++; // count number of completed tasks
}
}
} // end for each possible task
return taskExpired;
}
// utilities
uint16_t maxCommands() const {
return _maxCommands;
}
uint16_t queueCount() const {
return _count;
}
};
#endif
PS/ on s'éloigne bcp de la classe SimpleBouton ce qui "pollue" le partage de @bricoleau, le mieux serait de demander au modérateur de déplacer toute cette discussion dans le forum principal et continuer la discussion là bas