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

Nucléo – Faire plusieurs actions à intervalle régulier