
Bonjour à tous!
L'hiver est venu, et avec lui la tâche est de vérifier les propriétés d'isolation thermique des
bâtiments de la résidence de campagne de la datcha. Et puis il s'est avéré que sur le site chinois bien connu apparaissaient des modules d'imagerie thermique assez abordables. Est-il possible d'assembler une chose exotique et peut-être même utile - un imageur thermique fait maison? Pourquoi pas, comme la framboise gisait quelque part ...
MLX90640. Qu'est ce que c'est
Et cela, en fait, est une matrice d'imagerie thermique avec un microcontrôleur à bord. Production de la société Melexis jusque-là inconnue. La matrice d'imagerie thermique a une dimension de 32 par 24 pixels. Ce n'est pas beaucoup, mais lors de l'interpolation de l'image, cela semble suffisant pour au moins distinguer quelque chose.

Le capteur est disponible en deux versions, dont les cas diffèrent par l'angle de vue de la matrice. Une structure plus trapue A surplombe le monde extérieur sous un angle de 110 (horizontal) à 75 degrés (vertical). B - moins de 55 par 37,5 degrés, respectivement. Le boîtier de l'appareil n'a que quatre sorties - deux pour l'alimentation, deux pour communiquer avec le dispositif de contrôle via l'interface I2C. Les fiches techniques intéressées peuvent être téléchargées
ici .
Et puis qu'est-ce que le GY-MCU90640?
Des camarades chinois ont embarqué le MLX90640 avec un autre microcontrôleur (STM32F103). Apparemment, pour une gestion plus facile de la matrice. Toute cette ferme s'appelle GY-MCU90640. Et cela coûte au moment de l'acquisition (fin décembre 2018) dans la région de 5 mille roubles. Cela ressemble à ceci:

Comme vous pouvez le voir, il existe deux types de cartes, avec une version étroite ou grand angle du capteur à bord.
Quelle version vous convient le mieux? Une bonne question, malheureusement, je ne l'ai eu qu'après que le module a déjà été commandé et reçu. Pour une raison quelconque, au moment de la commande, je n'ai pas prêté attention à ces nuances. Mais en vain.
Une version plus large conviendra aux robots automoteurs ou aux systèmes de sécurité (le champ de vision sera plus large). Selon la fiche technique, il a également moins de bruit et une plus grande précision de mesure.

Mais pour les tâches de visualisation, je préférerais plutôt une version plus «longue portée» de B. Pour une raison très importante. À l'avenir, lors de la prise de vue, il peut être déployé (manuellement ou sur une plate-forme avec un lecteur) et prendre des "photos" composites, augmentant ainsi la résolution plus qu'une modeste de 32 par 24 pixels. Collectez des images thermiques de 64 par 96 pixels, par exemple ... Eh bien, d'accord, à l'avenir, les photos proviendront de la version grand angle A.
Se connecter à Raspberry PI
Il existe deux façons de contrôler le module d'imagerie thermique:
- Raccourcissez le cavalier «SET» sur la carte et utilisez I2C pour contacter directement le microcontrôleur interne MLX90640.
- Laissez le cavalier tranquille et communiquez avec le module via une interface similaire installée sur la carte STM32F103 via RS-232.
Si vous écrivez en C ++, il sera probablement plus pratique d'ignorer le microcontrôleur supplémentaire, de court-circuiter le cavalier et d'utiliser l'API du fabricant, qui se trouve
ici .
Les humbles pythonistes peuvent également faire le premier pas. Il semble qu'il y ait quelques bibliothèques Python (
ici et
ici ). Mais malheureusement, pas un seul n'a fonctionné pour moi.
Les pythonistes avancés peuvent essentiellement écrire un pilote de contrôle de module en Python. La procédure d'obtention d'un cadre est décrite en détail dans la fiche technique. Mais ensuite, vous devrez prescrire toutes les procédures d'étalonnage, ce qui semble légèrement contraignant. Par conséquent, j'ai dû emprunter la deuxième voie. Il s'est avéré être modérément épineux, mais tout à fait passable.
Grâce à la perspicacité des ingénieurs chinois ou simplement à une heureuse coïncidence, le châle s'est avéré avoir une très bonne localisation des conclusions:

Il ne reste plus qu'à mettre le bloc et insérer l'écharpe dans le connecteur framboise. Un convertisseur de 5 à 3 volts est installé sur la carte, il semble donc que rien ne menace les délicates sorties Rx et Tx de Raspberry.
Il convient d'ajouter que la connexion selon la première option est également possible, mais nécessite plus de main-d'œuvre et de compétences en soudure. La carte doit être installée de l'autre côté du connecteur Raspberry (montré dans la photo de titre de cet article).
Logiciels
Sur un site chinois bien connu, un tel miracle est proposé pour accéder au GY-MCU90640:

Apparemment, il devrait y avoir une description du protocole d'interaction avec le microcontrôleur installé sur la carte, selon lequel ce produit logiciel fonctionne! Après une brève conversation avec le vendeur de foulards (respect à ces messieurs respectés), un tel protocole m'a été envoyé. Il est apparu en pdf et en chinois pur.
Grâce au traducteur de Google et au copier-coller actif, le protocole a été décrypté en environ une heure et demie, et tout le monde peut le lire sur
Github . Il s'est avéré que l'écharpe comprend six commandes de base, parmi lesquelles une demande de trame sur le port COM.
Chaque pixel de la matrice est, en fait, la valeur de température de l'objet que ce pixel regarde. Température en degrés Celsius multipliée par 100 (nombre à deux octets). En fait, il existe même un mode spécial dans lequel l'écharpe enverra des images de la matrice au Raspberry 4 fois par seconde.
Le script pour obtenir des images thermiques ici:"""MIT License
Copyright (c) 2019
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE."""
import serial, time
import datetime as dt
import numpy as np
import cv2
# function to get Emissivity from MCU
def get_emissivity():
ser.write(serial.to_bytes([0xA5,0x55,0x01,0xFB]))
read = ser.read(4)
return read[2]/100
# function to get temperatures from MCU (Celsius degrees x 100)
def get_temp_array(d):
# getting ambient temperature
T_a = (int(d[1540]) + int(d[1541])*256)/100
# getting raw array of pixels temperature
raw_data = d[4:1540]
T_array = np.frombuffer(raw_data, dtype=np.int16)
return T_a, T_array
# function to convert temperatures to pixels on image
def td_to_image(f):
norm = np.uint8((f/100 - Tmin)*255/(Tmax-Tmin))
norm.shape = (24,32)
return norm
########################### Main cycle #################################
# Color map range
Tmax = 40
Tmin = 20
print ('Configuring Serial port')
ser = serial.Serial ('/dev/serial0')
ser.baudrate = 115200
# set frequency of module to 4 Hz
ser.write(serial.to_bytes([0xA5,0x25,0x01,0xCB]))
time.sleep(0.1)
# Starting automatic data colection
ser.write(serial.to_bytes([0xA5,0x35,0x02,0xDC]))
t0 = time.time()
try:
while True:
# waiting for data frame
data = ser.read(1544)
# The data is ready, let's handle it!
Ta, temp_array = get_temp_array(data)
ta_img = td_to_image(temp_array)
# Image processing
img = cv2.applyColorMap(ta_img, cv2.COLORMAP_JET)
img = cv2.resize(img, (320,240), interpolation = cv2.INTER_CUBIC)
img = cv2.flip(img, 1)
text = 'Tmin = {:+.1f} Tmax = {:+.1f} FPS = {:.2f}'.format(temp_array.min()/100, temp_array.max()/100, 1/(time.time() - t0))
cv2.putText(img, text, (5, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 0), 1)
cv2.imshow('Output', img)
# if 's' is pressed - saving of picture
key = cv2.waitKey(1) & 0xFF
if key == ord("s"):
fname = 'pic_' + dt.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + '.jpg'
cv2.imwrite(fname, img)
print('Saving image ', fname)
t0 = time.time()
except KeyboardInterrupt:
# to terminate the cycle
ser.write(serial.to_bytes([0xA5,0x35,0x01,0xDB]))
ser.close()
cv2.destroyAllWindows()
print(' Stopped')
# just in case
ser.close()
cv2.destroyAllWindows()
, Raspberry PI, 4 . , . OpenCV. «s» « » jpg.

. , . — . 20 40 . Ctrl + C.

Raspberry Pi Zero W Pi 3 B+. VNC . , , powerbank' VNC . , , .
. .
, , . . , . - , .
!
UPD: . . - , , . . — .

. +20...+40 -10...+5.