start:arduino:esp32:les_timers
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
start:arduino:esp32:les_timers [2022/04/24 08:44] – gerardadmin | start: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/ | ||
+ | |||
+ | ^SoC ESP32^Nombre de minuteries^ | ||
+ | |ESP32|4| | ||
+ | |ESP32-S2|4| | ||
+ | |ESP32-C3|2| | ||
+ | |ESP32-S3|4| | ||
+ | |||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | |||
+ | ===Timers sur ESP32=== | ||
Fondamentalement, | Fondamentalement, | ||
Ligne 9: | Ligne 24: | ||
- | Une interruption est un événement externe qui interrompt le programme en cours et exécute une routine de service d' | + | **Une interruption** est un événement externe qui interrompt le programme en cours et exécute une routine de service d' |
Une fois l'ISR terminé, le programme en cours se poursuit avec l' | Une fois l'ISR terminé, le programme en cours se poursuit avec l' | ||
Ligne 17: | Ligne 32: | ||
volatile int interruptCounter ; | volatile int interruptCounter ; | ||
+ | | ||
+ | | ||
+ | Nous aurons un compteur supplémentaire pour suivre le nombre d' | ||
+ | |||
+ | int totalInterruptCounter ; | ||
+ | |||
+ | Afin de configurer le timer, nous aurons besoin d'un pointeur vers une variable de type hw_timer_t . | ||
+ | |||
+ | | ||
+ | |||
+ | 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. | ||
+ | |||
+ | | ||
+ | |||
+ | 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), | ||
+ | |||
+ | timer = timerBegin(0, | ||
+ | |||
+ | 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. | ||
+ | |||
+ | Avant d' | ||
+ | |||
+ | | ||
+ | |||
+ | Cette fonction reçoit en entrée un pointeur vers le timer initialisé, | ||
+ | Pour cet exemple, nous passerons notre variable de minuterie globale en première entrée, en deuxième l' | ||
+ | |||
+ | | ||
+ | |||
+ | fonction timerAlarmWrite pour spécifier la valeur du compteur dans laquelle l' | ||
+ | Le troisième argument que nous passerons true , donc le compteur se rechargera et donc l' | ||
+ | Pour terminer la fonction de configuration en activant un appel à timerAlarmEnable(timer); | ||
+ | |||
+ | ==== Main loop ==== | ||
+ | |||
+ | La boucle principale (main loop) sera l' | ||
+ | |||
+ | <code c 1.ino> | ||
+ | if (interruptCounter > 0) { | ||
+ | |||
+ | portENTER_CRITICAL(& | ||
+ | interruptCounter--; | ||
+ | portEXIT_CRITICAL(& | ||
+ | |||
+ | totalInterruptCounter++; | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.println(totalInterruptCounter); | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | La fonction ISR doit être une fonction qui renvoie void et ne reçoit aucun argument. La routine de gestion des interruptions doit avoir l' attribut IRAM_ATTR , pour que le compilateur place le code dans IRAM. De plus, les routines de gestion des interruptions ne doivent appeler que les fonctions également placées dans l' IRAM. | ||
+ | |||
+ | <code c 2.ino> | ||
+ | void IRAM_ATTR onTimer() { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Puisque cette variable est partagée avec l'ISR, nous le ferons dans une section critique, que nous spécifions en utilisant une macro portENTER_CRITICAL et une macro portEXIT_CRITICAL . Ces deux appels reçoivent en argument l' | ||
+ | La gestion réelle des interruptions consistera simplement à incrémenter le compteur avec le nombre total d' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | |||
+ | ===== ESP32TimerInterrupt Library ====== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | ==== Pourquoi avons-nous besoin de cette bibliothèque ESP32TimerInterrupt==== | ||
+ | |||
+ | |||
+ | === Caractéristiques=== | ||
+ | |||
+ | Cette bibliothèque vous permet d' | ||
+ | |||
+ | Comme les temporisateurs matériels sont des atouts rares et très précieux de n' | ||
+ | |||
+ | Désormais, avec ces nouveaux temporisateurs basés sur 16 ISR , l' | ||
+ | |||
+ | La caractéristique la plus importante est qu'il s'agit de minuteries basées sur ISR. Par conséquent, | ||
+ | |||
+ | 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/ | ||
+ | |||
+ | 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' | ||
+ | |||
+ | 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' | ||
+ | |||
+ | Le bon choix consiste à utiliser une minuterie matérielle avec interruption pour appeler votre fonction. | ||
+ | |||
+ | Ces temporisateurs matériels, utilisant l' | ||
+ | |||
+ | 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:// | ||
+ | |||
+ | |||
+ | ===== Minuterie à usage général (GPTimer) ===== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | ===== Minuterie haute résolution ===== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ |
/home/chanteri/www/fablab37110/data/attic/start/arduino/esp32/les_timers.1650782699.txt.gz · Dernière modification : 2023/01/27 16:08 (modification externe)