L'objectif de ce tutoriel est de réaliser des photos thermiques à partir d'un capteur de température infrarouge et d'une led RGB.
Le capteur transmet la température à la carte Arduino qui va allumer la led d'une couleur correspondant à la température : plus c'est rouge plus c'est chaud, plus c'est bleu plus c'est froid. En utilisant la méthode du "light-painting", on peut ensuite réaliser une photo où seront colorées les zones en fonction de la température.
Je vais développer ce tutoriel pas à pas, de la même façon que j'ai appris à le réaliser. Je pense que sa réalisation est assez simple, mais il est nécessaire d’avoir déjà expérimenté un premier montage Arduino. Je ne détaillerai pas les étapes d’installation de pilote et du logiciel Arduino qui sont déjà largement expliqué sur Google.
Vous êtes prêts ? Allez, c’est parti !
Budget : Non défini
Pour ce projet on utilise le capteur MLX90614, qui est un capteur infrarouge sans contact qui permet de mesurer la température ambiante (-40 à +85 °C) et la température d’un objet (-70 à +380 °C)
Sur mon schéma, le capteur est alimenté en 3.3V, mais il existe également une version 5V. Pour vérifier la tension de votre capteur, il faut regarder les 3 lettres gravées sur son boitier. Si la première lettre est A, c’est la version 5V. Si c’est un B, c’est la version 3V
Pour communiquer avec le capteur, il existe une bibliothèque Arduino disponible à cette adresse : https://github.com/adafruit/Adafruit-MLX90614-Library. Pour l’installer, il faut placer les fichiers du Github dans mondossierarduino/libraires/Adafruit-MLX90614 puis redémarrer l’IDE.
Cette bibliothèque permet de récupérer la température ambiante, ainsi que la température de ce qui se trouve en face du capteur. C’est cette température qui nous intéresse. On peut alors exécuter ce code :
#include <Adafruit_MLX90614.h> Adafruit_MLX90614 mlx = Adafruit_MLX90614(); void setup() { Serial.begin(9600); mlx.begin(); } void loop() { // Lecture de la température ambiante Serial.print("Ambiant = "); Serial.print(mlx.readAmbientTempC()); Serial.println("*C"); // Lecture de la température de l'objet Serial.print("Objet = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C"); Serial.println(); delay(1000); }
Source : https://learn.adafruit.com/using-melexis-mlx90614-non-contact-sensors/wiring-and-test
Fichiers :
Arduino Uno R3 - 19.50 € - http://www.gotronic.fr/art-carte-arduino-uno-12420.htm
Capteur MLX90614 - 21.90 € - http://www.gotronic.fr/art-capteur-de-t-ir-mlx90614-20721.htm
Led RGB 5 mm (boitier diffusant) - 0.90 € - http://www.gotronic.fr/art-led-rgb-5-mm-l5rvb-c-20753.htm
Ecran LCD 2X16 - 7.50 € - http://boutique.semageek.com/fr/142-afficheur-alphanumérique-lcd-2x16-rétro-éclairé-bleu.html
Encodeur rotatif avec validation - 5.40€ - http://boutique.semageek.com/fr/896-encodeur-rotatif-24-positions-avec-validation-knob.html
Plaque de montage rapide - 4.50 € - http://www.gotronic.fr/art-plaque-de-montage-rapide-22812.htm
Résistances - http://www.gotronic.fr/cat-resistances-372.htm
Condensateur 100 nF - 0.20 € - http://www.gotronic.fr/art-condensateur-ceramique-100-nf-3215.htm
Fils de câblage (attention, la section 0.20 mm² flotte dans les pins Arduino) - http://www.gotronic.fr/cat-fil-de-cablage-950.htm
Potentiomètre 10kΩ - http://www.gotronic.fr/cat-potentiometres-263.htm
Boitier SA400 - 3.65 € - https://www.gotronic.fr/art-coffret-sa400-6151.htm
Support de Led - 0.85 € - http://www.gotronic.fr/art-support-5-mm-e501ch-2222.htm
Pile 9V - 3.20 € - http://www.gotronic.fr/art-pile-alcaline-9v-varta-19146.htm
Cordon d’alimentation - 2 € - http://www.gotronic.fr/art-cordon-alimentation-pile-9v-19414.htm
Interrupteur - 0.60 € - http://www.gotronic.fr/art-interrupteur-ti3-4167.htm
Budget total : 70 €
Nous allons maintenant allumer une LED RGB dont la couleur varie selon la température. La LED sera bleue si la température est froide, et rouge si la température est chaude.
La couleur de la LED sera définie en utilisant le modèle de couleurs TSV (Teinte Saturation Valeur) :
Dans notre cas, la saturation et la valeur resteront fixes à 100% et seule la teinte varie. Pour obtenir la teinte voulue en fonction de la température, nous allons ré-étalonner la température d’une échelle fixée (par exemple -25°C vers +75°C) vers une échelle de teinte (240° - bleu vers 0° - rouge) :
Une fois la couleur obtenue, il faut l’appliquer à notre LED. Le modèle TSV nous était utile puisqu’il permettait de ne modifier que la composante de teinte. Mais notre LED RGB fonctionne en appliquant 3 tensions sur les couleurs rouge verte et bleu. On va donc convertir notre couleur vers le modèle … RGB. La LED que j’utilise est à cathode commune, c’est-à-dire que la broche (-) est commune aux 3 couleurs. Une LED à anode commune est aussi utilisable. Choisissez de préférence un boitier diffusant plutôt qu’un boitier transparent, il permet une meilleure homogénéité de la couleur.
La LED doit être associée à des résistances de limitation de courant. Pour connaitre la valeur des résistances à utiliser, il faut connaitre les tensions de seuil de la LED, fournies par le constructeur. Dans mon cas, il est indiqué :
Caractéristiques sous 20 mA: Rouge: - tension: 2 V - longueur d'onde: 623 nm - éclairement: 2800 mcd Verte: - tension: 3,2 V - longueur d'onde: 521 nm - éclairement: 6500 mcd Bleue: - tension: 3,2 V - longueur d'onde: 466 nm - éclairement: 1200 mcd
On applique la loi R = (Uarduino – Uled) / I, où Uarduino = 3.3V et I = 0.02A.
Ce qui nous donne :
Si la valeur trouvée n’est pas standard, on choisit la valeur standard supérieure la plus proche. J’ai donc choisi 100 ohms et 10 ohms.
Je précise également qu’il est indispensable de placer les 3 broches de la LED sur des sorties PWM de l’Arduino. Ces sorties sont indiquées par un tilde (~) à côté du numéro de sortie. Elles permettent d’appliquer une tension variable, pendant qu’une sortie classique fonctionne en tout ou rien. J’ai choisi les sorties 9,10 et 11.
Le nouveau code devient :
#include <Wire.h> #include <Adafruit_MLX90614.h> Adafruit_MLX90614 mlx = Adafruit_MLX90614(); void setup() { Serial.begin(9600); mlx.begin(); // Initialisation de la LED pinMode(9, OUTPUT); // Bleu pinMode(10, OUTPUT); // Vert pinMode(11, OUTPUT); // Rouge } void loop() { // Lecture de la température float celsius = mlx.readObjectTempC(); // Re-etalonnage de la plage de temperature vers la plage de teinte const float lowTemp = 10.0; // Temperature min (bleu) const float highTemp = 30.0; // Temperature max (rouge) const float lowHue = 240.0; // Couleur min (bleu) const float highHue = 0; // Couleur max (rouge) celsius = constrain(celsius, lowTemp, highTemp); float hue = fmap(celsius, lowTemp, highTemp, lowHue, highHue); // Modification de la couleur de la LED float r, g, b; HSVtoRGB(&r, &g, &b, hue, 1, 1); setLeds(r * 255, g * 255, b * 255); } /** Applique les tensions sur les 3 broches de la LED */ void setLeds(byte r, byte g, byte b) { // LED à anode commune //analogWrite(9, 255 - b); //analogWrite(10, 255 - g); //analogWrite(11, 255 - r); // LED à cathode commune analogWrite(9, b); analogWrite(10, g); analogWrite(11, r); } /** Version float de la fonction Map */ float fmap(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } /** Converti le modele de couleur HSV vers le modele RGB. Source : http://www.cs.rit.edu/~ncs/color/t_convert.html */ void HSVtoRGB(float *r, float *g, float *b, float h, float s, float v) { int i; float f, p, q, t; if( s == 0 ) { *r = *g = *b = v; return; } h /= 60; i = floor(h); f = h - i; p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * ( 1 - f )); switch(i) { case 0: *r = v; *g = t; *b = p; break; case 1: *r = q; *g = v; *b = p; break; case 2: *r = p; *g = v; *b = t; break; case 3: *r = p; *g = q; *b = v; break; case 4: *r = t; *g = p; *b = v; break; default: *r = v; *g = p; *b = q; break; } }
En l’état, le projet peut s’arrêter ici. En utilisant la méthode du light painting, nous pouvons réaliser des photos où les zones sont colorées en fonction de la température (voir la dernière étape). Mais il peut être intéressant d’avoir un écran qui affiche la température, et permettre de modifier les seuils minimum et maximum de température sans modifier le code. C’est ce que nous allons voir dans la suite de ce tutoriel.
Source : https://publiclab.org/notes/ad/11-28-2011/thermal-camera-arduino-uno-mlx90614-ir-thermometer
https://skyduino.wordpress.com/2013/11/02/arduino-light-painting-et-capteur-de-temperature-humm/
Fichiers :
Nous allons utiliser un afficheur alphanumérique LCD de 2 lignes de 16 caractères. Les écrans compatibles avec la bibliothèque Arduino sont reconnaissables par leurs 16 broches que je vais brièvement décrire :
N° Nom Rôle
1 VSS Masse
2 Vdd +5V
3 V0 Réglage du contraste
4 RS Sélection du registre (commande ou donnée)
5 R/W Lecture ou écriture
6 E Entrée de validation
7 à 10 D0 à D3 Bits de données de poids fort
11 à 14 D4 à D7 Bits de données de poids faible
15 LED+ Anode du rétroéclairage (+5V)
16 LED- Cathode du rétroéclairage (masse)
Il existe 2 façons de pilote l’écran. Soit en utilisant les 16 connexions (mode 8 bits), soit en utilisant 4 connexions de moins (mode 4 bits). Le mode 4 bits, malgré qu’il soit plus lent, a l’avantage d’être plus simple et moins gourmand en pins. Comme nous n’avons pas besoin de changement d’information rapide, nous allons utiliser ce mode.
On reprend le tableau précédent et je vous explique où brancher vos broches :
N° Nom Rôle
1 VSS Masse générale du montage
2 Vdd +5V de l’Arduino
3 V0 Broche centrale du potentiomètre 10K
4 RS Pin 12 de l’Arduino
5 R/W Comme nous allons uniquement écrire sur l’écran, à relier à la masse
6 E Pin 13 de l’Arduino
7 à 10 D0 à D3 Comme nous utilisons le mode 4 bits, à la relier à la masse
11 à 14 D4 à D7 Pins 7,6,5 et 4 de l’Arduino. Oui, dans cet ordre
15 LED+ +5V de l’Arduino
16 LED- Masse générale du montage
Ça commence à faire beaucoup de fil tout ça ! La boite qui devait contenir le projet devait être plus petite, c’est pour ça que j’ai directement soudé les fils sur l’écran comme un malpropre. Mais sachez qu’il existe des connecteurs pour rendre votre montage moins définitif : https://www.gotronic.fr/art-connecteur-he14-mh100-4457.htm
Côté code, nous allons utiliser la librairie LiquidCrystal qui va nous simplifier la vie pour dialoguer avec l’écran. Pour l’installer dans l’IDE, il faut se rendre dans Croquis > Inclure une bibliothèque > Gérer les bibliothèques. Dans la barre de rechercher, chercher « LiquidCrystal ». Si la biliothèque est déjà installé, il est indiqué « INSTALLED » à côté de son nom, sinon il y a un bouton pour l’installer.
On peut lancer le code d’essai de l’écran :
#include <LiquidCrystal.h> LiquidCrystal lcd(12,13,7,6,5,4); // (RS, E, d4, d5, d6, d7) void setup() { lcd.begin(16,2); //on initialise la communication avec 16 colonnes et 2 lignes lcd.clear(); // on efface l'écran lcd.print("Oui are"); // on écrit la premiere ligne lcd.setCursor(0,1); //on passe à la ligne suivante lcd.print("Makers"); // on écrit la deuxieme ligne } void loop() { }
En soit, ce n’est pas super utile d’afficher un texte fixe sur un écran. Nous allons alors afficher la température en mélangeant ce code avec celui de l’étape 1 :
#include <Adafruit_MLX90614.h> #include <LiquidCrystal.h> Adafruit_MLX90614 mlx = Adafruit_MLX90614(); LiquidCrystal lcd(12,13,7,6,5,4); // (RS, E, d4, d5, d6, d7) void setup() { Serial.begin(9600); mlx.begin(); lcd.begin(16,2); // 16 colonnes et 2 lignes lcd.clear(); // On efface l'écran lcd.print(F("Temperature :")); // On écrit sur la 1ere ligne } void loop() { /* Affichage de la température */ lcd.setCursor(0,1); // On se place au debut de la 2eme ligne lcd.print(mlx.readObjectTempC()); lcd.print(" "); lcd.write(178); // Astuce pour afficher ° lcd.print("C"); /* Temps d'attente */ delay(1000); }
Source : https://openclassrooms.com/courses/perfectionnez-vous-dans-la-programmation-arduino/programmez-un-ecran-lcd
http://eskimon.fr/26-arduino-701-les-ecrans-lcd
Fichiers :
Pour pouvoir naviguer dans le menu, nous allons utiliser un encodeur rotatif. Cette petite bête ressemble à un potentiomètre qui ne possède pas de fin. En le tournant, on peut ressentir des crans, qui seront interprétées par l’Arduino par un +1 ou -1.
Comme je suis fainéant, je me vais me servir une fois de plus d’une librairie existante pour que l’Arduino puisse comprendre les mouvements de rotation de l’encodeur : https://github.com/brianlow/Rotary
Pour ceux du fond qui dormaient pendant la 1ère étape, pour l’installer, il faut placer les fichiers du Github dans mondossierarduino/libraires/Rotary puis redémarrer l’IDE.
La librairie possède 2 méthodes pour capturer les evenements : Polling ou Interrupt :
Mais il faut savoir que tous les pins de l’Arduino ne disposent pas de cette fonction d’interruption, seulement les pins 2 et 3 dans le cas de l’Arduino UNO. Ça tombe bien, ils sont encore disponibles dans notre projet, quel hasard !
Avec ce bout de code, nous affichons « +1 » pour une rotation dans le sens horaire, et « -1 » pour une rotation dans le sens anti-horaire :
#include <Rotary.h> Rotary r = Rotary(2, 3); void setup() { Serial.begin(9600); // Declaration de l'encodeur PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); } void loop() { } /** Fonction appelée au mouvement de l'encodeur */ ISR(PCINT2_vect) { unsigned char result = r.process(); if (result == DIR_CW) { Serial.println("+1"); } else if (result == DIR_CCW) { Serial.println("-1"); } }
L’encodeur dispose également d’un bouton poussoir qui est câblé indépendamment comme n’importe quel bouton. Il y a 3 manières de connecter un bouton sur l’Arduino :
Allez, on ajoute ce bout de code qui indique l’état du bouton en plus de l’état de l’encodeur :
#include <Rotary.h> Rotary r = Rotary(2, 3); // L'encodeur est sur les pins 2 et 3 int pinBouton = 8; // Le bouton est sur le pin 8 boolean etatBouton = 0; // Sauvegarde du dernier etat du bouton void setup() { Serial.begin(9600); // Declaration de l'encodeur PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); // Declaration du bouton en mode pullup pinMode(pinBouton,INPUT_PULLUP); } void loop() { boolean etatBoutonTmp= !digitalRead(pinBouton); // ! puisque l'etat est inversé par rapport au bouton if (etatBoutonTmp != etatBouton) { etatBouton = etatBoutonTmp; Serial.println(etatBouton); // On affiche l'etat du bouton delay(5); // Corrige un bug etrange qui engendre des appuis non sollicites } } /** Fonction appelée au mouvement de l'encodeur */ ISR(PCINT2_vect) { unsigned char result = r.process(); if (result == DIR_CW) { Serial.println("+1"); } else if (result == DIR_CCW) { Serial.println("-1"); } }
Source :
https://github.com/brianlow/Rotary
https://community.nxp.com/thread/29262
http://simple-duino.com/interruption-et-arduino/
https://openclassrooms.com/courses/programmez-vos-premiers-montages-avec-arduino/le-bouton-poussoir
Fichiers :
Pour résumer, nous avons réussi à faire fonctionner un capteur de température, une LED de couleur, un écran LCD et un encodeur numérique. Maintenant il faut les faire fonctionner tous ensemble.
L’écran et l’encodeur vont nous permettre de créer un menu. Il y aura 4 étapes :
Le code étant un peu longuet, je le place uniquement dans les fichiers techniques.
Il nous reste plus qu’à positionner tous ces éléments dans le boitier. Celui que j’ai indiqué dans la partie matériel est assez grand pour tout contenir, et assez haut pour que les fils ne soient pas écrasés (200 x 130x 45 cm). Je vous conseille de monter les composants avant d’entamer le câblage final, de cette manière on peut plus facilement couper les fils à la bonne taille. En plaçant tous les éléments sur la même face, nous pouvons plus facilement câbler et fermer le boitier.
Pour créer un interrupteur, il faut sectionner un des 2 fils reliant la pile à l’arduino, pour les souder sur l’interrupteur. Un brin du fil est soudé sur la borne centrale, l’autre fil sur une des 2 autres bornes, sachant que l’interrupteur doit être positionné vers cette borne pour alimenter l’arduino.
Pour fixer le support de la LED, l’interrupteur et l’encodeur, il suffit de percer aux bons diamètres et de fixer les écrous. Le capteur de température n’ayant pas de support, j’ai percé un trou aux dimensions exactes du capteur pour le fixer par friction. Pour fixer l’écran, j’ai découpé à la Dremel un rectangle de la taille de l’écran, puis fixé les vis pour le maintenir. L’arduino, la breadboard et la pile sont maintenus par de l’adhésif double face, ce qui fait largement l’affaire.
Fichiers :
Avoir un boitier qui fait de la couleur c’est bien beau, mais ce qui nous intéresse c’est faire des photos thermiques. Les photos doivent être prises selon la méthode du Light Painting.
Ils existent trois réglages qui influent sur le rendu de la scène photographiée. La sensibilité (ISO), l’ouverture (F/) et le temps de pose. Les appareils photo proposent généralement la possibilité d’effectuer ces différents réglages. Si ce n’est pas votre cas, vous pouvez tenter l’expérience en utilisant le mode « Nuit » de votre appareil.
Sensibilité ISO
Le paramètre ISO correspond à la sensibilité du capteur. Plus il est haut, plus le capteur capte de lumière et donc plus l’image est lumineuse. Dans le cas du light painting, la sensibilité doit être basse (ISO 100-200) afin que le capteur de l’appareil photo soit moins sensible à la lumière permettant des scènes correctement exposées malgré le long temps de pose. Par ailleurs, plus la sensibilité est basse, moins le bruit est apparent sur la photographie.
Ouverture (F/)
L’ouverture correspond à l’ouverture du diaphragme de l’objectif. Plus il est ouvert, plus la lumière peut entrer dans l’appareil photo pour atteindre le capteur. Comme le temps de pose sera important, il est préférable d’ouvrir le diaphragme au minimum pour laisser passer le moins de lumière possible. La valeur F/ de l’ouverture est contraire à l’ouverture physique du diaphragme. Ainsi une grande ouverture sera par exemple de F/2.8 alors qu’une petite ouverture sera de l’ordre de F/16. Pour les photos ci-dessus, j’ai fermé à F/22.
Temps de pose
Lorsque l’on appuie sur le bouton pour déclencher la photo, l’appareil ouvre un clapet pour laisser entrer la lumière, et le referme à la fin de la photo. C’est le temps de pose. Ici, il nous faut un temps de pose relativement long pour avoir le temps de balayer la zone avec notre LED. Le temps de pose pourra durer quelques secondes pour une petite zone jusqu’à plusieurs minutes si l’on peint toute une pièce. La plupart des appareils photos ont un temps maximum de 30sec. Cependant, il existe le mode BULB qui est un mode manuel. Nous pouvons lancer la photo et l’arrêter une fois notre balayage terminé.
En premier lieu, il faut que l’appareil soit immobile pendant toute la photo. L’idéal est un trépied, qui permet de modifier l’angle de la photo, mais vous pouvez aussi le poser sur une surface stable.
Sur notre photo nous voulons voir une grande différence de couleur entre les températures. Grâce au mode qui affiche la température, nous allons pouvoir repérer la température exacte du point le plus chaud, et du point le plus froid. Ce sont les températures que nous allons régler sur les seuils min et max.
Avant la prise de photo, il sera utile d’éteindre les lumières ambiantes afin que les zones colorées ne soient pas surexposées à la lumière. Il est cependant possible d’avoir une légère lumière ambiante pour éclairer les alentours. Il ne reste plus qu’à enclencher la photo et d’aller peindre le sujet. Vous pouvez faire des balayages horizontaux ou verticaux, ou laissez libre cours à votre créativité.
Pour ce premier projet sur Arduino, je dois avouer que je suis assez content du résultat. Les photos obtenues permettent de distinguer facilement les zones de chaleur, et les couleurs sont vives sans nécessiter de retouche photo.
Il y a une petite amélioration possible, concernant l’écran LCD qui reste allumé pendant la photo. Il oblige d’orienter le boitier dans le bons sens pour ne pas que la lumière de l’écran soit capté par l’appareil photo. Cela peut se régler par un transistor qui active ou désactive l’alimentation de l’écran.
Merci de m’avoir lu jusqu’ici, et n’hésitez pas à me partager vos critiques et corrections en commentaire, voire même votre meilleure blague. N’ayant pas de réelle formation en électronique, je m’excuse d’avance auprès des pros de mes raccourcis et erreurs éventuelles.