Hello,
To simplify your designs, you may use C.A.T.H
Git source
Hello,
To simplify your designs, you may use C.A.T.H
Git source
Écrivez en français dans le forum francophone
Il y a FreeRTOS qui marche nickel pour les esp32 mais n'est pas compatible avec tous les modèles d'arduino.
Hello, ok désolé, je ne savais pas.
C.A.T.H est plus simple et fonctionne quasi partout
Oui c’est sûr et ça n’a surtout rien à voir…
En gros votre abstraction vous permet d’appeler des fonctions de temps en temps (cf ci dessous) mais si une de vos tâches fait un delay()
vous bloquez tout le monde et il n’y a pas de points de synchro (les tâches ne se connaissent pas entre elles) ou possibilité d’ajout et retrait de tâches au runtime ou de gestion du contexte d’une tâche (sa propre pile par exemple).
Ça a le mérite de montrer un exemple d’approche objet.
Quelques suggestions :
Pour le monde arduino vous auriez pu conserver la nomenclature standard et le camelCase et appeler vos fonctions membres setup()
et loop()
Au lieu de tout mettre dans le .ino, vous pourriez proposer une bibliothèque.
Le nombre de tâches pourrait être dynamique au lieu d’avoir un tableau de taille statique, faites une liste chaînée et vous rajoutez la tâche en début ou fin de liste à chaque nouvelle instance.
Vous devriez revoir la gestion du temps dans votre fonction S_Loop() et de m_LoopDelay
pour faire une vraie approche avec millis()
Sinon le code d’exemple pourrait être amélioré
avoir une bibliothèque
n’utilisez pas un booléen pour HIGH et LOW, ce n’est pas propre et sort de la documentation donc risque de problèmes si Arduino décidait de typer HIGH et LOW (dans un enum par exemple).
pourquoi un pointeur ????
Hello, merci d'avoir pris le temps de répondre.
En effet, ici delay bloque tout. mais on en a généralement pas besoins ou alors c'est que l'on sait ce que l'on fait. L'avantage d'une approche cooperative est de justement éviter la plupart des problèmes de partage de ressources qu'il faut gérer avec les mutex, volatile etc...
L'idée ici est d'avoir un outil très léger et très simple. SI vous regarder les projets que j'ai développé avec, ça simplifie énormément sans se prendre la tête
Je l'ai avant tout développé pour moi mais je pense que ça peut inspirer d'autres développeurs.
Voici mes réponses à vos remarques et suggestions :
Merci et bonne journée.
J'ai supprimé votre traduction du français vers l'anglais. Le forum français est réservé à ceux qui préfèrent communiquer en français, comme son nom l'indique. Si vous souhaitez utiliser l'anglais, vous trouverez de nombreux endroits où le faire. Si vous souhaitez traduire un message du forum dans une autre langue, vous pouvez le faire vous-même. Je constate que vous avez attiré l'attention des modérateurs à plusieurs reprises, principalement pour des contributions inutiles. C'est pourquoi je vous ai suspendu du forum pour une semaine. Profitez de vos vacances pour vous familiariser avec le guide du forum, disponible en haut de chaque catégorie.
Merci
oui, c'est juste que si vous proposez quelque chose pour le monde Arduino, autant suivre les recommandations Arduino. ça aide à l'adoption de nouvelles idées en faisant la promotion de chose "connues" (comme setup() et loop()).
Oui bien sûr, c'est hors du champ de ce que vous faites. C'était plus une réponse pour @axelmaux et FreeRTOS.
vos commentaires parlent de temps en ms
CathCnt m_CurCounter; // Curent number of ms before next Loop call
CathCnt m_LoopDelay; // Default period of Loop call (in ms)
mais ce n'est pas ce que fait le code il me semble.
ah ok - oui j'avais raté les variables globales.
en gros (tapé ici) votre classe pourrait ressembler à cela
class Cath {
public:
virtual void setup() = 0;
virtual void loop() = 0;
static void registerTask(Cath* task, unsigned long period) {
task->period = period;
task->lastRunTime = 0;
task->next = taskList;
taskList = task;
}
static void setupTask() {
for (Cath* task = taskList; task != nullptr; task = task->next) task->setup();
}
static void loopTask() {
unsigned long currentMillis = millis();
for (Cath* task = taskList; task != nullptr; task = task->next) {
if (currentMillis - task->lastRunTime >= task->period) {
task->loop();
task->lastRunTime = currentMillis;
}
}
}
private:
unsigned long period;
unsigned long lastRunTime;
Cath* next;
static Cath* taskList;
};
Cath* Cath::taskList = nullptr;
et le .ino ne ferait comme vous que
void setup() {
Cath::setupTask();
}
void loop() {
Cath::loopTask();
}
(pas testé, juste pour l'idée de la liste chaînée et la gestion de la periode par millis)
PS/ si vous pouvez changer le titre de votre post en français, ce serait vraiment mieux pour le forum...
Si j'avais ce programme à faire sans chercher à économiser le code, j'écrirais:
// voir https://github.com/Phildem/Cath/blob/main/Cat-exemple_Schematic.GIF
// *********************** SlowBlink ***********************
// Allumée 1s, éteinte 1s
const uint8_t LED_SLOW_BLINK = 4;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
MTsoftPWM SlowBlink(LED_SLOW_BLINK, impulsions_de 1000000L micro_secondes, periodes_de 2000000L micro_secondes);
// *********************** FastBlink ***********************
// Allumée 0,11s, éteinte 0,1s
const uint8_t LED_FAST_BLINK = 5;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
MTsoftPWM FastBlink(LED_FAST_BLINK, impulsions_de 110000L micro_secondes, periodes_de 210000L micro_secondes);
// *********************** Assymetric ***********************
// Allumée 50ms, période 1,11s
const uint8_t LED_ASSYMETRIC = 6;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
MTsoftPWM Assymetric(LED_ASSYMETRIC, impulsions_de 50000L micro_secondes, periodes_de 1110000L micro_secondes);
// *********************** A ou B ***********************
const uint8_t LED_A_OU_B = 7;
const uint8_t BOUTON_A_OU = 2;
const uint8_t BOUTON_B_OU = 3;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
void ou(void);
MTbutton BoutonAou(BOUTON_A_OU, ou, ou);
MTbutton BoutonBou(BOUTON_B_OU, ou, ou);
void ou(void)
{
pinMode(LED_A_OU_B, OUTPUT);
digitalWrite(LED_A_OU_B, BoutonAou.getSelect() | BoutonBou.getSelect() ? HIGH : LOW);
}
// *********************** A ET B ***********************
const uint8_t LED_A_ET_B = 8;
const uint8_t BOUTON_A_ET = 2;
const uint8_t BOUTON_B_ET = 3;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
void et(void);
MTbutton BoutonAet(BOUTON_A_ET, et, et);
MTbutton BoutonBet(BOUTON_B_ET, et, et);
void et(void)
{
pinMode(LED_A_ET_B, OUTPUT);
digitalWrite(LED_A_ET_B, BoutonAet.getSelect() & BoutonBet.getSelect() ? HIGH : LOW);
}
// *********************** A ouexclusif B ***********************
const uint8_t LED_A_OUEXCLUSIF_B = 9;
const uint8_t BOUTON_A_OUEXCLUSIF = 2;
const uint8_t BOUTON_B_OUEXCLUSIF = 3;
#include "MTobjects.h" // Voir http://arduino.dansetrad.fr/MTobjects
void ouexclusif(void);
MTbutton BoutonAouexclusif(BOUTON_A_OUEXCLUSIF, ouexclusif, ouexclusif);
MTbutton BoutonBouexclusif(BOUTON_B_OUEXCLUSIF, ouexclusif, ouexclusif);
void ouexclusif(void)
{
pinMode(LED_A_OUEXCLUSIF_B, OUTPUT);
digitalWrite(LED_A_OUEXCLUSIF_B, BoutonAouexclusif.getSelect() ^ BoutonBouexclusif.getSelect() ? HIGH : LOW);
}
// *********************** Pour faire autre chose ***********************
void setup(){}
void loop(){}
Et j'aurais le message:
Le croquis utilise 3384 octets (10%) de l'espace de stockage de programmes. Le maximum est de 32256 octets.
Les variables globales utilisent 283 octets (13%) de mémoire dynamique, ce qui laisse 1765 octets pour les variables locales. Le maximum est de 2048 octets.
Et le jour ou j'utiliserai Arduino pour faire du traitement de texte et de la vidéo, je me pencherais sur le multitask
Mais pour l'instant la bibliothèque utilisée est en maintenance.
Maintenant pour ce qui est de delay(), je l'aime bien et elle ne m'empêche pas de faire tourner un moteur pas à pas tout en l'utilisant comme le montre cet exemple:
/ Ce programme montre que l'on peut faire autre chose pendant un delay,
// et même suspendre un delay par un autre.
// Ce programme comporte un "blink with delay" en toile de fond.
// Quand on appuie sur un bouton, un pas à pas part pour faire un tour et
// après 1s une ligne est envoyée à la console série. Cette temporisation
// utilise un delay() qui va suspendre le blink. Les deux delay() simultanés
// ne vont pas gêner la lecture du bouton ni la rotation du moteur. Si on
// appuie sur le bouton juste après un changement dʼétat de la led, les deux
// delay comptent en même temps et le clignotement nʼest pas affecté. Si on
// appuie sur le bouton longtemps après le changement dʼétat de la led,
// cette dernière ne peut évidemment pas changer d'état car elle n'a pas la
// main. La durée du blink est alors modifiée.
#include "MTobjects.h" // V1.0.3 Voir http://arduino.dansetrad.fr/MTobjects
const uint8_t PIN_BOUTON = A0;
MTulnStepper Stepper(pin_A1 2, pin_B1 3, pin_A2 4, pin_B2 5);
void bouge(void)
{
Stepper.move(Stepper.getStepsPerTurn()); // Parti pour un tour de rotation
delay(2000 milli_secondes); // Qui va donc suspendre le delay du blink
Serial.println(F("C'est parti"));
}
MTbutton Bouton(PIN_BOUTON, bouge);
void setup()
{
digitalWrite(LED_BUILTIN, LOW); // Led en sortie, éteinte
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200); // Pour envoyer les messages
}
void loop()
{
// Programme classique du "blink with delay"
digitalWrite(LED_BUILTIN, HIGH);
delay(5000 milli_secondes);
digitalWrite(LED_BUILTIN, LOW);
delay(5000 milli_secondes);
}
Hello,
Il y a toujours plein de manière de faire les choses.
Les leds, c'était juste pour montrer le concept mais on peut faire des application plus complexes facilement comme :
ou
Hi,
J'ai changé le titre.
Oui, utiliser une liste chainée est en effet plus simple mais ce qui me gêne un peu dans ce cas ,c'est que dans certains cas, une tâche peut appeler une méthode d'une autres instance de tâche et se sera parfois moins pratique.
Merci !
Ok - compris (en surchargeant l’opérateur [] vous pourriez retourner la N-ieme tâche). Il y a effectivement plusieurs approches possibles vous pourriez aussi faire un template par exemple pour la taille max.
Si vous faites une bibliothèque c’est mieux si l’utilisateur n’a pas à modifier le code de la bibliothèque pour changer cette taille statique