Sylvain Mahé Le site Web Retour à l'accueil Principes Partager des idées et des projets. Contact 06.45.49.96.98
contact@sylvainmahe.site
Écriture de la page : Sylvain Mahé
Créer des seuils avec la classe Hysteresis La classe Hysteresis permet de fixer les états d'une variable cible via la création automatique de seuils hauts et bas différents suivant l'évolution positive ou négative d'une variable source, et ainsi d'éviter des fluctuations non souhaitées. Imaginons un menu pouvant prendre différentes positions entières de 1 à 10 (soit 10 nombres entiers) navigable à l'aide d'un potentiomètre analogique. La tension de 0V à 5V retournée par le curseur du potentiomètre (qui est un pont diviseur de tension) est traduite par le convertisseur analogique/numérique du microcontrôleur en nombres entiers accessibles en programmation pouvant varier de 0 à 1023. Programmons ce montage comme l'exemple suivant : #include <AnalogRead.h> #include <Math.h> int main() { AnalogRead myPotentiometer = AnalogRead (25); unsigned char myMenu = 1; while (true) { myPotentiometer.read(); myMenu = Math::round (Math::curve (0, myPotentiometer.value, 1023, 1, 10, 0)); //myMenu est la position dans le menu (de 1 à 10) en fonction de la valeur retournée par le potentiomètre } return 0; } Dans cet exemple, dès que le potentiomètre approche après calcul une valeur se situant à mi-chemin entre deux positions du menu, plus il y a de chances que le menu saute d'une position à une autre d'une façon tout à fait erratique, et ce d'autant plus que le bruit analogique du potentiomètre est important. Pour palier à ce problème, il convient d'introduire un cycle d'hystérésis dans le calcul afin que le chemin emprunté par la variation qui anime le menu soit différent selon l'évolution positive ou négative de la valeur du potentiomètre, ce qui créé naturellement une zone delta, comme le montre l'exemple ci-dessous. Exemple d'utilisation de la classe Hysteresis : #include <AnalogRead.h> #include <Math.h> #include <Hysteresis.h> int main() { AnalogRead myPotentiometer = AnalogRead (25); Hysteresis myMenu = Hysteresis(); while (true) { myPotentiometer.read(); myMenu.set (Math::curve (0, myPotentiometer.value, 1023, 1, 10, 0)); //myMenu.value est la position dans le menu (de 1 à 10) en fonction de la valeur retournée par le potentiomètre } return 0; } Ci-dessus, un objet myPotentiometer de type AnalogRead est déclaré, en paramètre est indiqué d'utiliser le port GPIO numéro 25 de l'automate programmable en entrée. La ligne suivante est différente de l'exemple précédent, puisque c'est un objet myMenu de type Hysteresis qui est déclaré (ne prenant aucun paramètre). Puis dans la boucle, l'objet myPotentiometer appelle la fonction read ce qui permet de lire l'entrée analogique concernée, et donc de mettre à jour la variable value attachée à cet objet, variable utilisée en paramètre de la fonction statique curve de la classe Math afin de changer l'échelle de 0 à 1023 (la sortie du convertisseur analogique/numérique) vers 1 à 10 (la valeur souhaitée du menu). Cette valeur pouvant varier de 1 à 10, sortie de la fonction statique curve, est un nombre décimal. C'est ce nombre décimal qui est donné en paramètre à la fonction set de l'objet myMenu : Il est important de comprendre que le fonctionnement de la classe Hysteresis est basé sur l'exploitation des décimales des nombres (en virgule flottante) envoyés en paramètre à la fonction set, décimales à partir desquelles la classe Hyseresis produit des nombres entiers finis avec hystérésis. À présent le menu est doté d'un hystérésis et est débarrassé des sauts imprévisibles provoqués par les imperfections inhérentes à l'utilisation de signaux analogiques. La valeur exploitable du menu est accessible via la variable value attachée à l'objet myMenu. Dans tous les cas pour que l'hystérésis fonctionne, il convient de s'assurer que la quantité de bruit analogique généré par le potentiomètre soit (largement) inférieure à l'hystérésis souhaité, ce qui est complètement dépendant de la qualité du potentiomètre, du circuit qui l'asservi, et de la plage de valeurs finales (de 1 à 10 dans les exemples) par rapport à la plage de valeurs en sortie du convertisseur analogique/numérique du microcontrôleur (de 0 à 1023). Un autre exemple d'application du cycle d'hystérésis pourrait être l'allumage et l'extinction d'une chaudière qui devrait être en marche en dessous d'une température, et éteinte au dessus de cette même température. Imaginons une température consigne de 15 degrés Celcius en dessous de laquelle une chaudière démarre. La température initiale est supérieure à 15 degrés Celcius, la chaudière est éteinte et la température baisse progressivement. Dès que la température est inférieure à 15 degrés Celcius, c'est-à-dire 14.999... degrés Celcius, la chaudière démarre. Au bout de quelques secondes la température augmente et passe au dessus de 15 degrés Celcius, immédiatement la chaudière s'éteint alors, la température redescends, puis la chaudière redémarre à nouveau, et ainsi de suite. Dans ce montage la chaudière démarrerait et s'éteindrait d'une façon intempestive, ce qui n'est pas souhaité pour une question pratique, ergonomique, d'économie d'énergie, et d'usure prématurée des composants mis en œuvre. C'est également ici qu'intervient le cycle d'hystérésis, comme le montre l'exemple ci-dessous. Autre exemple d'utilisation de la classe Hysteresis : #include <AnalogRead.h> #include <Math.h> #include <Hysteresis.h> int main() { AnalogRead mySensor = AnalogRead (25); Hysteresis myTemperature = Hysteresis(); bool myBoilerState = false; while (true) { mySensor.read(); myTemperature.set (Math::curve (0, mySensor.value, 1023, 0, 100, 0)); if (myTemperature.value < 15) { myBoilerState = true; } else { myBoilerState = false; } //myBoilerState est l'état de la chaudière (à l'arrêt ou en marche) } return 0; } L'hystérésis créé une zone delta de 1 degrés Celcius. Dans ce montage, selon si la température est dans une phase d'augmentation ou de diminution, la chaudière peut être dans un état de marche (true) ou d'arrêt (false) dans cette zone delta. L'hystérésis est donc indispensable dans la majorité des projets afin de faire fonctionner des systèmes correctement et avec fiabilité, ou encore ne serait-ce que pour pouvoir visualiser sur des affichages numériques des valeurs stables. À ce propos, la classe Hysteresis est un bon complément en association avec la classe Filter dans le but de produire des informations exploitables pour l'utilisateur. Références : Récapitulatif des fonctions et variables de cette classe : signed long value = 0; Hysteresis(); void set (const float VALUE);