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