Tenez j'ai retrouvé un bout de code que j'avais
mettez ça dans un fichier AsyncTask.h
#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);
}
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
c'est une petite classe qui permet de gérer pour vous N trucs "à faire plus tard"
N est un paramètre d'instanciation (c'est un template) de la classe (pour ne pas avoir à le câbler en dur) qui dit combien de tâches au max vous pouvez avoir en parallèle. par exempleAsyncTask<10> gestionnaireDeTache;définit un objet nommé gestionnaireDeTache capable de contenir 10 tâches.
Une tâche se définie par un identifiant (un nombre), un délai à attendre en ms et une fonction à appeler (un callback).
Quand vous voulez que quelque chose se lance plus tard vous appelez la méthode registerAsyncCommand() en passant un N° d'identifiant (qui sera passé au callback), un délai d'attente avant d'appeler le callback et le pointeur sur la fonction à appeler.
Dans la loop() vous n'avez qu'à appeler à chaque tour de loop updateQueue(); pour déclencher les callbacks au bon moment
par exemple on va l'utiliser comme ça
#include "AsyncTask.h"
AsyncTask<10> gestionnaireDeTache;
void callback1(t_commandID identifier)
{
Serial.print(millis() / 1000);
Serial.print(F("\tCall back #1 pour ID = "));
Serial.println(identifier);
}
void callback2(t_commandID identifier)
{
Serial.print(millis() / 1000);
Serial.print(F("\tCall back #2 pour ID = "));
Serial.println(identifier);
gestionnaireDeTache.registerAsyncCommand(40, 5000UL, callback2); // on relance la tâche ID 40 pour dans 5 secondes
}
void setup()
{
Serial.begin(115200);
// on amorce avec 3 tâches futures dans 3, 6 et 9 secondes
gestionnaireDeTache.registerAsyncCommand(10, 3000UL, callback1);
gestionnaireDeTache.registerAsyncCommand(20, 6000UL, callback1);
gestionnaireDeTache.registerAsyncCommand(30, 9000UL, callback2);
}
void loop()
{
gestionnaireDeTache.updateQueue();
}
ce bout de code déclare dans le setup qu'on veut déclencher la fonction callback1 dans 3secondes, puis 6 secondes et la fonction callback2 dans 9 secondes
// on amorce avec 3 tâches futures dans 3, 6 et 9 secondes
gestionnaireDeTache.registerAsyncCommand(10, 3000UL, callback1);
gestionnaireDeTache.registerAsyncCommand(20, 6000UL, callback1);
gestionnaireDeTache.registerAsyncCommand(30, 9000UL, callback2);
les fonctions ne font qu'imprimer un petit message sur la console à 115200 bauds, et le callback2 remet une pièce dans la machine et redemande d'être rappelée 5 secondes plus tard en faisant gestionnaireDeTache.registerAsyncCommand(40, 5000UL, callback2); // on relance la tâche ID 40 pour dans 5 secondes
donc on va avoir un appel au bout de 3s, 6s, 9s puis ensuite toutes les 5 secondes. la console série va afficher
[color=purple][color=red]3 Call back #1 pour ID = 10
6 Call back #1 pour ID = 20
9 Call back #2 pour ID = 30[/color]
14 Call back #2 pour ID = 40
19 Call back #2 pour ID = 40
24 Call back #2 pour ID = 40
29 Call back #2 pour ID = 40
[/color]
On voit en rouge les 3 premiers callbacks (avec leurs identifiant 10, 20 30) au bout des 3,6 et 9 secondes et ensuite toutes 5 secondes on a l'autre callback pour l'ID 40.
voilà avec ça plus besoin de vous casser la tête avec millis(). Au moment ou vous ouvrez une vanne vous enregistrez un callback dont l'ID sera le numéro de la vanne et le temps que vous voulez conserver la vanne ouverte et vous écrivez un petit callback qui ne fait que fermer la vanne reçue en paramètre. ça se déclenchera pour vous tout seul, du moment que vous appelez en début de loop la fonction updateQueue().