Pour pallier aux problèmes générés par l’utilisation de la fonction delay(), une solution possible est d’utiliser la fonction millis(). Dès la première utilisation de l’Arduino, la fonction delay() est utilisée afin de gérer les instructions en fonction du temps. Le problème majeur de la fonction delay() est qu’elle bloque l’exécution de la suite du code. Ceci devient très limitant lorsqu’on travaille avec plusieurs composants (gestions de plusieurs LEDs ou capteurs). Nous allons voir dans ce tutoriel comment utiliser la fonction millis() pour remplacer la fonction delay().
Description de la fonction millis()
La fonction millis() ne prend aucun paramètre et renvoie une valeur qui représente le nombre de millisecondes écoulées depuis la mise en tension de l’Arduino. La valeur est de type long non-signé (unsigned long, 4-bytes ou 32-bits). La valeur maximale qu’elle peut prendre est de 4,294,967,295 soit 49 jours.
N.B.: Il existe aussi la fonction micros() qui fonctionne sur le même principe mais renvoie des microsecondes.
void setup() {} void loop() { Serial.print("Milliseconds since ignition: "); Serial.println(millis()) delay(200); }
Remplacer delay()
Dans les premiers exemples d’Arduino, on utilise la fonction delay() pour exécuter un bloc de code périodiquement mais ce n’est pas sa fonction propre puisqu’elle bloque l’exécution du code. La fonction millis() est bien plus adaptée pour cette fonction.
Reprenons l’exemple Blink. Nous utilisons la fonction delay pour faire clignoter une LED toutes les 200 millisecondes.
void setup() { pinMode(13,OUTPUT); } void loop() { digitalWrite(13,HIGH); delay(200); digitalWrite(13,LOW); delay(200); }
Pour remplacer ce code par un structure avec millis(), l’idée est de créer une variable afin de conserver en mémoire à chaque itération la valeur de temps écoulé puis de la comparer à la valeur de temps actuelle. A chaque intervalle, nous inversons l’état de la led avec l’opérateur « ! ».
unsigned long currentTime=0; unsigned long previousTime=0; bool ledState=LOW; void setup() { Serial.begin(9600); pinMode(13,OUTPUT); } void loop() { currentTime=millis(); if((currentTime-previousTime)>200){ previousTime=currentTime; ledState=!ledState; digitalWrite(13,ledState); Serial.print(F("LED State : "));Serial.println(ledState); } }
Nous recréons l’exemple blink avec, en plus, la possibilité d’exécuter du code même si l’intervalle de temps n’est pas écoulé. Dans ce code, la led vas s’allumer et s’éteindre toutes les 200ms.
Définir différents intervalles de temps
Dans le cas où vous voudriez avoir des cycles ON et OFF de la LED avec des temps différents, il est possible de modifier l’intervalle de temps en fonction de l’état de la LED.
unsigned long currentTime=0; unsigned long previousTime=0; unsigned long interval,interval1=200, interval2=1000; bool ledState=LOW; void setup() { Serial.begin(9600); pinMode(13,OUTPUT); } void loop() { currentTime=millis(); if(ledState){ interval=interval2; }else{ interval=interval1; } if((currentTime-previousTime)>interval){ previousTime=currentTime; ledState=!ledState; digitalWrite(13, ledState); Serial.print(F("LED State : "));Serial.println(ledState); } }
Ce code permet de ‘allumer la LED pendant 200ms toutes les secondes.
Aller plus loin
Il est important de noter que la fonction millis() utilise des timers internes du microcontrôleur et peut être perturbée par l’utilisation d’interruption ou d’autres librairies.
Pour aller vers une programmation d’un niveau plus avancé, il est possible d’utiliser les librairies de gestion de timer (Timer.h,Timer2.h, TimerOne.h, etc.)
Il est aussi possible de venir jouer avec les registres du microcontrôleur pour configurer les timers internes
Sources
- Référence Arduino sur la fonction millis()
- Le fameux exemple Blink without delay
- Programmer avec Arduino
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie
bonjour,je veux allumer deux leds en utilisant la fonction millis() mais je veux que la première LED s’allume en premier et qu’après un certain moment que la deuxième LED s’allume sans éteindre la première
Bonjour,
Il vous faut définir quatre variables currentTime1, currentTime2, previousTime1 et previousTime2 en initialisant previousTime2 à 500, par exemple, pour 500ms de décalage.
j’ai aussi un soucis. J’aimerai calculé l’énergie consommée par un appareil(lampe de 100w), chaque 1 seconde…j’ai utilisé cette formule E = P*t avec t = millis() et enregistrer cette consommation chaque 1 seconde sur une carte SD,mon soucis c’est que l’enregistrement se fait chaque 2 et seconde,de même la consommation
bonjour j’ai un probleme avec mon code, j’aimerais que mon moteur s’active qu’une fois tous les 5 heures 4 fois et ensuite qu’il s’arrete pendant 10 heures et ainsi de suite mais je n’arrive pas l’arreter pendant 10 heures. voici mon code :
int pos = 0; // variable to store the servo position
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
void setup() {
Serial.begin(9600);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
if (currentMillis-previousMillis >= 72000000);
currentMillis = millis();
previousMillis = currentMillis;
delay (36000000);
for (pos = 0; pos = 0; pos -= 1) { // goes from 100 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 5ms for the servo to reach the position
}
delay (18000000);
}
fin
donc il s’arrete bien pendant 5 heure mais au tous le temps et j’aimera que tuous les 4 fois qu’il s’arrete 5 heures ils’arrete 10 heures.
merci
Bonjour, il y a un soucis dans votre code, dans le code suivant currentMillis et previousMillis sont toujours égaux.
if (currentMillis-previousMillis >= 72000000);
currentMillis = millis();
previousMillis = currentMillis;
}
essayez
currentMillis = millis();
if (currentMillis-previousMillis >= 72000000);
previousMillis = currentMillis;
}
Je vous conseille d’essayer avec des valeurs plus petites pour les temps et d’afficher les valeurs de currentMillis et previousMillis pour vérifier que tout fonctionne.
Aussi, si vous souhaitez une bonne précision de temps je vous conseille d’ajouter un module RTC comme le module DS3231
Bonjour. j’ai utilisé un module RTCDS1307,les seconde passent de 1,2,4,6,8sec…..ETC. Je comprend pas
bonsoir , j’aimerai utiliser la fonction millis pour tourner mon moteur pas a pas. mon moteur dois tourner chaque 2h ,le nbre de pas a faire est de 50 dans un sens puis 50 dans l’autre. mais mon code ne fonctionne pas ,pouvez vous m’aidez svp.merci
#include
const int NbrPas =100;
Stepper monmoteur(NbrPas, 8, 9, 10, 11);
unsigned long Newval=0;
unsigned long ancienneval=0;
//unsigned long millisBetweenSteps = 25; // milliseconds
void setup() {
Serial.begin(9600);
ancienneval=millis();//initialisation
monmoteur.setSpeed(10); // Vitesse à 10 tours/min
}
void loop() {
Moteur();
Newval=millis();
if((Newval-ancienneval)<=1000)
ancienneval=Newval;
}
void Moteur() {
monmoteur.step(50);
delay(500);
monmoteur.step(-50);
delay(500);
}
Bonjour,
il faut mettre la fonction moteur dans la condition if((Newval-ancienneval)<=1000)
Bonjour,
Pour un projet de serrure avec badge RFID, je voudrai afficher sur un écran LCD de deux lignes un message alterné pendant deux secondes.
Le premier « Identification … » et sur le suivant « Passez votre carte … » et revenir au premier « Identification … » et ainsi de suite.
Mon code affiche seulement le premier
D’avance merci pour votre aide
void loop()
{
unsigned long previousTime=0;
if(tempo-previousTime<2000)
{
previousTime=millis();
lcd.setCursor(1, 0);
lcd.print("Identification");
lcd.setCursor(3, 1);
lcd.print("en service");
}
else
{
lcd.setCursor(1, 0);
lcd.print("Scannez votre");
lcd.setCursor(0, 1);
lcd.print("carte / badge…");
tempo = millis();
lcd.clear();
}
Bonjour,
je pense que l’exemple BlinkWithoutDelay correspond exactement à ce que tu souhaites faire.
Il faut juste rajouter une variable d’état lcdState, par exemple, qui passe de LOW à HIGH en fonction du texte à afficher
Super et merci
Bonjour,
Ma question concerne le code « Ce code permet de ‘allumer la LED pendant 200ms toutes les secondes »
Je l’ai transformé pour obtenir 2 et 4 secondes pour réaliser un chargeur de piles Alcalines avec 2 secondes de charge et 4 secondes de repos.
Durant la période de 2 secondes je veux réguler le courant via void RegulCourant()
Durant la période de 4 secondes je veux traiter les données acquises précédemment.
Je ne trouve pas de solutions pour intégrer des fonctions différentes dans chaque temporisations au lieu d’un simple changement d’état..
Pouvez vous m’aider SVP ?
Merci
Vous pouvez créer un switch..case et placer une tempo dans chaque état défini et passer d’un état à l’autre
switch state
case charge
tempo interval1
if tempo done: state=rest
case rest
tempo interval2
if tempo done: state=charge
Bonjour,
Merci de votre réponse mais débutant, je n’arrive pas à comprendre alors voilà mon code:
unsigned long ActuelMilli = 0;
unsigned long PrecedentMilli = 0;
unsigned long Periode;
unsigned long Periode2Sec = 200;
unsigned long Periode4Sec = 1000;
bool EtatLed = LOW;
unsigned int cptr = 0;
void setup()
{
Serial.begin(19200);
pinMode(13, OUTPUT);
Serial.print(F(« Setup »)); Serial.println(« »);
} // Fin Setup
void loop()
{
ActuelMilli = millis();
if (EtatLed)
{
Periode = Periode4Sec;
}
else
{
Periode = Periode2Sec;
}
if ((ActuelMilli – PrecedentMilli) > Periode)
{
cptr++;
Serial.print(F(« Compteur = « )); Serial.print(cptr);
Serial.print(F( » Periode = « )); Serial.print(Periode);
Serial.print(F( » ActuelMilli = « )); Serial.print(ActuelMilli);
PrecedentMilli = ActuelMilli;
Serial.print(F( » PrecedentMilli = « )); Serial.print(PrecedentMilli);
EtatLed = !EtatLed;
digitalWrite(13, !EtatLed);
Serial.print(F( » Etat LED : « )); Serial.print(EtatLed);
Serial.print(F( » Avec Etat LED Lu = « )), Serial.println(digitalRead(13));
if (cptr >= 9) // led eteinte à la fin du pg et si >=10 led allumee
{
Serial.print(F( » Fin Pg avec Cptr = « )), Serial.print(cptr);
Serial.print(F( » Avec Etat LED Lu = « )), Serial.println(digitalRead(13));
while (1);
}
}
} // Fin Loop
et le résultat:
17:58:54.308 -> Setup
17:58:54.508 -> Compteur = 1 Periode = 200 ActuelMilli = 201 PrecedentMilli = 201 Etat LED : 1 Avec Etat LED Lu = 0
17:58:55.510 -> Compteur = 2 Periode = 1000 ActuelMilli = 1202 PrecedentMilli = 1202 Etat LED : 0 Avec Etat LED Lu = 1
17:58:55.710 -> Compteur = 3 Periode = 200 ActuelMilli = 1403 PrecedentMilli = 1403 Etat LED : 1 Avec Etat LED Lu = 0
17:58:56.711 -> Compteur = 4 Periode = 1000 ActuelMilli = 2404 PrecedentMilli = 2404 Etat LED : 0 Avec Etat LED Lu = 1
17:58:56.911 -> Compteur = 5 Periode = 200 ActuelMilli = 2605 PrecedentMilli = 2605 Etat LED : 1 Avec Etat LED Lu = 0
17:58:57.913 -> Compteur = 6 Periode = 1000 ActuelMilli = 3606 PrecedentMilli = 3606 Etat LED : 0 Avec Etat LED Lu = 1
17:58:58.113 -> Compteur = 7 Periode = 200 ActuelMilli = 3807 PrecedentMilli = 3807 Etat LED : 1 Avec Etat LED Lu = 0
17:58:59.115 -> Compteur = 8 Periode = 1000 ActuelMilli = 4808 PrecedentMilli = 4808 Etat LED : 0 Avec Etat LED Lu = 1
17:58:59.315 -> Compteur = 9 Periode = 200 ActuelMilli = 5009 PrecedentMilli = 5009 Etat LED : 1 Avec Etat LED Lu = 0
17:58:59.369 -> Fin Pg avec Cptr = 9 Avec Etat LED Lu = 0
Pourquoi votre ledState est l’opposé de digitalRead(13) ?
Pouvez vous me monter comment modifier votre exemple 2 intervals avec un switch case afin que je puisse inclure dans interval 1 ma régulation PWM depuis le résultat de lecture fourni par un INA219 et dans interval 2 stopper le PWM et traiter afficher la quantité de courant injecté dans la pile ?
Merci.
Cordialement.
Bonjour,
L’appareil que j’ai utilisé pour le tutoriel était allumé a False et éteint a True.
Si vous n’avez que deux états, vous pouvez rester avec if else.
Pour l’utilisation de Switch case je vous renvoie a ce tuto
Bonjour.
Je voudrais faire clignoter ma LED un certain nombre de fois ,avec une boucle FOR et DELAY c’est facile mais avec MILLIS ou cela ne s’arrête pas ou cela ne fonctionne pas pouvez vous m’aider
Il faut rajouter une condition sur le nombre de cycle
int nbcycle = 10;
void loop() {
if (nbcycle>0) {
nbcycle–;
currentTime=millis();
if((currentTime-previousTime)>200){
previousTime=currentTime;
ledState=!ledState;
digitalWrite(13,ledState);
Serial.print(F(« LED State : « ));Serial.println(ledState);
}
}else{
digitalWrite(13,LOW);
}
}
Bonjour et merci pour cette réponse rapide mais il me reste une erreur sur « nbcycle-; »
C:\Users\windows10\AppData\Local\Temp\.arduinoIDE-unsaved2024427-4884-oh5pr2.iumue\sketch_may27a\sketch_may27a.ino:15:8: error: stray ‘\342’ in program
nbcycle–;
^
C:\Users\windows10\AppData\Local\Temp\.arduinoIDE-unsaved2024427-4884-oh5pr2.iumue\sketch_may27a\sketch_may27a.ino:15:9: error: stray ‘\200’ in program
nbcycle–;
^
C:\Users\windows10\AppData\Local\Temp\.arduinoIDE-unsaved2024427-4884-oh5pr2.iumue\sketch_may27a\sketch_may27a.ino:15:10: error: stray ‘\223’ in program
nbcycle–;
^
exit status 1
Compilation error: stray ‘\342’ in program
aurriez vous une idée merci
Bonjour,
stray ‘\342’ est une erreur de copier-coller à partir de la page internet.
Je vous invite à réécrire les lignes
Bonjour
J’ai vu que plusieurs personnes ont la même erreur que moi peut-être être trouverez-vous la solution, mais pour moi ne cherchez plus, j’ai trouvé une autre solution à mon problème avec ‘’delayMicrosecond ‘’ bonne journée et encore merci.