Accueil > Arduino > Thermomètre coloré
samedi 1er octobre 2016, par
Avec un capteur de température et une led RGB il est possible de créer un thermomètre qui indique la température par une couleur.
Ici le capteur est une thermistance Rth de 10k à 25°C placée dans un pont diviseur avec R8=R25=10k (Rth à 25°C).
Le pont n’est alimenté qu’un court instant pendant la mesure pour éviter l’auto-échauffement de la thermistance.
Tout d’abord il faut pré-calculer pour chaque valeur adc fournie par le convertisseur analogique numérique (de 0 à 1023) la valeur de la température t correspondante.
De adc on déduit V, puis V donne R, puis par la loi R(T(K)) de la thermistance on obtient T et enfin t par t=273.15 + T. On peut montrer que :
La valeur de B est donnée dans la documentation de la thermistance (ici B = 3977K pour une RTC Vishay NTCLG100E2 10k)
Le calcul est fait pour chaque valeur adc possible et les résultats en dixième de °C sont placés dans un tableau en mémoire flash (attribut PROGMEM) :
const int16_t TempLookUpTable[] PROGMEM = { ERR_HI,ERR_HI,ERR_HI,ERR_HI,ERR_HI,ERR_HI,ERR_HI,1950,1885,1829,1779,1734,1694,1657,1624,1593,1564,1537,1512,..................................................................., -347,-351,-355,-360,-365,-369,-374,-379,-384,-390,-395,-401,-407,-413,-419, -426,-433,-440,-448,-456,-465,-474,-483,-493,ERR_LOW,ERR_LOW,ERR_LOW,ERR_LOW };
Deux constantes ERR_HI et ERR_LOW sont définies pour les valeurs hors spécifications de la thermistance (inférieures à -50° ou supérieures à 200°C).
On pourra ainsi avoir directement accès à la température à partir de la conversion analogique/numérique adc en lisant le tableau flash par la fonction
pgm_read_word_near(&TempLookUpTable[adc]);
D’où le code de la fonction de lecture de la température :
// return thermistor temperature in 0.1°c int16_t readTemp(){ digitalWrite(THERM_PWR,1); // apply power delay(50); // wait for voltage to stabilise uint16_t adc = analogRead(THERM_ANA); // read thermistor voltage digitalWrite(THERM_PWR,0); // remove power // return temperature in celsius by reading look up table in flash memory return pgm_read_word_near(&TempLookUpTable[adc]); }
La couleur de la led RGB se commande en fonction des courants moyens dans chacune des led individuelles. On peut faire varier ces courants moyen par un signal pwm de fréquence assez rapide pour que l’œil fasse la moyenne.
Red,Green,Blue sont les valeurs relatives des intensités r,g,b entre 0 et 1.
Il faut les ramener entre 0 et 255 pour la fonction analogWrite qui travaille sur 8 bits.
La variable Value permet de faire varier facilement la luminosité globale.
float Red,Green,Blue; // color in rgb space (range 0..1) float Value; // Value 0..1 analogWrite(RED,255*Red*Value); analogWrite(GREEN,255*Green*Value); analogWrite(BLUE,255*Blue*Value);
Le système r,g,b n’est pas bien adapté pour cela. En effet une "couleur" peut correspondre a plusieurs valeurs relative de r,g,b en fonction de la luminosité.
Il n’existe pas en r,g,b une relation mathématique simple en la couleur et les valeurs r,g,b. Il est plus commode d’utiliser le système H,S,V
H est la teinte (hue) c’est un angle en degré selon le cercle chromatique :
S est la saturation. Une couleur vive ou pure a une saturation proche de 1. Une couleur pastel ou délavée à une faible saturation.
V est la valeur. C’est l’intensité globale de la lumière.
Dans le système H,S,V il est très commode de "mapper" une couleur sur une valeur scalaire. Par exemple linéairement avec le bleu 240° correspondant au froid 10°C et le rouge 0° correspondant au chaud 30°C, on aurait :
H = 240 + (t - 10) x (0 - 240)/(30-10)
(attention ici H diminue quand t augmente)
C’est ce que fait la fonction map dans le code :
// map temperature to color Hue = map(t,T_BLUE,T_RED,BLUE_HUE,RED_HUE);
Il faut prévoir les cas hors de ces limites de température. En dessous de 10°C on restera au bleu et au dessus de 30°C on pourra "dé-saturer" la couleur pour aller vers le blanc.
if (Hue < RED_HUE) { // decrease saturation to have white after red Saturation = 1 + Hue / 500 ; // adjust to match your preference Hue = 0; if (Saturation < 0) Saturation = 0; } else if (Hue > BLUE_HUE) { Hue = BLUE_HUE; Saturation = 1; } else Saturation = 1;
Ensuite il suffit de repasser dans le système RGB pour piloter la led.
Les formules de conversion se trouvent ici :
[https://fr.wikipedia.org/wiki/Teinte_Saturation_Valeur]
Une fonction cpp de conversion est disponible ici :
[https://gist.github.com/fairlight1337/4935ae72bcbcc1ba5c72]
// Convert to RGB HSVtoRGB(Red,Green,Blue,Hue,Saturation,Value);
Le code arduino complet est disponible ici :
[http://arlotto.univ-tln.fr/ressources/er/s1_2016-2017/coloredThermo1.0.zip]
Il y a deux fichiers un pour le programme et l’autre pour la table de conversion.
Il faudra modifier les constantes pour s’adapter à votre câblage et à vos préférences.
// RGB LED pins
#define RED 3
#define BLUE 6
#define GREEN 5
// global led brightness 0 to 1
#define LED_BRIGHTNESS 0.4
// thermistor pins
#define THERM_ANA A0 // thermistor voltage
#define THERM_PWR 2 // thermistor brigde power
// Adjsut temperature interval to match to your preference
#define T_RED 290 // x0.1°C
#define T_BLUE 255