17) Mémoriser l’évolution de la tension de décharge en EEPROM.

Lorsque le logiciel était entièrement développé, que la capacité était mesurée correctement et le résultat affiché à convenance sur l’écran LCD, le programme complet restait bien discret, très loin de saturer la place possible dans la SDRAM qui lui est réservée. Pourtant la détection de fin de charge était en place, ainsi que le système d’alerte sur absence de fusible. N’utiliser que le quart de l’espace programme disponible n’est pas très rentable, aussi, l’idée de mémoriser des données traduisant l’évolution du processus devenait particulièrement tentante. De plus, tant qu’à utiliser la mémoire EEPROM non volatile, autant s’en servir pour sauvegarder le contexte. Ainsi, il devient possible d’interrompre le processus à tout moment, puis de le reprendre plus tard. Par exemple vous avez commencé à tester une batterie, et vous réalisez que la fin du mesurage va survenir vers trois heures du matin ! Soit le laboratoire est loin de votre chambre. Vous n’entendrez pas le bruiteur qui vous alerte. Hors il faut stopper la décharge sans tarder. Soit vous avez caché le bazar sous votre lit pour vous chauffer l’hiver, et ne désirez surtout pas être réveillé durant la nuit. Dans cette hypothèse, bien que la décharge totalise déjà plusieurs heures, vous suspendez le processus et débranchez la batterie. Le lendemain matin, après un bon petit déjeuner, vous rechargez le contexte depuis l’EEPROM, relancez les mesures et branchez à nouveau la batterie. Pour savoir ce que désigne « le contexte », voyons auparavant comment on va mémoriser l’historique du processus. Ces sauvegardes de données pourront librement être consultées par la suite. On en déduira si on le souhaite la tension nominale de la batterie, la courbe de décroissance de cette tension en fonction du temps. Bien entendu, seront également mémorisés le nombre d’échantillons consultables, et la capacité mesurée pour le bloc énergétique évalué. Chaque échantillon contiendra l’instant de capture, et la tension batterie à ce moment. L’instant  correspond au temps écoulé depuis de début de la décharge. Il faut un octet pour coder le nombre d’heures, et un octet pour les minutes. Les saisies d’échantillons se faisant pour des secondes nulles, deux octets sont donc suffisants. Pour la tension batterie, on mémorisera la valeur issue du CAN codée sur un entier. Donc deux octets seront suffisants. À la restitution, on transposera cet entier en volts, la routine est déjà écrite pour l’exploitation en cours de mesurage.

CONCLUSION : Il faut quatre octets par échantillon. On s’impose de ne pas dépasser 1000 octets réservés aux données, pour en avoir 24 pour sauvegarder le contexte. Comme on peut aller jusqu’à 50Ah avec un courant moyen de 4A, la décharge exigera 10,5 Heures au maximum soit 750 minutes. Sachant que le nombre d’échantillons maximal sera de 1000 / 4 = 250, on en déduit facilement l’intervalle de temps entre deux échantillons : ΔT = 750 / 250 = 3 minutes.
Pour simplifier la gestion de sauvegarde, les échantillons seront inscrits depuis le bas de la mémoire. Tout en haut, à l’adresse 1023 on logera le nombre d’échantillons mémorisés qui sera fonction de la capacité de la batterie, ou du fait que l’on a interrompu le mesurage. Maximum 250 se code sur un octet. Juste en dessous, sur quatre octets aux adresses comprises entre 1019 et 1022 sera sauvegardée la valeur mesurée de la capacité. Codée sur un réel, donc un float, quatre octets sont suffisants. Pour restituer le contexte, (Explications données plus avant.) il faut également sauvegarder la valeur de la Capacité Théorique de la batterie testée. Codée sur un octet en cellule 1018. Les octets de l’EEPROM compris entre les adresses 1001 et 1017 inclus restent disponibles pour d’éventuelles modifications futures. La Fig.56 résume l’implantation des données en EEPROM.

Gestion de la mémoire EEPROM.

Contrairement à la mémoire vive, c’est à dire la RAM qui contient les données, l’EEPROM est une mémoire qui ne s’efface pas quand on coupe l’énergie. Elle ne peut être écrite qu’environ 100000 fois, comme la SD RAM de programme. Ensuite, on peut la considérer comme n’étant plus fiable. Il ne faut pas y inscrire des données à des cadences considérables, comme le programme le fait pour ses données par exemple. Ceci étant dit, quand vous aurez testé 100000 fois des batteries …  vous pourrez vous payer un autre ATmega 328 pour changer celui qui est sur la carte Arduino UNO !
La mémoire EEPROM est une ressource interne au microcontrôleur, sa taille est fonction du modèle utilisé. Sur l’ATmega328 on dispose d’un kilo octets soit 1024 emplacements. C’est déjà pas mal du tout et ouvre une foule d’applications possibles.
Comme toutes les ressources spécifiques à un microcontrôleur, le langage C++ qui lui est dédié peut offrir au programmeur des instructions spéciales. Pour lire et écrire des octets élémentaires en EEPROM, c’est assez élémentaire. Par contre, si on veut y loger des entiers, des réels, il faut aller chercher les valeurs  des variables en mémoire RAM. Hors, intrinsèquement nous ne savons pas où elles se trouvent, car c’est le compilateur qui se charge de leur réserver des emplacements.
Résoudre ces difficultés passe par ce que les initiés nomment les pointeurs. BERKKKKKKKK !
Heureusement, des courageux ont écrit des bibliothèques, nous n’avons qu’à en utiliser les procédures adaptées. Si nous n’en comprenons pas tout à fait la syntaxe, avec ces « * » qui se baladent un peu partout, ce n’est pas fondamental. On respecte l’écriture imposée, on remplace les paramètres par les identificateurs de nos variables et roule boule tout rond …

On commence par déclarer la bibliothèque : #include <avr/eeprom.h>

Pas besoin d’aller la chercher sur Internet. Elle est tellement commode qu’actuellement elle fait partie intégrante de l’IDE. Donc rien de particulier à faire, c’est méga génial non ?
Pour « naviguer dans l’espace EEPROM on va utiliser un indicateur d’adresse nommé INDEX. C’est la, ou les cellules mémoire pointées par INDEX, qui seront lue ou écrites. Une cellule si on travaille sur un  byte, deux si c’est un int et quatre pour un float. Nous avons à notre disposition six procédures et fonction de service qui permettent des échanges faciles avec la mémoire EEPROM :

(1) Par principe personnel, et vous êtes parfaitement libres de ne pas le partager, pour une lecture en mémoire je ne modifie pas le pointeur d’adresse. C’est avant d’aller chercher la donnée que j’affecte une valeur à ce dernier. (2) Toujours par systématisme, lorsqu’une l’écriture est réalisée, quel que soit la taille de ce qui est inscrit en mémoire, le pointeur d’adresse est laissé sur la prochaine cellule mémoire. Ainsi, on peut effectuer une succession d’écritures sans avoir à se préoccuper de l’adresse. Les six subroutines dont la liste précède respectent cette façon d’élaborer un logiciel.
Notez au passage qu’il y a une différence fondamentale entre lecture et écriture. Pour lire, on utilise des fonctions qui retournent un résultat. Donc, en préambule on impose une valeur à INDEX, puis on affecte la valeur retournée à une variable de type identique à celui de la fonction.
Par exemple : INDEX = 1019; Capacite = Lire_un_Float_en_EEPROM(INDEX);
En revanche, les écritures sont des procédures, c’est à dire qu’elles réalisent des instructions sans retourner de résultats. Dans mes procédures,INDEX est mis à jour à chaque écriture. C’est au tout début du programme que le pointeur est forcé à l’adresse 0000. Ensuite, écrite H et min l’incrémentera de 1, sauvegarder UBAT l’augmentera de deux. Ainsi INDEX pointe en permanence une cellule libre « à la suite » pour le prochain échantillonnage.
Par exemple au tout début d’un mesurage : INDEX = 0000;

Puis toutes les trois minutes :

Lorsque l’on amorce le mesurage d’une batterie, on se doute que le nombre d’échantillons mémorisés est forcé à zéro, et incrémenté toutes les trois minutes. Quand la détection de fin de décharge est déclenchée, automatiquement le nombre d’échantillons ainsi que la capacité mesurée sont alors sauvegardés respectivement en 1023 et en 1019. On peut alors couper la batterie, car le programme nous en informe par un « tirlituit » sonore très particulier dont vous aurez rapidement compris la signification. L’organigramme de la Fig.57 résume le déroulement du programme complet dans sa boucle de base pour que nous ayons une vue d’ensemble. Quelques explications s’imposent.

Examinons ensembles le fonctionnement de la boucle de base. Si en (1) un bouton poussoir n’est pas activé, le programme passe immédiatement à la suite en (3). Puis, si une seconde n’est pas écoulée, le logiciel reboucle en (1). Comme ces deux tests ne consomment que très peu de temps, la rotation est rapide, et une sollicitation de l’opérateur sera prise en compte sans attendre. Si exactement une seconde s’est écoulée, le test (3) est positif et le logiciel commence par inverser en (4) la LED verte qui atteste du bon fonctionnement du programme. Et surtout sur le connecteur HE14 nous avons le signal qui permet de vérifier la période avec précision. Puis l’horloge qui mesure le temps écoulé depuis le début du mesurage est incrémentée d’une seconde en (5) dans le système sexagésimal. En (6) le gros du travail est effectué. La tension aux bornes de R est mesurée par le CAN. Puis l’intensité débitée est calculée. Enfin, en (7) la capacité actuellement vérifiée est mise à jour. Pour des raisons de sécurité, en (8) la température du dissipateur de chaleur est mesurée. Si elle dépasse le seuil critique, l’alarme en boucle fermée de la Fig.58 est déclenchée incitant l’opérateur à intervenir. La tonalité des différentes alarmes est « agressive », car il faut attirer l’attention d’un intervenant éventuel présent à proximité des lieux. Puis, la tension aux bornes du fusible est mesurée en (9). Si elle dépasse le niveau de détection d’absence, une autre alarme avec un texte spécifique comme montré sur la Fig.59 est déclenchée. Notez que toutes les alertes, avant de prévenir l’opérateur commencent par sauvegarder le contexte pour sécurité, autorisant s’il le désire effectuer une reprise en différé après avoir traité le problème. Si tout va bien, le microcontrôleur continue son petit bonhomme de chemin. En (10) il incrémente un compteur. Si en  (11) ce compteur arrive à 180, comme il est modifié exactement une fois par seconde, c’est qu’il s’est écoulé trois minutes. Il est temps en (12) de sauvegarder un échantillon contenant l’Heure et la valeur de la tension batterie issue du CAN. En (13) on réarme le comptage. Dans tous les cas, en (14) on affiche les valeurs actuelles. La nature des informations visualisée dépendra de l’option sélectionnée par l’opérateur lors du traitement en (2) d’une action sur un bouton poussoir. La Fig.60 présente les quatre types d’informations disponibles. En (15) le logiciel vérifie si la batterie n’est pas complètement déchargée. Si ce n’est pas le cas, il y a reprise en (1) pour un nouveau tourbillon jusqu’à la prochaine seconde écoulée. Si la batterie est épuisée, immédiatement le contexte est sauvegardé en (16). Puis en (17) l’écran A est forcé à l’affichage. Les deux notes (18)  émises en boucle génèrent le « tirlituit » particulier informant l’utilisateur que le mesurage s’achève. Dès qu’en (19) on clique sur l’un des B.P, l’écran en (20) incite l’intervenant à débrancher la batterie et précise que les données ont été sauvegardées en EEPROM pour consultation ultérieure.
L’écran A est le plus immédiat. Il indique la valeur de la capacité actuellement évaluée, le courant de décharge, le temps écoulé depuis le début du mesurage, et la tension actuelle aux bornes de la batterie en cours de test. L’écran B permet de surveiller si on le désire la température actuelle du dissipateur thermique. Accessoirement, sur la ligne du haut est indiquée la tension aux bornes du fusible qui sera toujours très faible. (Sauf si il grille ou s’il est enlevé de son support.) Quand on clique sur le bouton LEFT, on fait alterner l’affichage entre les deux dernières options. L’affichage C précise le nombre actuel d’échantillons. La ligne du bas étant disponible, pourquoi ne pas indiquer le maximum possible ? C’est un peu du luxe, mais la mémoire de programme n’est vraiment pas encombrée, on peut gaspiller des octets à profusion. Et comme le processeur n’était pas du tout rentabilisé, en D nous avons un « sablier » dont le fonctionnement est précisé dans le chapitre qui suit.

Affichage d’un « sablier ».

Difficile de gaver la mémoire disponible pour loger un programme dans l’ATmega328. Il faut un logiciel « meumeu » pour la consommer presque entièrement. Du coup, quand tout fonctionnait, que les échantillons étaient sauvegardés en EEPROM ainsi que les séquences de visualisation de ces derniers écrites, il restait encore plein plein de place non utilisé. C’est assez agassif de se dire que l’on a financé 32256 octets et que l’on en consomme que 10424. Aussi, histoire de rentabiliser notre investissement, l’idée du sablier s’est imposée comme étant absolument INDISPENSABLE.
De quoi s’agit-t’il ?
Ben … quand vous téléchargez sur Internet un « gros truc » et que votre BOX est d’une lenteur désespérante, pour vous faire patienter WINDOWS affiche une rampe analogique qui simule un sablier. Il évalue le temps qu’il faudra, puis vous montre la proportion déjà effectuée.
Le sablier D fonctionne exactement pareil. Toute la largeur de la ligne du bas correspond au temps qu’il faudra pour « ratatiner » entièrement la batterie. Comme sous la tension nominale de 12V le courant est connu, il est facile de déterminer la durée nécessaire pour la décharge :

Calculer pour obtenir une largeur d’affichage correspondant à la durée maximale estimée exige de connaitre la Capacité théorique de la batterie testée, c’est à dire la capacité annoncée par le fournisseur quand elle est neuve. Cette information ne peut être devinée par le programme, aussi elle sera initialisée à la mise en service de l’appareil de mesures.
Le ruban analogique exploite la possibilité de pouvoir faire afficher jusqu’à huit caractères spéciaux à notre module LCD. En particulier le « é », » le « à » et « ° » n’existent pas d’origine, pas plus que   et . Par ailleurs, le « p », le « g » et le « j » minuscules ne sont pas très beaux. Aussi, tous ces caractères sont générés dans des matrices spécifiques. Le ruban analogique qui est affiché sur la ligne du bas de l’afficheur exige également pour son compte des caractères spéciaux. Deux programmes de démonstration sont disponibles. P04_Test_de_simultaneite.ino et P05_Rampe analogique.ino servent à dégrossir le problème. Pour afficher la rampe analogique il faut des pavés complets à cinq colonnes comme sur la Fig.61 celui représenté en 1. Mais l’étalement latéral ne comportera pas forcément un multiple de cinq colonnes élémentaires. Pour assurer la proportionnalité qui résultera du calcul de pourcentage, les caractères de 2 à 5 sont également indispensables. Au total, nous avons besoin de 13 caractères spéciaux. Hors l’afficheur ne peut en loger simultanément que huit. On peut les modifier librement à tout moment. En revanche, l’affichage des deux lignes ne se fait que sur un seul jeu de matrices car les pixels visualisés sur l’écran sont branchés « directement » sur les matrices personnalisées. Pour vous permettre de mieux comprendre ce qui se passe, téléchargez P04_Test_de_simultaneite.ino dans l’ATmega328, observez le déroulement du programme et surtout décortiquez son écriture. Enfin, il faut transposer le rapport calculé entre Capacité théorique et Capacité actuelle pour que 100% corresponde à 16 caractères, c’est à dire 16 x 6 = 80 colonnes élémentaires. Le démonstrateur P05_Rampe analogique.ino facilite l’analyse logicielle. Initialement la ligne du haut devait contenir le texte « Capacité« , donc les caractères spéciaux « p » et « é » devaient être disponibles simultanément avec les pavés géométriques. Le texte définitif adopté montre sur la Fig.60 D qu’il faut le « à ». Pour obtenir la simultanéité, l’ordre décrit sur la Fig.62 permet un affichage correct, car  changer la police de caractères spéciaux n’écrase dans les cellules de matrices de l’afficheur que les cinq premiers.

La suite est ici.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *