Outils pour utilisateurs

Outils du site


start:arduino:esp32:les_timers

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
start:arduino:esp32:les_timers [2022/04/24 08:50] gerardadminstart:arduino:esp32:les_timers [2023/01/27 16:08] (Version actuelle) – modification externe 127.0.0.1
Ligne 1: Ligne 1:
 ======== Les Timers ======== ======== Les Timers ========
  
-Timers sur ESP32+=== Timers === 
 + 
 +Les SoC ESP32 contiennent de 2 à 4 minuteries matérielles. Ce sont tous des temporisateurs génériques 64 bits (54 bits pour ESP32-C3) basés sur des pré-scalers 16 bits et des compteurs croissants/décroissants 64 bits (54 bits pour ESP32-C3) capables d'être rechargés automatiquement. 
 + 
 +^SoC ESP32^Nombre de minuteries^ 
 +|ESP32|4| 
 +|ESP32-S2|4| 
 +|ESP32-C3|2| 
 +|ESP32-S3|4| 
 + 
 + 
 +[[https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/timer.html|Arduino-ESP32 Timer API¶]] 
 + 
 + 
 + 
 +===Timers sur ESP32===
  
 Fondamentalement, un Timer (minuterie)  est une horloge, qui est utilisée pour mesurer et contrôler les événements temporels. offrant une temporisation précise.  Fondamentalement, un Timer (minuterie)  est une horloge, qui est utilisée pour mesurer et contrôler les événements temporels. offrant une temporisation précise. 
Ligne 21: Ligne 36:
 Nous aurons un compteur supplémentaire pour suivre le nombre d'interruptions déjà survenues. Nous aurons un compteur supplémentaire pour suivre le nombre d'interruptions déjà survenues.
  
- int totalInterruptCounter ;+   int totalInterruptCounter ;
  
 Afin de configurer le timer, nous aurons besoin d'un pointeur vers une variable de type hw_timer_t . Afin de configurer le timer, nous aurons besoin d'un pointeur vers une variable de type hw_timer_t .
  
- hw_timer_t * timer = NULL;+   hw_timer_t * timer = NULL;
  
 Enfin, nous devrons déclarer une variable de type portMUX_TYPE qui nous servira à nous occuper de la synchronisation entre la boucle principale et l'ISR. Enfin, nous devrons déclarer une variable de type portMUX_TYPE qui nous servira à nous occuper de la synchronisation entre la boucle principale et l'ISR.
  
- portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;+   portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  
 Pour initialiser le timer à l'aide d'une fonction timerbegin , cette fonction reçoit le numéro du timer que l'on souhaite utiliser (de 0 à 3, puisque nous avons 4 timers matériels), la valeur du prescaler et un drapeau indiquant si le compteur doit compter (vrai) ou vers le bas (faux). Pour initialiser le timer à l'aide d'une fonction timerbegin , cette fonction reçoit le numéro du timer que l'on souhaite utiliser (de 0 à 3, puisque nous avons 4 timers matériels), la valeur du prescaler et un drapeau indiquant si le compteur doit compter (vrai) ou vers le bas (faux).
  
-  minuterie minuterieBegin(0, 80, vrai);+   timer timerBegin(0, 80, vrai);
  
 Pour cet exemple, nous utiliserons la première minuterie et passerons vrai au dernier paramètre, donc le compteur compte la fréquence du signal de base utilisé par les compteurs ESP32 est de 80 MHz . Si nous divisons cette valeur par 80 (en utilisant 80 comme valeur du prescaler), nous obtiendrons un signal avec une fréquence de 1 MHz qui incrémentera le compteur de la minuterie 1 000 000 fois par seconde. Pour cet exemple, nous utiliserons la première minuterie et passerons vrai au dernier paramètre, donc le compteur compte la fréquence du signal de base utilisé par les compteurs ESP32 est de 80 MHz . Si nous divisons cette valeur par 80 (en utilisant 80 comme valeur du prescaler), nous obtiendrons un signal avec une fréquence de 1 MHz qui incrémentera le compteur de la minuterie 1 000 000 fois par seconde.
Ligne 39: Ligne 54:
 Avant d'activer le temporisateur, nous devons le lier à une fonction de traitement, qui sera exécutée lorsque l'interruption sera générée. Cela se fait avec un appel à la fonction timerAttachInterrupt . Avant d'activer le temporisateur, nous devons le lier à une fonction de traitement, qui sera exécutée lorsque l'interruption sera générée. Cela se fait avec un appel à la fonction timerAttachInterrupt .
  
- timerAttachInterrupt(timer, &onTimer, true);+   timerAttachInterrupt(timer, &onTimer, true);
  
 Cette fonction reçoit en entrée un pointeur vers le timer initialisé, que nous avons stocké dans notre variable globale, l'adresse de la fonction qui va gérer l'interruption et un drapeau indiquant si l'interruption à générer est front (true) ou level (false) . Cette fonction reçoit en entrée un pointeur vers le timer initialisé, que nous avons stocké dans notre variable globale, l'adresse de la fonction qui va gérer l'interruption et un drapeau indiquant si l'interruption à générer est front (true) ou level (false) .
 Pour cet exemple, nous passerons notre variable de minuterie globale en première entrée, en deuxième l'adresse d'une fonction appelée onTimer que nous spécifierons plus tard, et en troisième la valeur true , donc l'interruption générée est de type edge. Pour cet exemple, nous passerons notre variable de minuterie globale en première entrée, en deuxième l'adresse d'une fonction appelée onTimer que nous spécifierons plus tard, et en troisième la valeur true , donc l'interruption générée est de type edge.
  
- timerAlarmWrite(timer, 1000000, true);+   timerAlarmWrite(timer, 1000000, true);
  
 fonction timerAlarmWrite pour spécifier la valeur du compteur dans laquelle l'interruption du temporisateur a été générée. Donc, pour cet exemple, on suppose que l'on veut générer une interruption chaque seconde, et on passe donc la valeur de 1 000 000 microsecondes, qui est égale à 1 seconde. fonction timerAlarmWrite pour spécifier la valeur du compteur dans laquelle l'interruption du temporisateur a été générée. Donc, pour cet exemple, on suppose que l'on veut générer une interruption chaque seconde, et on passe donc la valeur de 1 000 000 microsecondes, qui est égale à 1 seconde.
Ligne 50: Ligne 65:
 Pour terminer la fonction de configuration en activant un appel à timerAlarmEnable(timer); Pour terminer la fonction de configuration en activant un appel à timerAlarmEnable(timer);
  
-Boucle principale+==== Main loop ====
  
-La boucle principale sera l'endroit où nous gérons réellement l'interruption de la minuterie, après qu'elle ait été signalée par l' ISR (routine de service d'interruption également appelée gestionnaire d'interruption) . Pour vérifier la valeur du compteur d'interruptions, nous allons donc vérifier si lavariable du compteur d'interruptions est supérieur à zéro et si c'est le cas, nous entrerons le code de gestion des interruptions. Là, la première chose que nous allons faire est de décrémenter ce compteur, signalant que l'interruption a été acquittée et sera traitée.+La boucle principale (main loop) sera l'endroit où nous gérons réellement l'interruption de la minuterie, après qu'elle ait été signalée par l' ISR (routine de service d'interruption également appelée gestionnaire d'interruption) . Pour vérifier la valeur du compteur d'interruptions, nous allons donc vérifier si lavariable du compteur d'interruptions est supérieur à zéro et si c'est le cas, nous entrerons le code de gestion des interruptions. Là, la première chose que nous allons faire est de décrémenter ce compteur, signalant que l'interruption a été acquittée et sera traitée.
  
 <code c 1.ino> <code c 1.ino>
Ligne 82: Ligne 97:
 La gestion réelle des interruptions consistera simplement à incrémenter le compteur avec le nombre total d'interruptions survenues depuis le début du programme et à l'imprimer sur le port série. La gestion réelle des interruptions consistera simplement à incrémenter le compteur avec le nombre total d'interruptions survenues depuis le début du programme et à l'imprimer sur le port série.
  
-Minuterie_série+{{ :start:arduino:esp32:timer_serial.png?direct&400 |}} 
 + 
 + 
 + 
 +===== ESP32TimerInterrupt Library ====== 
 + 
 +[[https://github.com/khoih-prog/ESP32TimerInterrupt|ESP32TimerInterrupt Library]] 
 + 
 + 
 +==== Pourquoi avons-nous besoin de cette bibliothèque ESP32TimerInterrupt==== 
 + 
 + 
 +===  Caractéristiques=== 
 + 
 +Cette bibliothèque vous permet d'utiliser "Interrupt from Hardware Timers" sur une carte basée sur ESP32. 
 + 
 +Comme les temporisateurs matériels sont des atouts rares et très précieux de n'importe quelle carte, cette bibliothèque vous permet désormais d'utiliser jusqu'à 16 temporisateurs basés sur ISR, tout en ne consommant qu'un seul temporisateur matériel . L'intervalle des temporisateurs est très long ( ulong millisecs ). 
 + 
 +Désormais, avec ces nouveaux temporisateurs basés sur 16 ISR , l'intervalle maximal est pratiquement illimité (limité uniquement par de longues millisecondes non signées) tandis que la précision est presque parfaite par rapport aux temporisateurs logiciels. 
 + 
 +La caractéristique la plus importante est qu'il s'agit de minuteries basées sur ISR. Par conséquent, leurs exécutions ne sont pas bloquées par des fonctions/tâches au mauvais comportement . Cette fonctionnalité importante est absolument nécessaire pour les tâches critiques. 
 + 
 +L' exemple ISR_Timer_Complex démontrera la précision presque parfaite par rapport aux temporisateurs logiciels en imprimant les millisecondes écoulées réelles de chaque type de temporisateurs. 
 + 
 +Étant des minuteries basées sur ISR, leurs exécutions ne sont pas bloquées par des fonctions/tâches qui se comportent mal, telles que la connexion aux services WiFi, Internet et Blynk. Vous pouvez également avoir plusieurs (up to 16)minuteries à utiliser. 
 + 
 +Cette fonctionnalité importante non bloquée est absolument nécessaire pour les tâches critiques. 
 + 
 +Vous verrez que le logiciel blynkTimer est bloqué pendant que le système se connecte au WiFi / Internet / Blynk, ainsi qu'en bloquant la tâche dans loop(), en utilisant la fonction delay() comme exemple. Le temps écoulé est alors très imprécis 
 +Pourquoi l'utilisation d'une interruption de minuterie matérielle basée sur ISR est préférable 
 + 
 +Imaginez que vous ayez un système avec une fonction critique , mesurant le niveau d'eau et contrôlant la pompe de puisard ou faisant quelque chose de beaucoup plus important. Vous utilisez normalement une minuterie logicielle pour interroger, ou même placer la fonction dans loop(). Mais que se passe-t-il si une autre fonction bloque la boucle() ou la configuration(). 
 + 
 +Ainsi, votre fonction pourrait ne pas être exécutée et le résultat serait désastreux. 
 + 
 +Vous préféreriez que votre fonction soit appelée, quoi qu'il arrive avec d'autres fonctions (boucle occupée, bogue, etc.). 
 + 
 +Le bon choix consiste à utiliser une minuterie matérielle avec interruption pour appeler votre fonction. 
 + 
 +Ces temporisateurs matériels, utilisant l'interruption, fonctionnent toujours même si d'autres fonctions bloquent. De plus, ils sont beaucoup plus précis (certainement en fonction de la précision de la fréquence d'horloge) que les autres temporisateurs logiciels utilisant millis() ou micros(). Cela est nécessaire si vous avez besoin de mesurer certaines données nécessitant une meilleure précision. 
 + 
 +Les fonctions utilisant des minuteries logicielles normales, reposant sur loop() et appelant millis(), ne fonctionneront pas si loop() ou setup() est bloqué par certaines opérations. Par exemple, certaines fonctions se bloquent lors de la connexion au WiFi ou à certains services. 
 + 
 +Le hic, c'est que votre fonction fait maintenant partie d'un ISR (Interrupt Service Routine), et doit être courte et  rapide , et suivre certaines règles. Plus à lire sur : 
 + 
 + 
 +[[https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/| HOWTO Attach Interrupt]] 
 + 
 + 
 +===== Minuterie à usage général (GPTimer) ===== 
 + 
 +[[https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gptimer.html?highlight=timers|Minuterie à usage général (GPTimer)]] 
 + 
 + 
 +===== Minuterie haute résolution ===== 
 + 
 +[[https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html?highlight=timers|Minuterie haute résolution]] 
 + 
/home/chanteri/www/fablab37110/data/attic/start/arduino/esp32/les_timers.1650783006.txt.gz · Dernière modification : 2023/01/27 16:08 (modification externe)