La bibliothèque Gauge_asukiaaa offre une solution de conversion de valeurs précise et efficace pour les systèmes embarqués, ciblant spécifiquement les interfaces utilisateur de type tableau de bord (gauges). Son objectif principal n'est pas le traitement de signal généraliste, mais la transformation de lectures de capteurs brutes en positions d'affichage pour des indicateurs analogiques ou numériques, comme des aiguilles de compteurs, des barres de progression LED ou des affichages OLED/TFT. Conçue pour des microcontrôleurs à ressources limitées tels que l'ATmega328P (Arduino Uno), l'ESP32 ou les STM32F1/F4, cette bibliothèque se distingue par son utilisation exclusive de l'arithmétique entière, évitant ainsi le recours à une unité de calcul en virgule flottante (FPU).
Le projet vise à offrir la meilleure fidélité d'affichage avec un encombrement code minimal. Il permet de définir des relations de mappage non linéaires à partir de quelques points d'échantillonnage discrets, améliorant significativement la précision visuelle des lectures de capteurs sur un cadran sans nécessiter d'outils de calibrage externes. Le nom Gauge_asukiaaa combine l'application principale ("Gauge" pour jauge/indicateur) avec l'identifiant de l'auteur ("asukiaaa"), une pratique courante dans la communauté Arduino. Distribuée sous licence MIT, elle garantit une intégration libre dans des projets commerciaux ou open source.
Pourquoi une interpolation par segments est-elle nécessaire plutôt qu'un simple mappage linéaire ?
La fonction map() traditionnelle, couramment utilisée dans l'écosystème Arduino, effectue un mappage strictement linéaire :
int valeur_lineaire = map(valeur_brute, min_brute, max_brute, min_cadran, max_cadran);
Cette approche est souvent insuffisante et introduit des distorsions importantes dans plusieurs situations :
- Réponse non linéaire des capteurs : Les capteurs tels que les thermistances CTP (Coefficient de Température Négatif) présentent une courbe de résistance-température exponentielle, où la même variation de résistance ne correspond pas à la même variation de température à différentes plages.
- Réponse mécanique non linéaire : Les instruments mécaniques peuvent ne pas avoir une relation strictement proportionnelle entre le courant de commande et l'angle de déviation de l'aiguille, en raison des propriétés du ressort, de la saturation magnétique, etc.
- Perception humaine non linéaire : Notre perception visuelle d'un même incrément physique peut être plus sensible dans les zones denses d'une échelle (par exemple, de 0 à 10%) que dans les zones plus espacées (de 90 à 100%).
Pour contrer ces limitations, Gauge_asukiaaa utilise une approche d'interpolation linéaire par segments (Piecewise Linear Interpolation - PLI). Le principe consiste à définir une série de "points de contrôle" (couples entrée-sortie) qui délimitent des segments, et à interpoler linéairement entre ces points. Pour un segment donné entre les points (X_i, Y_i) et (X_{i+1}, Y_{i+1}), la valeur de sortie Y pour une entrée X est calculée par :
Y = Y_i + (X - X_i) * (Y_{i+1} - Y_i) / (X_{i+1} - X_i)
Une optimisation clé de cette bibliothèque est le précalcul des pentes ((Y_{i+1} - Y_i) / (X_{i+1} - X_i)) pour chaque segment sous forme de rapports entiers. Cela évite les divisions coûteuses en temps réel et les opérations en virgule flottante, rendant la solution extrêmement performante et adaptée aux microcontrôleurs.
Définition pratique des points de contrôle
La bibliothèque nécessite au moins trois points de contrôle pour former un minimum de deux segments. La configuration de ces points est cruciale pour obtenir un mappage précis. Voici un exemple typique de configuration pour un capteur ADC vers une échelle de 0 à 100 :
| Valeur d'entrée (capteur brut) | Valeur de sortie (affichage) | Description |
|---|---|---|
| 0 | 0 | Point de référence bas (calibrage du zéro) |
| 512 | 50 | Point intermédiaire |
| 1023 | 100 | Point de pleine échelle (valeur maximale de l'ADC) |
Avec cette configuration, deux segments de mappage linéaire sont définis :
- De
[0, 512]vers[0, 50] - De
[512, 1023]vers[50, 100]
Pour des capteurs ayant des réponses très non linéaires, comme une thermistance NTC où la résistance change rapidement à basse température, il est possible d'ajouter plus de points de contrôle dans les plages critiques afin d'améliorer la résolution et la précision. Par exemple, pour une plage de basse température :
// Points de contrôle pour une haute résolution dans la plage de basse température
// (valeur_ADC, température_en_°C)
PointMappage pointsTemp[] = {
{ .valEntree = 0, .valSortie = -40 }, // -40°C
{ .valEntree = 12, .valSortie = -35 }, // -35°C (delta_x=12, delta_y=5)
{ .valEntree = 38, .valSortie = -30 }, // -30°C (delta_x=26, delta_y=5)
// ... d'autres points pour couvrir toute la plage
};
Dans cet exemple, les pentes des segments s'adapteront automatiquement : le premier segment aura une pente effective de 5/12 ≈ 0.417, et le second de 5/26 ≈ 0.192. Cela garantit qu'une petite variation de température dans cette zone sera traduite par un mouvement d'aiguille suffisant sur le cadran.
Structures de données fondamentales
La bibliothèque s'appuie sur des structures de données simples pour gérer les points de contrôle. Typiquement, une structure C serait définie pour encapsuler un couple entrée-sortie :
// Structure représentant un point de mappage (entrée, sortie)
typedef struct {
int32_t valEntree; // Valeur d'entrée brute (ex: lecture ADC)
int32_t valSortie; // Valeur de sortie mappée (ex: position cadran, pourcentage)
} PointMappage;
Ces structures sont ensuite regroupées dans un tableau ou une liste, et la logique interne de la bibliothèque parcourt ces points pour trouver le segment approprié et effectuer l'interpolation pour toute valeur d'entrée.