mardi 19 mars 2019

Arduino, ESP8266 et ESP32 une librairie timers



 Arduino, ESP8266 et ESP32

 une librairie timers


Sur ARDUINO la gestion du temps est pour le moins spartiate. Les développeurs utilisent souvent millis et lorsque l'on a plusieurs timers à gérer le code devient vite sac de nouilles.

Pourquoi ne pas bâtir une librairie qui permettent de gérer un ou plusieurs timers ?

Ou pourrait résumer l'interface à celle-ci :
  • créer  le timer
  • armer le timer
  • consulter le timer
  • le timer pourrait aussi appeler une fonction fournie par l'utilisateur lorsque le temps est écoulé.
Des choses existent déjà :
Oui, mais ces librairies monopolisent un timer pour chaque utilisation. Ce n'est pas suffisant si l'on a besoin de plus de deux timers, surtout sur un ARDUINO NANO qui n'en possède que deux.

Sur ESP8266 et ESP32 la librairie le kit de développement dispose déjà de timers modernes qui correspondent exactement au besoin.
Mais comme toujours dans le monde Espressif, chaque microcontrôleur a une interface logicielle différente. Pourquoi simplifier la vie des développeurs quand on peut s'en dispenser ?

On pourrait tout simplement exploiter les timers ESP8266 et ESP32 pour les intégrer dans la librairie. L'interface serait donc identique pour ARDUINO, ESP8266 et ESP32.

1. Le besoin

L'idée de base serait de reprendre l'idée de TimerOne ou Timer2, c'est à dire accrocher une routine d'interruption au vecteur TIMER1 ou TIMER2. A partir de cette routine gérer plusieurs instances purement logicielles ne devrait pas être bien complexe.

J'ai donc déterré une idée que j'avais eu à il y a dix ans : porter l'interface de timers du kernel LINUX :
  • void init_timer(struct timer_list * timer);
  • void setup_timer(struct timer_list timer, void (function)(unsigned long), unsigned long data );
  • int add_timer(struct timer_list* timer);
  • void mod_timer(struct timer_list* timer, unsigned long expires);
  • int del_timer(struct timer_list* timer);
init_timer crée un timer
setup_timer permet de fournir une fonction utilisateur
add_timer ajoute le timer au système
mod_timer arme le timer
del_timer le détruit

A l'époque ce portage avait été fait sur MSP430. Un ARDUINO sera parfaitement à l'aise. Le code de la routine d'interruption est très légère.

Un timer est un élément de liste chaînable, et nous pourrons en créer autant que nécessaire.

Un petit exemple de ce que cela pourrait donner :

#include <kernel_timers.h>

#define TIMEOUT          (HZ*5)

struct timer_list timer;

void setup()
{
  Serial.begin(115200);
  // initialize timers system with TIMER1
  timer_init(1);
  init_timer(&timer);
  add_timer(&timer);
  Serial.println("\nStart the timer for 5 seconds");
  mod_timer(&timer, jiffies + TIMEOUT);
}

void loop()
{
  if (timer.expires != 0 && timer.expires == jiffies) {
    Serial.println("Timer has elapsed");
    mod_timer(&timer, 0);
  }
} 

HZ représente la fréquence de d'actualisation des timers (l'interruption).
jiffies représente le temps courant.
Donc jiffies + (5 * HZ) représente le temps courant + 5 secondes.

Une explication des jiffies sous WIKIPEDIA : https://en.wikipedia.org/wiki/Jiffy_(time)

Notre librairie aura une valeur de HZ de 200. Cela nous donnera une résolution de 5 millisecondes pour nos timers.

La fonction d'initialisation de la librairie accepte un paramètre timer. Il s'agit du numéro de timer hardware :
  • sur Atmega328 vous avez le choix entre 1 et 2
  • sur Atmega2560 vous avez le choix entre 1,2, 3, 4 et 5
  • sur ESP8266 et ESP32 ce paramètre est ignoré

2. La librairie

La librairie est disponible ici :
https://bitbucket.org/henri_bachetti/kernel_timers.git

Cette page vous donne toutes les informations nécessaires :
https://riton-duino.blogspot.com/p/migration-sous-bitbucket.html

Quelques  exemples d'utilisation sont fournis.

Tous les exemples tournent sur ARDUINO UNO, MEGA, ESP8266 et ESP32.


Cordialement

Henri BACHETTI

3 commentaires:

  1. 5 millisecondes je trouve que c'est un peu long. Est-il possible de descendre plus bas?

    RépondreSupprimer
    Réponses
    1. En général lorsque l'on a besoin de timings courts on n'utilise pas ce genre de technique qui ferait passer plus de temps dans les interruptions timers que dans l'application, à moins de disposer d'un gros processeur.

      Supprimer
    2. Mais sinon, oui, on peut diminuer TICK pour descendre à 1ms.

      Supprimer