Comment gérer le temps dans un programme ?
et comment faire plusieurs tâches simultanément
. Par : Dominique, Guillaume, Jean-Luc
Vous répondez à :
Voila Votre code adapté pour 2 leds si j’ai bien compris ? mon code est il bon ? ou sera trop chargé sur 37 leds ou autre anomalie dans ma manière d’aborder et de construire mon montage qui fera clignoter les phares et les balises dans leur clignotement réels sur une carte marine( oui ce n’est pas du ferroviaire mais bon) le projet est de reproduire la rade de Brest avec ses balises et feux de nuit qui ont tous une couleur et un clignotements différents pour qu’un navigateur ne se perde pas la nuit et sache par rapport aux annotations de la carte officielles reconnaitre les fréquences de clignotement des repères lumineux
suis pas sur d’être clair
merci
bernard
65 Messages
-
Comment gérer le temps dans un programme ? 14 janvier 2015 16:25, par Stéphane
je sens que c’est pile ce que je veux essayer de faire pour mon réseau. Avec votre aide, plus celle du forum LRPresse les idées se mettent en place.
Merci à tous. -
Comment gérer le temps dans un programme ? 14 janvier 2015 16:26, par Stéphane
Et j’attends impatiemment la suite avec les objets ;-)
-
Comment gérer le temps dans un programme ? 26 janvier 2015 10:42, par petitrain
Bonjour à toute l’équipe
Bravo pour ce blog et toute l’aide que vous apportez.J’ai suivi avec grand intérêt cet article sur le temps. J’essaie de faire une fonction pour gérer la pwm sans delay mais sans succés.
Pouvez-vous m’aiguiller pour me dire pourquoi ça ne va pas
Je voudrais que les deux leds aient une progression ensemble, bien sur à des rythmes différents.
Dans la loop, Arduino n’exécute que le premier appel de la fonction, si je mets un // devant, alors il exécute le deuxième appel.
Merci pour votre aide.byte x=0; unsigned long tempsPresent; void monteeEclairage(byte numeroBroche,int interval){ if(millis()>=tempsPresent+interval){ tempsPresent= tempsPresent+interval; analogWrite(numeroBroche,x); x=x+1; } } void setup(){ pinMode(3,OUTPUT); pinMode(5,OUTPUT); unsigned long tempsPresent=0; } void loop(){ monteeEclairage(3,100); monteeEclairage(5,200); }
-
Bonjour,
quand tu veux faire appel à deux fonctions distinctes utilisant millis(), il te faut stocker le temps dans 2 variables différentes.
Car dans ton cas seule la 1ère fonction avec les paramètres est exécutée entièrement, temps est "remis à 0" et la condition dans la 2ème fonction n’attend jamais 200.Dans ton programme aussi, j’avoue que je ne sais pas comment analogWrite gère le x sup à 255. Rajoute peut être une condition pour dire stop ou pour faire repartir au début.
Une petite suggestion : introduis des constantes pour désigner tes broches.
-
Bonjour et merci :)
Guillaume a raison. Le problème vient de la variable
tempsPresent
qui est utilisée pour les deux DEL. Lors du 2e appel à la fonction :monteeEclairage(5,200);
,millis()>=tempsPresent+interval
est toujours faux puisquetempsPresent
vient juste d’être changé par l’appel précédent. Donc tout se passe comme si le 2e appel n’avait pas d’effet. De manière général l’appel avec l’intervalle le plus court fonctionnera bien, les autres non.Il faut donc une variable par DEL.
C’est un peu compliqué car la fonction doit pouvoir changer cette variable. Il faut donc passer un pointeur ou une référence. Essayez comme ceci :
byte x=0; unsigned long tempsPresentDEL3 = 0; unsigned long tempsPresentDEL5 = 0; /* * le & après le unsigned long indique que l'argument tempsPresent * est passé par référence. Si tempsPresent est modifié dans la fonction, * la variable passée en argument sera modifiée */ void monteeEclairage(byte numeroBroche,int interval, unsigned long& tempsPresent) { if(millis()>=tempsPresent+interval){ tempsPresent= tempsPresent+interval; analogWrite(numeroBroche,x); x=x+1; } } void setup(){ pinMode(3,OUTPUT); pinMode(5,OUTPUT); } void loop(){ monteeEclairage(3, 100, tempsPresentDEL3); monteeEclairage(5, 200, tempsPresentDEL5); }
Concernant la variable x, elle est de type byte. Sa valeur maximum est donc 255. Quand elle est augmentée de 1 alors qu’elle est à 255, elle repasse à 0.
-
Comme je lis vite, je n’avais pas regardé le type comme d’habitude me diras tu...
mais si le type est alors de int que se passe-t-il sur l’analogWrite si on le met à 600 par exemple ?
-
-
-
-
Comment gérer le temps dans un programme ? 26 janvier 2015 17:12, par petitrain
Merci à tous les deux pour vos réponses rapides et précises.
J’en étais presque arrivé à la bonne formulation après la réponse de Guillaume mais il me manquait le & après le 3ème paramètre de ma fonction (manque de connaissance !!!).
A guillaume : effectivement ma variable est une byte donc débordement...
pour les constantes de broches, je voulais faire voir aux personnes de mon club quelles n’étaient pas obligatoires et expliquer l’intérêt de les déclarer au début ; j’ai pris l’habitude de mettre des commentaires quand le programme tourne bien.
Encore merci à vous deux.-
Il y aura prochainement un article sur les fonctions et notamment le passage des arguments ;-)
-
-
Comment gérer le temps dans un programme ? 8 février 2015 12:09, par Doxy
Bonjour et bravo pour cet article sur la fonction millis
La fonction Delay m’avait déçu ; certes elle m’avait permis de faire un montage sympas mais impossible à ma carte Arduino de faire autre chose en même temps ; http://forum.e-train.fr/viewtopic.p...;; j’ai bien l’intention de m’y remettre pour d’autre éclairage. -
Comment gérer le temps dans un programme ? 4 août 2016 17:29, par Précillia
Bonjour à tous,
Merci pour cet article qui m’a déjà pas mal aidé !
Je souhaiterai contrôler l’allumage ou l’extinction de 5 LEDs de couleurs différentes (UV, bleu, vert, orange et rouge) tout en contrôlant leur intensité d’éclairement (PWM wave).Par exemple,
en premier je souhaiterai que les LEDs s’allument avec les valeurs suivantes pendant 1min :
UV = 0
BLEU = 0
VERT = 0
ORANGE = 0
ROUGE = 125
(Donc ici, seule la rouge est allumée)Ensuite toutes les éteindre pendant 2 min
Puis pendant 1min :
UV = 0
BLEU = 0
VERT = 75
ORANGE = 2
ROUGE = 10Etc...et j’en ai d’autres.
J’avais pensé utiliser le code suivant :
int uv = 13; int bleu = 3; int vert = 11; int orange = 10; int rouge = 9; byte etatDELUV = 0; byte etatDELBLEU = 0; byte etatDELVERT = 0; byte etatDELORANGE = 0; byte etatDELROUGE = 125; unsigned long dateDernierChangementUV = 0; unsigned long dateDernierChangementBLEU = 0; unsigned long dateDernierChangementVERT = 0; unsigned long dateDernierChangementORANGE = 0; unsigned long dateDernierChangementROUGE = 0; void setup() { pinMode(uv, OUTPUT); pinMode(bleu, OUTPUT); pinMode(vert, OUTPUT); pinMode(orange, OUTPUT); pinMode(rouge, OUTPUT); } void UV() { unsigned long dateCourante = millis(); unsigned long intervalle = dateCourante - dateDernierChangementUV; if (etatDELUV == 0 && intervalle > 720000) { etatDELUV = 125; analogWrite(uv, etatDELUV); dateDernierChangementUV = dateCourante; } else if (etatDELUV == 125 && intervalle > 60000) { etatDELUV = 0; analogWrite(uv, etatDELUV); dateDernierChangementUV = dateCourante; } else if (etatDELUV == 0 && intervalle > 120000) { etatDELUV = 250; analogWrite(uv, etatDELUV); dateDernierChangementUV = dateCourante; } } void BLEU() { unsigned long dateCourante = millis(); unsigned long intervalle = dateCourante - dateDernierChangementBLEU; if (etatDELBLEU == 0 && intervalle > 540000) { etatDELBLEU = 50; analogWrite(bleu, etatDELBLEU); dateDernierChangementBLEU = dateCourante; } else if (etatDELBLEU == 50 && intervalle > 60000) { etatDELBLEU = 0; analogWrite(bleu, etatDELBLEU); dateDernierChangementBLEU = dateCourante; } else if (etatDELBLEU == 0 && intervalle > 120000) { etatDELBLEU = 50; analogWrite(bleu, etatDELBLEU); dateDernierChangementBLEU = dateCourante; } else if (etatDELBLEU == 50 && intervalle > 60000) { etatDELBLEU = 0; analogWrite(bleu, etatDELBLEU); dateDernierChangementBLEU = dateCourante; } else if (etatDELBLEU == 0 && intervalle > 120000) { etatDELBLEU = 100; analogWrite(bleu, etatDELBLEU); dateDernierChangementBLEU = dateCourante; } }
etc ... pour toutes les LEDs
puis enfin :
void loop() { UV(); BLEU(); VERT(); ORANGE(); ROUGE(); }
Mais malheureusement, certaines LEDs s’allument mais pas dans l’ordre que je souhaite...
Je ne m’y connais pas assez en programmation pour savoir d’où vient mon erreur, et si j’utilise les bonnes fonctions.Pourriez-vous m’aider ? ou me renvoyer vers une explication ?
Merci beaucoup !-
Je pense comme Jean-Luc que votre programmation est du type "à donner des résultats imprévisibles" !
Pour vous répondre directement, il faudrait réaliser le montage et tester le logiciel en ajoutant des affichages des états sur le moniteur.
Cette piste vous conduirait à programmer autrement. Des automates de ce genre existent en exemple un peu partout. Sur Locoduino, la bibliothèque ScheduleTable est là pour cela. Elle vous donnera des instants déterminés et remettra vos événements en ordre.
Bon courage.
-
bonjour Dominique
je suis heureux que vous parliez et répondiez en FRANÇAIS pour certaine personne et en plus "Bon courage" pour ce Monsieur, quel honneur !!!! alors que moi j’ai terminé mon message par "Amicalement". et aucune marque de civilité, avec une réponse en ANGLAIS, par contre Jean-Luc m’a répondu en FRANÇAIS et a terminé sa réponse par "cordialement".
il a peut-être plus d’éducation que vous ????
et si cela vous dérangeait de répondre à ma question "basique", il fallait, vous en dispenser, cela vous aurait dispensé de mes commentaires.
il faut peut-être prendre les à leur niveau et descendre de votre nuage de je sais TOUT.
si les questions posées ne semblent pas de votre niveau, laissez d’autres plus sympa y répondre.
en plus Jean-Luc m’a mis un lien.
au plaisir de ne plus vous lire.
PS : mon mail concernait la signification de while(!) pour info.
"si tous les animateurs étaient comme vous, le site aurait très mauvaise presse".
Amicalement
Phil
-
-
-
Comment gérer le temps dans un programme ? 4 août 2016 17:34, par Jean-Luc
Bonjour,
Quand ça devient trop compliqué, on s’y perd. Peut-être devriez vous essayer la La bibliothèque ScheduleTable que j’ai réalisée pour précisément faciliter ce type de programmation.
-
Super, merci beaucoup pour votre aide !
Je vais regarder avec ScheduleTable, ça semble effectivement moins compliqué !
-
-
Comment gérer le temps dans un programme ? 10 mai 2018 17:43, par an
Une petite remarque concernant la fonction micros() : elle a, selon les cartes Arduino (et aussi, apparemment, sur les ATtiny85 et sans doute d’autres), une résolution de quatre ou huit microsecondes (c’est-à-dire que la fonction retourne toujours un multiple de quatre ou huit ; cf. le lien joint pour les cartes Arduino ; pour les ATtiny je ne sais pas où on peut trouver cette info mais cela semble également valable…).
Sur certains programmes cela peut avoir son importance… Par exemple dans un programme tournant sur un attiny85 où j’avais besoin d’un nombre plus ou moins aléatoire entre 1 et 6, je l’obtenais en calculant, à chaque fois que j’appuyais sur un bouton : (micros() % 6 + 1)). Et je ne comprenais pas pourquoi je n’obtenais que des nombres impairs !
Bonne journée !Voir en ligne : https://www.arduino.cc/reference/en...
-
Bonjour,
effectivement la résolution de
micros()
varie selon le microcontrôleur. Sur un ATMega 328 (Uno), par exemple, elle est basée sur le Timer 0 qui fait un tour en 256 ticks et 1024 microsecondes. Par conséquent le tick vaut 4μs et on ne peut pas avoir une mesure de temps plus fine à moins d’utiliser un autre Timer pour le faire.
-
-
Comment gérer le temps dans un programme ? 3 mars 2019 13:44, par Lionel
Bonjour,
Personnellement j’ai résolu ce problème en utilisant un compteur.
A chaque loop j’incrémente ce compteur avec une pause de 1 sec, ce qui permet pendant ce temps de contrôler les autres entrées.int reset = 8 ; // sortie reset
int capteur = 2 ; // entrée capteur
int appelHaut = 9 ; //sortie appel extrème haut
int inspection = 3 ; // entree commande inspection
int compteur ;void setup()
pinMode(inspection, INPUT_PULLUP) ;
pinMode(capteur, INPUT_PULLUP) ;
pinMode(reset, OUTPUT) ;
pinMode(appelHaut, OUTPUT) ;
compteur = 0 ;
void loop()
if (digitalRead (capteur) == HIGH or digitalRead (inspection) == LOW)
compteur = 0 ;
if (digitalRead (capteur) == LOW)
compteur ++ ;
delay (1000) ;
if (compteur == 10)digitalWrite (reset, HIGH) ;
delay (1000) ;
digitalWrite (reset, LOW) ;
delay (1500) ;
digitalWrite (appelHaut, HIGH) ;
delay (1000) ;
digitalWrite (appelHaut, LOW) ; -
Comment gérer le temps dans un programme ? 17 mars 2019 20:38, par PECOURT Jean-Louis
Bonsoir,
Je désirerais une petite précision. Il y a des choses qui rentrent (en se creusant un peu la tête...) ; mais d’autres où cela coince...
Dans ce logiciel, il y a deux déclarations en Byte (byte etatDEL13 = HIGH et identique pour l’autre sortie).
Pourquoi Byte et pas Boolean, qui serait - à mon sens - plus logique ?
Un booléen peut être vrai/faux ou haut/bas ou 1/0. Mais le Byte est un octet, et (pour ce que j’en ai compris), correspond à une valeur numérique.
Bon d’accord, le programme marche dans les deux cas. Mais si on peut utiliser des bytes pour des booléens, quel est l’intérêt de ce type de donnée ?
Cordialement.
J.L.-
Bonsoir, il y a deux réponses à cette question. Tout d’abord le C est assez basique en ce qui concerne le typage et les booléens n’existent pas vraiment, ce sont en réalité des entiers sur un octet. Ensuite l’état d’un broche, HIGH ou LOW, n’est pas un booléen mais un octet.
-
-
Comment gérer le temps dans un programme ? 15 février 2020 14:06, par Fabien
Bonjour !
Merci pour cet article très clair.
J’ai cependant une question.
Du fait de la boucle sans fin ni pause, le CPU de l’arduino ne va t’il pas être en permanence à 100% et donc chauffer ?
A+
Fabien-
De toute manière, de boucler, le CPU n’a que ça à faire et il est conçu pour cela !
-
C’est un point de vue. Un autre ici (en anglais https://wiki.c2.com/?BusyWaiting)
-
Difficile de se faire une idée sur des conseils de programmation sortis de leur contexte. Mais pour autant qu’on puisse en juger, l’auteur considère que c’est maladroit de bloquer un programme temps réel par une boucle d’attente. Ce le serait à moins.
Pour autant je ne vois pas le lien avec une surchauffe du processeur. -
C’est un point de vue qui considère qu’on dispose d’un système d’exploitation. Ce n’est pas le cas pour l’Arduino.
-
-
-
-
Comment gérer le temps dans un programme ? 15 février 2020 19:47, par Fabien
Effectivement si le cpu à 100% est bien refroidi il ne devrait pas y avoir de problème à part une consommation électrique elle aussi au max.
Au cas où la carte arduino serait mal ventilée et/ou sans radiateur il faut faire attention.
Personnellement l’introduirais tout de même une petite tempo dans la boucle pour ne pas la laisser à fond.-
Je pense que vous transposez ici les problèmes de température des processeurs d’ordinateurs qui consomment des dizaines de watts.
La figure 35-2. de la fiche technique de l’ATmega328P donne une consommation de 5 mA sous 5V à 8MHz soit 25mW en mode actif. (et aucune différence suivant les instructions exécutées).
La difficulté est plutôt d’avoir un programme qui marche et comme le dit l’article que vous signaliez il vaut mieux que le processeur reste actif en permanence puisque nous sommes en temps réel.
-
Oui,
vous pouvez faire tourner n’importe quel microcontrôleur à 100% pendant des jours, la température sera légèrement supérieure à la température ambiante.
-
Et si on prend en considération une résistance thermique boitier / ambiance de 50°C/W, on a une élévation de température de 50 x 25 10-3 = 1,25°C
-
-
-
-
Comment gérer le temps dans un programme ? 11 mars 2020 11:43, par AMARA Yazid
Bonjour,
Je dois écrire un programme dans lequel je dois déterminer la moyenne de clics sur le bouton poussoir par seconde. Mon problème c’est que je sais pas comment identifier le temps(la durée) entre le premier et le dernier clic.
Je dois calculer nombre de clics/intervalle de temps entre premier et dernier clic
Merci pour votre aide.
-
Comment gérer le temps dans un programme ? 11 mars 2020 12:55, par msport
LOCODUINO est consacré aux discussions ayant trait à l’utilisation de l’Arduino dans les automatismes et les animations pour le train miniature. Si vos questions ne concernent pas le modélisme ferroviaire, vous perdez votre temps et nous aussi.
Par ailleurs, vous avez la réponse à vos questions dans l’article à travers les exemples donnés. -
Comment gérer le temps dans un programme ? 19 novembre 2020 13:23, par Etienne
Je m’interroge sur la portée des variables dan votre exemple.
La variable dateDernierChangementUV n’est pas initialisée la première fois ! Comment pouvez-vous être sur que cette valeur sera inférieure à la valeur retournée pas le fonction millis() la première fois. Est-ce que toutes les variables sont initialisée à 0 au démarrage ?
J’avais cru comprendre que le langage était du C ! en retournant dans un fonction, les variable locales ne devraient pas conserver leur valeur (enfin elle le pourrait mais rien ne le garanti).Je débute en programmation Arduino, mais je suis assez perplexe !
-
Comment gérer le temps dans un programme ? 19 novembre 2020 17:35, par msport
Vous posez une question à un intervenant ou à l’auteur ?
Sauf erreur, par défaut les variables sont initialisées à 0 par l’IDE.
Avec les Arduino, rien de tel que l’expérimentation, parfois on a des surprises. -
Comment gérer le temps de mon moteur pas a pas avec ( Millis) ? 15 juillet 2021 16:02, par Dadou
bonjour, cela fait plusieurs jour que j’essaie de programmer mon stepper moteur. Je veux le faire tourner d’un sens puis de l’autre chaque 2h,durant 18jours.
pour le moment j’essaie de faire la 1ere partie ( tourner à chaque 2h) , mais cela ne marche pas. s’il vous plait quelqu’un peut m’aider c’est pour mon projet de fin d’etude. merci.
le code que j’ai fait :#include <Stepper.h> #define in1Pin 8 #define in2Pin 9 #define in3Pin 10 #define in4Pin 11 Stepper motor(50, in1Pin, in2Pin, in3Pin, in4Pin); const long onDuration = 500;// OFF time const long offDuration = 500;// ON time long rememberTime=0;// this is used by the code const int NbrPas =50; Stepper monmoteur(NbrPas, in1Pin, in2Pin, in3Pin, in4Pin); void setup() { monmoteur.step(50); Serial.begin(9600); pinMode(in1Pin,OUTPUT); pinMode(in2Pin,OUTPUT); pinMode(in3Pin,OUTPUT); pinMode(in4Pin,OUTPUT); monmoteur.setSpeed(20); // Vitesse à 10 tours/min } void loop() { int j= NbrPas; int i=-NbrPas; if ( (millis()- rememberTime) >= onDuration ) { monmoteur.step(-50); rememberTime=millis();// remember Current millis() time } else { if( (millis()- rememberTime) >= 1000){ monmoteur.step(50); rememberTime=millis();// remember Current millis() time } } }
-
Bonjour chère camarades, comment allez-vous ? J’espère que vous allez bien !
Bon a vrai dire moi aussi je suis confronté au même problème que vous et j’aimerais vous demandez de l’aide vu que ça fait longtemps que vous vous êtes confronter à ceci._
-
-
Comment gérer le temps dans un programme ? 15 juillet 2021 18:45, par Dominique
Est-ce un projet de modélisme ferroviaire ? Si oui le debugging de programme se fait plutôt sur le forum.
-
signification de (while !) en début de programme 10 décembre 2022 14:50, par Phil
Bonjour Messieurs
pouvez-vous me dire à quoi sert ce fameux (while !) souvent en début de programme dans le setup (), avant ou après :
"Serial.begin(9600) ;"
est-il indispensable ???
Merci
Amicalement
Phil-
The while(Serial) loop is NOT waiting for you to open the Serial Monitor. It is waiting for the USB to Serial chip to report that it us ready. That chip gets ready pretty quick.
-
Bonjour,
C’est expliqué dans la documentation : https://www.arduino.cc/reference/en...Cordialement
-
-
(while !) 11 décembre 2022 15:00, par phil
bonjour Messieurs
Merci, de votre réactivité mais surtout de votre réponse.
bonne journée.
Amicalement.
Phil-
bonjour Dominique
je suis heureux que vous parliez et répondiez en FRANÇAIS pour certaine personne et en plus "Bon courage" pour ce Monsieur, quel honneur !!!! alors que moi j’ai terminé mon message par "Amicalement". et aucune marque de civilité, avec une réponse en ANGLAIS, par contre Jean-Luc m’a répondu en FRANÇAIS et a terminé sa réponse par "cordialement".
il a peut-être plus d’éducation que vous ????
et si cela vous dérangeait de répondre à ma question "basique", il fallait, vous en dispenser, cela vous aurait dispensé de mes commentaires.
il faut peut-être prendre les à leur niveau et descendre de votre nuage de je sais TOUT.
si les questions posées ne semblent pas de votre niveau, laissez d’autres plus sympa y répondre.
en plus Jean-Luc m’a mis un lien.
au plaisir de ne plus vous lire.
PS : mon mail concernait la signification de while(!) pour info.
"si tous les animateurs étaient comme vous, le site aurait très mauvaise presse".
Amicalement
Phil-
Bonjour,
Ma foi, il existe sans doute plusieurs Dominique/dominique par ici. Normalement Dominique est authentifié car il est rédacteur sur Locoduino et donc son prénom n’apparaîtra pas avec un d minuscule.
J’ai donc regardé les IP de Dominique et de dominique. Il se trouve qu’ils n’ont pas la même IP et que l’IP de dominique n’est pas une IP française alors que celle de Dominique l’est.
Par conséquent, il semble que vous ayez confondu les Dominique/dominique, ce qui n’est pas étonnant car ils sont légion.
Et donc on fait quoi de vos invectives à la suite de la réponse de Dominique que vous avez postées là et qui apparaissent comme parfaitement injustifiées (si on peut juger justifié le fait de régler ses comptes dans les forums des articles de Locoduino) ?
Cordialement -
Bonjour Phil,
j’ai vu cette réponse en anglais. Elle provient du site Arduino.cc où tout un chacun peut puiser ses connaissances en complément de Locoduino, en ce qui concerne les questions simples, mais la réponse en anglais se traduit facilement par les nombreux traducteurs disponibles.Votre agressivité n’a pas lieu d’être de toute façon et cela me semble pire que ce dont vous vous plaignez.
Cordialement
-
Bonjour Messieurs
Jean-Luc et Dominique avec D
je suis désolé de cette confusion entre D et d car jusqu’à présent je n’avais jamais été confronté à ce genre de problème. A chaque question (cette été),une réponse de Christian ou jean-Luc (avec formule de politesse) mais je ne m’attendais pas à recevoir une réponse en Anglais alors que la question a été posé en français. alors effectivement, il existe des traducteurs (et c’est ce que j’ai fait) mais pourquoi le fameux dominique ne m’a pas répondu en FRANÇAIS ???? (avec un traducteur).Bref, déjà merci à Jean-Luc sa réactivité, qui m’a toujours très bien répondu et désolé pour Dominique pour qui mon message et ma colère (visiblement) n’était pas destiné.
Amicalement.
Phil
-
-
-
-
Comment gérer le temps dans un programme ? 13 décembre 2022 17:01, par msport
Bonjour,
à tout le moins, on peut relire le chapitre sur la convivialité (et pas que) dans le sujet :
Où et comment demander de l’aide ?
Cordialement-
Bonjour msport
je viens de lire ce chapitre.
une fois de plus désole pour l’incident (excès de colère).
Cordialement
Phil
-
-
Comment gérer le temps dans un programme ? 8 juin 2023 15:48, par bernard
bonjour,
moi mon problème est différent faire clignoter ok ça c’est bon mais je n’arrive pas à faire clignoter par exemple 3 fois une seconde toutes les 20 secondes, je bloque là dessus et ça me fatigue à force. je n’arrive même pas à mettre en brouillon un code car tous ceux que je tente ne fonctionnent pas. avez vous une idée de la manière d’aborder millis dans ce cas de figure ?bernard
-
Comment gérer le temps dans un programme ? 8 juin 2023 16:17, par Jean-Luc
Bonjour,
Il vous faut une variable d’état, par exemple un booléen qui indique si le programme fait clignoter 3 fois la LED. Appelons làbool clignote = true;
. Le fait qu’elle soit initialisée àtrue
fait que le programme démarrera en faisant clignoter la LED. Ensuite on a le code qui fait clignoter la LED qui est construit selon le principe décrit dans l’article mais qui ne s’exécute que si clignote esttrue
. En plus on compte combien de fois l’état de la LED est changé pour arrêter au bout de 6 (3 clignotements) en mettant clignote àfalse
.Ça donne ça :
if (clignote) { uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateClignote > 500) { derniereDateClignote = nouvelleDate; digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN)); compteClignote++; if (compteClignote == 6) { compteClignote = 0; clignote = false; } } }
Il suffit maintenant de rajouter le code qui passe clignote à
true
toutes les 20 secondes sans oublier de mettre la derniereDateClignote à la date courante :uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateDelai > 20000) { derniereDateDelai = nouvelleDate; derniereDateClignote = nouvelleDate; clignote = true; }
Le programme complet :
void setup() { pinMode(LED_BUILTIN, OUTPUT); } bool clignote = true; uint32_t derniereDateClignote = 0; uint32_t derniereDateDelai = 0; uint8_t compteClignote = 0; void loop() { if (clignote) { uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateClignote > 500) { derniereDateClignote = nouvelleDate; digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN)); compteClignote++; if (compteClignote == 6) { compteClignote = 0; clignote = false; } } } uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateDelai > 20000) { derniereDateDelai = nouvelleDate; derniereDateClignote = nouvelleDate; clignote = true; } }
-
Comment gérer le temps dans un programme ? 14 juin 2023 17:06, par bernard
Merci infiniment,
ça me fait avancer et apprendre aussi, je vais tenter maintenant sur cette base de faire clignoter plusieurs leds à des rythmes et délais différents, ça me donne bien une leçon votre explication que j’ai, je pense comprise merci, merci.
Bernard. -
Comment gérer le temps dans un programme ? 14 juin 2023 23:27, par bernard
Voila Votre code adapté pour 2 leds si j’ai bien compris ? mon code est il bon ? ou sera trop chargé sur 37 leds ou autre anomalie dans ma manière d’aborder et de construire mon montage qui fera clignoter les phares et les balises dans leur clignotement réels sur une carte marine( oui ce n’est pas du ferroviaire mais bon) le projet est de reproduire la rade de Brest avec ses balises et feux de nuit qui ont tous une couleur et un clignotements différents pour qu’un navigateur ne se perde pas la nuit et sache par rapport aux annotations de la carte officielles reconnaitre les fréquences de clignotement des repères lumineux
suis pas sur d’être clair
merci
bernard -
Comment gérer le temps dans un programme ? 14 juin 2023 23:29, par bernard
oups code oublié le voila
#define LED1 8 #define LED2 9 void setup() { pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); } bool clignote1 = true; bool clignote2 = true; uint32_t derniereDateclignote1 = 0; uint32_t derniereDateclignote2 = 0; uint32_t derniereDateDelai = 0; uint8_t compteclignote1 = 0; uint8_t compteclignote2 = 0; void loop() { if (clignote1) { uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateclignote1 > 500) { derniereDateclignote1 = nouvelleDate; digitalWrite(LED1, ! digitalRead(LED1)); compteclignote1++; if (compteclignote1 == 6) { compteclignote1 = 0; clignote1 = false; } } } uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateDelai > 20000) { derniereDateDelai = nouvelleDate; derniereDateclignote1 = nouvelleDate; clignote1 = true; } /*..............2EME LED......................*/ if (clignote2) { uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateclignote2 > 1000) { derniereDateclignote2 = nouvelleDate; digitalWrite(LED2, ! digitalRead(LED2)); compteclignote1++; if (compteclignote2 == 2) { compteclignote2 = 0; clignote2 = false; } } } /*uint32_t nouvelleDate = millis(); // ANCIEN CODE LOCO */ if (nouvelleDate - derniereDateDelai > 2000) { derniereDateDelai = nouvelleDate; derniereDateclignote2 = nouvelleDate; clignote2 = true; } }
-
Bonjour,
Pas de soucis à dupliquer du code. Est-ce que ça marchera pour 37 LED ? C’est sur un Mega ? Attention à la consommation totale (voir Que peut-on alimenter avec un Arduino) et il faudra sans doute mettre des amplis comme des ULN (voir Amplifier le signal de sortie d’un ARDUINO avec un ULN 2803). Est-ce que le CPU ne sera pas trop chargé ? Non, le temps d’exécution du code pour 1 LED ne doit pas dépasser quelques dizaines de µs. Avec des process qui sont dans le domaine de la seconde, on peut en piloter des centaines.
Mais si vous répliquez exactement le même schéma pour plusieurs LED, ça va être fastidieux et ça vaut le coup de faire une fonction, voire même des objets. Ça sera plus simple à comprendre et à lire, plus court et ça prendra moins de mémoire.
-
-
Comment gérer le temps dans un programme ? 15 juin 2023 09:38, par bernard
bon j’ai remodifié le code et super grand merci ça marche pour 2 donc je peux continuer comme ça pour toutes les leds. mille merci ça fonctionne..
et en plus j’ai appris un truc , pas belle la vie ?voici mon code pour 2
#define LED1 7 #define LED2 8 void setup() { pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); } bool clignote1 = true; bool clignote2 = true; uint32_t derniereDateclignote1 = 0; uint32_t derniereDateclignote2 = 0; uint32_t derniereDateDelai = 0; uint32_t derniereDateDelai2 = 0; uint8_t compteclignote1 = 0; uint8_t compteclignote2 = 0; void loop() { if (clignote1) { uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateclignote1 > 1000) { derniereDateclignote1 = nouvelleDate; digitalWrite(LED1, ! digitalRead(LED1)); compteclignote1++; if (compteclignote1 == 6) { compteclignote1 = 0; clignote1 = false; } } } uint32_t nouvelleDate = millis(); if (nouvelleDate - derniereDateDelai > 10000) { derniereDateDelai = nouvelleDate; derniereDateclignote1 = nouvelleDate; clignote1 = true; } /*..............2EME LED......................*/ if (clignote2) { uint32_t nouvelleDate2 = millis(); if (nouvelleDate2 - derniereDateclignote2 > 100) { derniereDateclignote2 = nouvelleDate2; digitalWrite(LED2, ! digitalRead(LED2)); compteclignote2++; if (compteclignote2 == 12) { compteclignote2 = 0; clignote2 = false; } } } uint32_t nouvelleDate2 = millis(); if (nouvelleDate2 - derniereDateDelai2 > 5000) { derniereDateDelai2 = nouvelleDate2; derniereDateclignote2 = nouvelleDate2; clignote2 = true; } }
-
Comme je le disais, si vous avez plus de 2 LED, répliquer le code n’est pas la voie à suivre. Le mieux est d’encapsuler le code dans une classe et d’instancier des objets. Je peux vous expliquer ça.
C’est comme si vous me disiez « J’ai creusé 2m de tranchée avec une pelle, ça marche, je peux continuer sur 37m ? ». Ben non. Faut aller chercher une pelleteuse et mieux, ici elle sera robotisée, on lui explique sur 1m et elle fait sur 37m ou plus toute seule.
-
Comme je le disais, si vous avez plus de 2 LED, répliquer le code n’est pas la voie à suivre. Le mieux est d’encapsuler le code dans une classe et d’instancier des objets. Je peux vous expliquer ça.
bonjour,
oui je veux bien qu’on m’explique l’encapsulage. , oula la laaa je vais en apprendre des choses moi avec vous.. vous êtes une vraie encyclopédie pour moi. je ne suis qu’un électricien de base qui apprend la domotique à la retraite en passe temps. je sais programmer simplement mais je ne cherche pas plus loin pour améliorer quand ça fonctionne. deja je comprends quand on me coache c’est pas si mal.. et comme on dit il faut apprendre toute sa vie.
sinon oui je vais le faire avec un Arduino méga.bernard
-
Bonjour,
Pour encapsuler tout ça on va faire une classe. Tout d’abord les données. Le fonctionnement d’une LED nécessite :- La broche de la LED ;
- Un intervalle de temps ;
- Une période de clignotement ;
- Un nombre de clignotement.
Dans le programme actuel, ces 4 paramètres apparaissent en tant que constantes dans le code. On a aussi besoin des deux variables qui stockent les deux dates, celle qui compte les clignotements et un booléen pour savoir si on est en train de clignoter ou non. Ça nous donne ceci :
class Clignotant { /* Intervalle d'émission des clignotements */ uint32_t mIntervalle; /* Date de démarrage de l'intervalle en cours */ uint32_t mDateIntervalle; /* Date de du dernier clignotement */ uint32_t mDatePeriode; /* Période des clignotements */ uint16_t mPeriode; /* Nombre de clignotements */ uint8_t mNombre; /* Comptage du nombre de clignotements */ uint8_t mCompteClignote; /* true si un clignotement est en cours */ bool mClignote; /* broche de la LED */ uint8_t mLEDPin;
Par habitude je préfixe les données qui sont à l’intérieure d’une classe par un ’m’ pour membre.
Ensuite, on a besoin d’une fonction membre de la classe qu’on appelle le constructeur. Cette fonction porte le même nom que la classe et a pour but d’initialiser les données membres. Elle est appelée lorsqu’on crée un objet. Ici notre constructeur prend 4 argument qui sont les paramètres listés plus haut et qui sont copiés dans les données membres correspondantes. Les autres données membres sont initialisés à 0 pour les dates, à
true
pour le clignotement.public: Clignotant(uint8_t inLEDPin, uint32_t inIntervalle, uint16_t inPeriode, uint8_t inNombre): mLEDPin(inLEDPin), mIntervalle(inIntervalle), mDateIntervalle(0), mPeriode(inPeriode / 2), mDatePeriode(0), mNombre(inNombre * 2), mCompteClignote(0), mClignote(true) {
À noter qu’on en profite pour rendre les paramètres de l’objet plus compréhensibles : le nombre de clignotement est multiplié par 2 car pour, par exemple, 3 clignotements, on a 6 changements d’état de la LED. Symétriquement le période est divisée par deux.
Ensuite on a une fonction membre
objectLoop
qui contient le code que nous avons déjà vu en substituant aux constantes les données membres correspondantes :void objectLoop() { const uint32_t nouvelleDate = millis(); if (nouvelleDate - mDateIntervalle > mIntervalle) { mDateIntervalle = nouvelleDate; mDatePeriode = nouvelleDate; mClignote = true; } if (mClignote) { const uint32_t nouvelleDate = millis(); if (nouvelleDate - mDatePeriode > mPeriode) { mDatePeriode = nouvelleDate; digitalWrite(mLEDPin, ! digitalRead(mLEDPin)); mCompteClignote++; if (mCompteClignote == mNombre) { mCompteClignote = 0; mClignote = false; } } } }
On a aussi besoin d’une fonction membre qui va juste programmer la broche de la LED en sortie :
void setupObject() { pinMode(mLEDPin, OUTPUT); }
Il suffit ensuite de déclarer nos objet :
Clignotant led1(LED_BUILTIN, 20000, 1000, 6); Clignotant led2(4, 8000, 500, 3); Clignotant led3(5, 9000, 700, 4);
Pour les faire fonctionner, il faudrait appeler dans
setup
tous lessetupObject
:led1.setupObject(); led2.setupObject(); led3.setupObject();
idem dans loop avec
loopObject
C’est pas terrible, on réplique un tas de ligne de code et si on ajoute une LED, il faut l’ajouter aussi dans setup et loop. Or il est possible de construire une liste d’objets lorsqu’on les crées. On a besoin d’un pointeur permettant de chainer les objets et d’une variable, pointeur également, pour stocker la tête de liste. Le premier pointeur est un membre de la classe, il y en a autant qu’il y a d’objets, le second est en exemplaire unique. On va en faire une variable de classe, partagée par touts les objets. Pour cela on ajoutestatic
devant sa déclaration :/* Chainage de tous les objets lors de leur création */ Clignotant *mNext; static Clignotant *sListe;
Une donnée de classe doit être initialisée à part. Le pointeur est initialisé à NULL pour signifier qu’il pointe sur rien :
Clignotant *Clignotant::sListe = NULL;
Dans le constructeur, on construit la liste d’objets en ajoutant l’objet que l’on construit en tête de liste :
mNext = sListe; sListe = this;
On peut ensuite écrire deux fonctions de classe qui parcourent la liste pour appeler
setupObject
etsetupLoop
:static void setup() { Clignotant *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectSetup(); objetCourant = objetCourant->mNext; } } static void loop() { Clignotant *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectLoop(); objetCourant = objetCourant->mNext; } }
Ces deux fonctions sont appelées comme ceci dans
setup
etloop
:void setup() { Clignotant::setup(); } void loop() { Clignotant::loop(); }
Et c’est beaucoup plus sympa car maintenant si on veut ajouter une LED, il suffit de la déclarer, elle sera automatiquement prise en charge. Le code complet :
class Clignotant { /* Intervalle d'émission des clignotements */ uint32_t mIntervalle; /* Date de démarrage de l'intervalle en cours */ uint32_t mDateIntervalle; /* Date de du dernier clignotement */ uint32_t mDatePeriode; /* Période des clignotements */ uint16_t mPeriode; /* Nombre de clignotements */ uint8_t mNombre; /* Comptage du nombre de clignotements */ uint8_t mCompteClignote; /* true si un clignotement est en cours */ bool mClignote; /* Pin de la LED */ uint8_t mLEDPin; /* Chainage de tous les objets lors de leur création */ Clignotant *mNext; static Clignotant *sListe; public: Clignotant(uint8_t inLEDPin, uint32_t inIntervalle, uint16_t inPeriode, uint8_t inNombre): mLEDPin(inLEDPin), mIntervalle(inIntervalle), mDateIntervalle(0), mPeriode(inPeriode / 2), mDatePeriode(0), mNombre(inNombre * 2), mCompteClignote(0), mClignote(true) { mNext = sListe; sListe = this; } void objectLoop() { const uint32_t nouvelleDate = millis(); if (nouvelleDate - mDateIntervalle > mIntervalle) { mDateIntervalle = nouvelleDate; mDatePeriode = nouvelleDate; mClignote = true; } if (mClignote) { const uint32_t nouvelleDate = millis(); if (nouvelleDate - mDatePeriode > mPeriode) { mDatePeriode = nouvelleDate; digitalWrite(mLEDPin, ! digitalRead(mLEDPin)); mCompteClignote++; if (mCompteClignote == mNombre) { mCompteClignote = 0; mClignote = false; } } } } void objectSetup() { pinMode(mLEDPin, OUTPUT); } static void setup() { Clignotant *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectSetup(); objetCourant = objetCourant->mNext; } } static void loop() { Clignotant *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectLoop(); objetCourant = objetCourant->mNext; } } }; Clignotant *Clignotant::sListe = NULL; Clignotant led1(LED_BUILTIN, 20000, 1000, 6); Clignotant led2(4, 8000, 500, 3); Clignotant led3(5, 9000, 700, 4); void setup() { Clignotant::setup(); } void loop() { Clignotant::loop(); }
-
-
-
-
Comment gérer le temps dans un programme ? 15 juin 2023 12:27, par bernard
c’est encore moi, comme je suis chiant et que j’aime bien compliquer les choses, que je me creuse beaucoup la tête en tant que débutant avec millis.
je tente de faire allumer une led avec millis toujours mais cette fois ci avec allumage progressif sur une seconde, rester allumée une seconde puis éteindre progressif une seconde et cela toutes les 10 secondes par exemple.bernard
-
J’ai fait une bibliothèque pour ce genre de chose : https://github.com/Locoduino/LightDimmer
Elle des disponible dans le gestionnaire de bibliothèques de l’IDE
-
-
Comment gérer le temps dans un programme ? 19 juin 2023 23:02, par bernard
Merci beaucoup pour ce cours monsieur jean luc.
J’ai compris et je vais pouvoir commencer à faire autre chose avec les classes, mais pour le moment je me concentre sur mon projet de feux en mer et de la pointe bretonne.Il va falloir que je m’arrache encore un peu de cheveux car certains des clignotements des balises et feux sont très particuliers dans les périodes et je tiens à rester fidèle à la réalité. Pour exemple voici un lien qui vous donnera une vision plus précise des périodes non régulières. Voir à la page 8 du document, c’est très parlant.
merci encore car j’apprend plein de chose et c’est super intéressant de travailler sur ce projet qui me force à sortir de ma zone de confort.
Bernard.Voir en ligne : feux et balises en mer périodes
-
Comment gérer le temps dans un programme ? 22 juin 2023 08:59, par Jean-Luc
Bonjour Bernard,
J’ai parcouru le document. Concernant les feux à occultation et les feux à éclats, le fonctionnement se réduit à une série de durées avec un changement d’état du feu à chaque frontière. Ça peut être représenté par un tableau de durées et un état initial du feu (allumé ou éteint). D’où la définition de la classeFeuMaritime
:class FeuMaritime { /* Dates relatives de changement d'état du feu */ const uint32_t *mDatesChangement; /* Dernière date de changement */ uint32_t mDerniereDate; /* Nombre de dates */ uint8_t mNombreDeDates; /* Changement courant */ uint8_t mChangementCourant; /* Etat initial */ uint8_t mEtatInitial; /* Pin de la LED */ uint8_t mLEDPin; /* Chainage de tous les objets lors de leur création */ FeuMaritime *mNext; static FeuMaritime *sListe; public: FeuMaritime(const uint8_t inLEDPin, const uint32_t *inDatesChangement, const uint8_t inNombreDeDates, const uint8_t inEtatInitial): mLEDPin(inLEDPin), mDatesChangement(inDatesChangement), mDerniereDate(0), mNombreDeDates(inNombreDeDates), mEtatInitial(inEtatInitial) { mNext = sListe; sListe = this; } void objectLoop() { const uint32_t nouvelleDate = millis(); if (nouvelleDate - mDerniereDate > mDatesChangement[mChangementCourant]) { digitalWrite(mLEDPin, ! digitalRead(mLEDPin)); mDerniereDate = nouvelleDate; mChangementCourant++; if (mChangementCourant == mNombreDeDates) { mChangementCourant = 0; } } } void objectSetup() { pinMode(mLEDPin, OUTPUT); digitalWrite(mLEDPin, mEtatInitial); } static void setup() { FeuMaritime *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectSetup(); objetCourant = objetCourant->mNext; } } static void loop() { FeuMaritime *objetCourant = sListe; while (objetCourant != NULL) { objetCourant->objectLoop(); objetCourant = objetCourant->mNext; } } }; FeuMaritime *FeuMaritime::sListe = NULL;
Les arguments du constructeur sont la broche où la LED est connectée, un pointeur vers un tableau de constantes qui sont les intervalles de temps, le nombre d’éléments dans ce tableau et l’état initial (HIGH ou LOW).
Pour utiliser cette classe, il faut d’abord instancier un tableau de constantes puis instancier un objet en lui passant ce tableau. Voici par exemple les feux mentionnés aux sections 2.1, 2.2 et 2.3.const uint32_t specAISM1[] = { 1000, 3000 }; FeuMaritime feuAOccultationsRegulieres(0, specAISM1, 2, LOW); const uint32_t specAISM2[] = { 1000, 2000, 1000, 6000 }; FeuMaritime feuAOccultationsGroupees(1, specAISM2, 4, LOW); const uint32_t specAISM3[] = { 1000, 1000, 1000, 3000, 1000, 9000 }; FeuMaritime feuAOccultationsDiversementGroupees(2, specAISM3, 6, LOW);
setup
etloop
sont simplement :void setup() { FeuMaritime::setup(); } void loop() { FeuMaritime::loop(); }
-
Comment gérer le temps dans un programme ? 22 juin 2023 23:33
bonjour, Jean Luc,
la vache vous êtes super balaise. J’avance vite avec vos conseils et en plus je découvre plein de choses, moi je suis incapable d’avoir cette logique. je comprends mais il me faut du temps pour bien assimiler. j’ai du temps à la retraite aussi, donc j’avance à mon rythme dans l’apprentissage. ayant fait une carrière aux 3 ports de Nantes métropole (NGE) me voila retourné à Brest ma ville natale ou j’ai décidé de me lancer dans le maquettisme maritime, hé bien ce n’est pas de la tarte finalement. bon pour ce qui est décors ça va mais l’Arduino me rendra fou et grâce à vous je vais peut être devenir bon un jour et aussi pouvoir donner des petits conseils aux débutants. (peut être)
merci mille fois
Bernard -
Comment gérer le temps dans un programme ? 6 août 2023 18:38
bonjour, jean Luc et les autres , je suis content de votre retour sur la toile. j’avais appris que vous aviez été piraté. quelle histoire. bon voila juste pour souhaiter un bon retour. pendant ce temps j’avance sur mes feux maritimes. doucement mais surement.
bernard