Comment faire plusieurs actions à intervalle régulier ?
NIVEAU 2
Objectifs
- Mettre en oeuvre des timers logiciels basés sur un timer matériel
Pré-requis
Timer logiciel
Les modules matériels de gestion du temps ne sont pas en nombre suffisant pour certaines applications afin de pouvoir traiter indépendamment toutes les actions à réaliser à intervalle régulier. Il est parfois nécessaire de passer par des timers dits logiciels.
Timer logiciel
Un timer logiciel est une variable du programme qui va servir de compteur. Celle-ci sera décrémentée à chaque interruption d’un timer matériel (voir tutoriel Faire une action à intervalle régulier). A l’aide de cette variable, on pourra alors compter le nombre de périodes réalisées du timer matériel (dont on connait la période de répétition – \(T_M\)). Ainsi, en paramétrant bien la valeur initiale du compteur, à une valeur \(N\), on pourra obtenir un temps précis : \(\Delta{}T = (N+1) \cdot T_M\).
On peut ainsi déclarer une grande quantité de variables “timers”.
Exemple complet en mode astable
Dans le cas où l’on souhaite réaliser une action à intervalle régulier dans le temps et de manière répétée indéfiniment, on parle d’un fonctionnement astable. Le code suivant permet d’obtenir un tel fonctionnement sur deux sorties différentes avec des périodes d’allumage et d’extinction différentes, multiples d’un quantum de temps (1 ms dans cet exemple).
#include "mbed.h" #define TIMER1 54 #define TIMER2 221 Ticker log_timer; // Déclaration du ticker DigitalOut led1(LED1); // Déclaration de la sortie numérique DigitalOut led2(D10); // Déclaration de la sortie numérique int timer1, timer2; // variables compteurs void toggle_cpt() { if(timer1 != 0) timer1--; if(timer2 != 0) timer2--; } int main() { timer1 = TIMER1; timer2 = TIMER2; log_timer.attach(&toggle_cpt, 0.001); while (1) { if(timer1 == 0){ timer1 = TIMER1; led1 = !led1; } if(timer2 == 0){ timer2 = TIMER2; led2 = !led2; } // Boucle Infinie } }
Dans cet exemple, on paramètre un timer matériel à une période de 1 ms (voir tutoriel Faire une action à intervalle régulier). La routine d’interruption associée à ce timer permet de décrémenter l’ensemble des compteurs logiciels (variables entières) jusqu’à 0. Dans la boucle infinie du programme principal, on teste en permanence le passage par 0 de ces compteurs logiciels. Lorsqu’ils arrivent à 0, on les recharge à une valeur particulière (correspondant à la période associée à l’ensemble des actions à réaliser).
Ici la sortie nommée LED1 “clignotera” à la période de 2 x 54 ms et la sortie nommée LED2 à la période de 2 x 221 ms.
Exemple complet en mode monostable
On peut aussi avoir de déclencher une action pendant un temps donné : allumage d’une sortie durant un temps prédéfini, temporisation d’une cage d’escalier… On parle alors d’un fonctionnement en mode monostable.
La fin de l’action sera fixée par la durée de la temporisation et le début de l’action par un événement extérieur : le passage d’une variable à une valeur particulière, l’appui sur un bouton poussoir.
Dans l’exemple suivant, on déclenche une minuterie de 500 ms à partir de l’appui sur le bouton-poussoir BUTTON1.
#include "mbed.h" #define TIMER1 50 Ticker log_timer; // Déclaration du ticker DigitalOut led1(LED1); // Déclaration de la sortie numérique InterruptIn bp_int(BUTTON1); // Déclaration d'une entrée numérique / interruption int timer1; // variable compteur void toggle_cpt() { if(timer1 != 0) timer1--; } void routine_bp(){ timer1 = TIMER1; led1 = 1; } int main() { timer1 = TIMER1; bp_int.fall(&routine_bp); log_timer.attach(&toggle_cpt, 0.01); while (1) { if(timer1 == 0){ // FIN ACTION led1 = 0; } // Boucle Infinie } }
Dans cet exemple, on paramètre un timer matériel à une période de 10 ms (voir tutoriel Faire une action à intervalle régulier).
On paramètre également l’entrée BUTTON1 comme entrée d’interruption, que l’on attache à la fonction routine_bp. Celle-ci permet d’initialiser le compteur logiciel et de réaliser l’action à faire sur l’appui sur le bouton poussoir (ici mettre à ‘1’ la sortie led1). Dans la boucle infinie, dès que le compteur timer1 arrive à 0, on réalise une seconde action (ici mettre à ‘0’ la sortie led1).
MInE Prototyper Prototyper avec Nucleo et MBED