arduino
Gestion du temps
Recherche…
Syntaxe
non signé long millis ()
non signé long micros ()
délai d'annulation (millisecondes longues non signées)
délai videMicrosecondes (microsecondes longues non signées)
Voir l'en-tête elapsedMillis pour les constructeurs et les opérateurs de cette classe. En bref:
- elapsedMillis elapsedMillisObject; crée un objet pour suivre le temps écoulé depuis sa création ou depuis un autre point défini explicitement dans le temps
- elapsedMillisObject = 0; réinitialiser le temps suivi par l'objet à "depuis maintenant"
- unsigned long deltaT = elapsedMillisObject; nous permet de regarder le temps suivi
- elapsedMillisObject + = et - = ceux-ci fonctionnent comme prévu
Remarques
Code bloquant ou non bloquant
Pour des esquisses très simples, écrire du code de blocage à l'aide de delay()
et delayMicroseconds()
peut être approprié. Lorsque les choses deviennent plus complexes, l'utilisation de ces fonctions peut présenter certains inconvénients. Certains d'entre eux sont:
- Perte de temps CPU: des croquis plus complexes peuvent nécessiter le CPU pour autre chose en attendant la fin de la période de clignotement des voyants.
- Retards inattendus: lorsque
delay()
est appelé dans des sous-routines qui ne sont pas appelées de manière évidente, par exemple dans les bibliothèques que vous incluez. - les événements manquants qui se produisent pendant le délai et qui ne sont pas traités par un gestionnaire d'interruption, par exemple une pression sur le bouton d'interrogation: un bouton peut être pressé pendant 100 ms, mais cela peut être
delay(500)
.
Détails d'implémentation
millis()
repose généralement sur une minuterie matérielle dont la vitesse est bien supérieure à 1 kHz. Lorsque millis()
est appelée, l'implémentation retourne une valeur, mais vous ne savez pas quel âge elle a. Il est possible que la milliseconde "courante" vienne juste de démarrer ou qu'elle se termine juste après cet appel de fonction. Cela signifie que, lors du calcul de la différence entre deux résultats à partir de millis()
, vous pouvez être désactivé par presque zéro et presque une milliseconde. Utilisez micros()
si une plus grande précision est nécessaire.
En elapsedMillis
code source de elapsedMillis
que millis()
interne pour comparer deux points dans le temps, ce qui nuit également à cet effet. Encore une fois, il existe une alternative elapsedMicros
pour une plus grande précision, à partir de la même bibliothèque.
blinky blinky avec delay ()
Une des manières les plus simples de faire clignoter une LED est: allumez-la, attendez un peu, éteignez-la, attendez encore et répétez sans cesse:
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500
void setup()
{
pinMode(OUTPIN, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(OUTPIN, HIGH); // sets the pin on
delayMicroseconds(PERIOD); // pauses for 500 miliseconds
digitalWrite(OUTPIN, LOW); // sets the pin off
delayMicroseconds(PERIOD); // pauses for 500 milliseconds
// doing other time-consuming stuff here will skew the blinking
}
Cependant, attendre comme dans l'exemple ci-dessus gaspille les cycles du processeur, car il ne fait que rester en boucle pendant un certain temps. C'est ce que les méthodes non bloquantes, à l'aide de millis()
ou elapsedMillis
, font mieux - dans le sens où elles ne brûlent pas autant de fonctionnalités du matériel.
Blinky non bloquant avec la bibliothèque elapsedMillis (et la classe)
La bibliothèque elapsedMillis fournit une classe avec le même nom qui garde la trace du temps écoulé depuis sa création ou sa valeur:
#include <elapsedMillis.h>
#define OUTPIN LED_BUILTIN
#define PERIOD 500
elapsedMillis ledTime;
bool ledState = false;
void setup()
{
// initialize the digital pin as an output.
pinMode(OUTPIN, OUTPUT);
}
void loop()
{
if (ledTime >= PERIOD)
{
ledState = !ledState;
digitalWrite(OUTPIN, ledState);
ledTime = 0;
}
// do other stuff here
}
Vous pouvez voir dans l'exemple que l'objet ledTime
est assigné à zéro lorsque la broche du voyant a été basculée. Cela n’est peut-être pas surprenant à première vue, mais cela se produit si des choses plus chronophages se produisent:
Considérons une situation où la comparaison entre ledTime
et PERIOD
se fait après 750 millisecondes. Le réglage de ledTime
à zéro signifie que toutes les opérations de bascule suivantes seront 250 ms en retard. Si, au contraire, PERIOD
a été soustrait de ledTime
, la LED verrait une courte période, puis continuer à clignoter comme si rien ne se passait.
Blinky non bloquant avec le millis ()
Ceci est très proche d’ un exemple de la documentation arduino :
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500 // this is in milliseconds
int ledState = LOW;
// millis() returns an unsigned long so we'll use that to keep track of time
unsigned long lastTime = 0;
void setup() {
// set the digital pin as output:
pinMode(OUTPIN, OUTPUT);
}
void loop() {
unsigned long now = millis();
if (now - lastTime >= PERIOD) // this will be true every PERIOD milliseconds
{
lastTime = now;
if (ledState == LOW)
{
ledState = HIGH;
}
else
{
ledState = LOW;
}
digitalWrite(OUTPIN, ledState);
}
// now there's lots of time to do other stuff here
}
Utiliser millis()
de cette façon - pour chronométrer les opérations de manière non bloquante - est quelque chose qui est nécessaire assez fréquemment, alors envisagez d'utiliser la bibliothèque elapsedMillis
pour cela.
Mesurer combien de temps quelque chose a pris, en utilisant Millis et ElapsedMicros
#include <elapsedMillis.h>
void setup() {
Serial.begin(115200);
elapsedMillis msTimer;
elapsedMicros usTimer;
long int dt = 500;
delay(dt);
long int us = usTimer;
long int ms = msTimer;
Serial.print("delay(");Serial.print(dt);Serial.println(") took");
Serial.print(us);Serial.println(" us, or");
Serial.print(ms);Serial.println(" ms");
}
void loop() {
}
Dans cet exemple, un objet elapsedMillis
et un objet elapsedMicros
sont utilisés pour mesurer combien de temps quelque chose a pris, en les créant juste avant que l'expression que nous voulons chronométrer soit exécutée, et en obtenant ensuite leurs valeurs. Ils afficheront des résultats légèrement différents, mais le résultat en millisecondes ne sera pas désactivé par plus d'une milliseconde.
Plus d'une tâche sans délai ()
Si vous avez plus d'une tâche à exécuter à plusieurs reprises dans des intervalles différents, utilisez cet exemple comme point de départ:
unsigned long intervals[] = {250,2000}; //this defines the interval for each task in milliseconds
unsigned long last[] = {0,0}; //this records the last executed time for each task
void setup() {
pinMode(LED_BUILTIN, OUTPUT); //set the built-it led pin as output
Serial.begin(115200); //initialize serial
}
void loop() {
unsigned long now = millis();
if(now-last[0]>=intervals[0]){ last[0]=now; firstTask(); }
if(now-last[1]>=intervals[1]){ last[1]=now; secondTask(); }
//do other things here
}
void firstTask(){
//let's toggle the built-in led
digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN)?0:1);
}
void secondTask(){
//say hello
Serial.println("hello from secondTask()");
}
Pour ajouter une autre tâche à exécuter toutes les 15 secondes, étendez les intervals
variables et last
:
unsigned long intervals[] = {250,2000,15000};
unsigned long last[] = {0,0,0};
Ajoutez ensuite une instruction if
pour exécuter la nouvelle tâche. Dans cet exemple, je l'ai nommé thirdTask
.
if(now-last[2]>=intervals[2]){ last[2]=now; thirdTask(); }
Enfin déclarez la fonction:
void thirdTask(){
//your code here
}