DIY Wärmebildkamera auf Raspberry PI oder "Jetzt denke ich, ich weiß, was ich diesen Sommer tun werde"

Bild

Hallo allerseits!

Der Winter ist gekommen, und damit ist es die Aufgabe, die wärmeisolierenden Eigenschaften der Gebäude des Landsitzes der Datscha zu überprüfen. Und dann stellte sich heraus, dass auf der bekannten chinesischen Website recht erschwingliche Wärmebildmodule erschienen. Ist es möglich, eine exotische und möglicherweise sogar nützliche Sache zusammenzustellen - eine hausgemachte Wärmebildkamera? Warum nicht, als ob Raspberry irgendwo gelegen hätte ... Was dabei herausgekommen ist - ich werde es dir unter dem Schnitt sagen.

MLX90640. Was ist das?


Und dies ist in der Tat eine Wärmebildmatrix mit einem Mikrocontroller an Bord. Produktion der bisher unbekannten Firma Melexis. Die Wärmebildmatrix hat eine Abmessung von 32 x 24 Pixel. Das ist nicht viel, aber wenn man das Bild interpoliert, scheint es genug zu sein, um zumindest etwas zu erkennen.

Bild

Der Sensor ist in zwei Versionen erhältlich, deren Gehäuse sich im Betrachtungswinkel der Matrix unterscheiden. Eine gedrungenere Struktur A überblickt die Außenwelt in einem Winkel von 110 (horizontal) bei 75 (vertikal) Grad. B - unter 55 um 37,5 Grad. Das Gerätegehäuse verfügt nur über vier Ausgänge - zwei für die Stromversorgung und zwei für die Kommunikation mit dem Steuergerät über die I2C-Schnittstelle. Interessierte Datenblätter können hier heruntergeladen werden .

Und was ist dann der GY-MCU90640?


Chinesische Kameraden haben den MLX90640 mit einem weiteren Mikrocontroller (STM32F103) an Bord gebracht. Anscheinend zur einfacheren Matrixverwaltung. Diese ganze Farm heißt GY-MCU90640. Und es kostet zum Zeitpunkt der Akquisition (Ende Dezember 2018) in der Größenordnung von 5.000 Rubel. Es sieht so aus:

Bild

Wie Sie sehen können, gibt es zwei Arten von Platinen mit einer schmalen oder Weitwinkelversion des Sensors an Bord.

Welche Version passt am besten zu Ihnen? Eine gute Frage, leider hatte ich sie erst, nachdem das Modul bereits bestellt und erhalten wurde. Aus irgendeinem Grund habe ich diese Nuancen zum Zeitpunkt der Bestellung nicht beachtet. Aber vergebens.

Eine breitere Version eignet sich für selbstfahrende Roboter oder für Sicherheitssysteme (das Sichtfeld wird größer). Laut Datenblatt hat es auch weniger Rauschen und eine höhere Messgenauigkeit.

Bild

Für Visualisierungsaufgaben würde ich jedoch eher eine Version mit größerer Reichweite von B empfehlen. Aus einem sehr wichtigen Grund. Zukünftig kann es beim Aufnehmen bereitgestellt werden (manuell oder auf einer Plattform mit einem Laufwerk) und zusammengesetzte "Fotos" aufnehmen, wodurch die mehr als bescheidene Auflösung von 32 x 24 Pixel erhöht wird. Sammeln Sie beispielsweise Wärmebilder mit einer Größe von 64 x 96 Pixel ... Okay, in Zukunft werden die Fotos aus der Weitwinkelversion A stammen.

Stellen Sie eine Verbindung zu Raspberry PI her


Es gibt zwei Möglichkeiten, das Wärmebildmodul zu steuern:

  1. Kürzen Sie den SET-Jumper auf der Platine und verwenden Sie I2C, um den internen Mikrocontroller MLX90640 direkt zu kontaktieren.
  2. Lassen Sie den Jumper in Ruhe und kommunizieren Sie mit dem Modul über eine ähnliche Schnittstelle, die über RS-232 auf der STM32F103-Karte installiert ist.

Wenn Sie in C ++ schreiben, ist es wahrscheinlich bequemer, den zusätzlichen Mikrocontroller zu ignorieren, den Jumper kurzzuschließen und die API des Herstellers zu verwenden, die hier liegt.

Bescheidene Pythonisten können auch den ersten Weg gehen. Es scheint, als gäbe es ein paar Python-Bibliotheken ( hier und hier ). Aber leider hat kein einziger für mich gearbeitet.

Fortgeschrittene Pythonisten können grundsätzlich einen Modulsteuerungstreiber in Python schreiben. Die Vorgehensweise zum Abrufen eines Frames ist im Datenblatt ausführlich beschrieben. Aber dann müssen Sie alle Kalibrierungsverfahren vorschreiben, was etwas lästig erscheint. Deshalb musste ich den zweiten Weg gehen. Es stellte sich als mäßig dornig heraus, aber ziemlich passabel.

Dank der Einsicht chinesischer Ingenieure oder einfach nur eines glücklichen Zufalls stellte sich heraus, dass der Schal eine sehr gute Position für die Schlussfolgerungen hatte:

Bild

Es bleibt nur der Block zu setzen und den Schal in den Himbeeranschluss einzuführen. Auf der Platine ist ein 5- bis 3-Volt-Wandler installiert, sodass anscheinend nichts die empfindlichen Rx- und Tx-Ausgänge von Raspberry gefährdet.

Es sollte hinzugefügt werden, dass die Verbindung gemäß der ersten Option ebenfalls möglich ist, jedoch mehr Arbeit und Lötfähigkeiten erfordert. Die Karte muss auf der anderen Seite des Himbeer-Anschlusses installiert sein (siehe Titelfoto dieses Beitrags).

Software


Auf einer bekannten chinesischen Website wird ein solches Wunder angeboten, um auf die GY-MCU90640 zuzugreifen:

Bild

Höchstwahrscheinlich sollte das Interaktionsprotokoll mit dem auf der Karte installierten Mikrocontroller beschrieben werden, nach dem dieses Softwareprodukt funktioniert! Nach einem kurzen Gespräch mit dem Verkäufer von Schals (in Bezug auf diese angesehenen Herren) wurde mir ein solches Protokoll zugesandt. Es erschien im PDF und in reinem Chinesisch.

Dank des Google-Übersetzers und des aktiven Kopierens und Einfügens wurde das Protokoll in etwa anderthalb Stunden entschlüsselt, und diejenigen, die dies wünschen, können es auf Github kennenlernen . Es stellte sich heraus, dass der Schal sechs grundlegende Befehle versteht, unter denen sich eine Rahmenanforderung am COM-Port befindet.

Jedes Pixel der Matrix ist tatsächlich der Temperaturwert des Objekts, das dieses Pixel betrachtet. Temperatur in Grad Celsius mal 100 (Doppelbytezahl). Tatsächlich gibt es sogar einen speziellen Modus, in dem der Schal 4 Mal pro Sekunde Frames von der Matrix an die Himbeere sendet.

Das Skript zum Erhalten von Wärmebildern hier:
"""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.

image

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

image

Raspberry Pi Zero W Pi 3 B+. VNC . , , powerbank' VNC . , , .

. .

, , . . , . - , .

!

UPD: . . - , , . . — .

image

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

Source: https://habr.com/ru/post/de435946/


All Articles