【树莓派5】便携热成像仪
本文介绍了树莓派 5 单板计算机结合 SPI 通信协议驱动 LCD 彩色显示屏、结合 IIC 协议驱动 MLX90640 热成像传感器模块,实现便携热成像仪的项目设计。
项目介绍
项目包括驱动 LCD 彩屏、驱动 MLX90640 模块、综合搭建热成像仪三部分。
硬件连接:使用杜邦线连接 LCD 彩屏、MLX90640 模块和树莓派;
环境搭建:安装部署所需驱动、软件包和库;
工程代码:流程图、关键代码;
效果演示:LCD 显示彩色热成像图,终端打印温度范围。
硬件连接
包括 LCD 彩色显示屏、MLX90640模块和树莓派的接线方式。
LCD 彩屏| Raspberry Pi | LCD | Note |
| GND | GND | Ground |
| 3.3V | Vin | Power |
| Pin 22 | RST | Reset |
| Pin 18 | DC/RS | Command |
| Pin 24 | CS | Chip Select |
| Pin 19 | MOSI | Data |
| Pin 23 | SCLK | Clock |
详见:Python Wiring and Setup | LCD Display .
MLX90640 模块
| MLX90640 | Raspberry Pi | Note |
| SDA | SDA (Pin3) | Serial Data |
| SCL | SCL (Pin5) | Serial Clock |
| GND | GND | Ground |
| VIN | 3V3 | Power |
树莓派 40Pin 引脚定义: Raspberry Pi GPIO Pinout .
详见:MLX90640热成像传感器 - 立创开源硬件平台 .
环境搭建
创建并激活虚拟环境,安装所需 LCD 驱动包和 MLX90640 传感器驱动包
python3 -m venv .venv source .venv/bin/activate pip install adafruit-circuitpython-rgb-display pip install adafruit-circuitpython-mlx90640
终端执行指令
sudo i2cdetect -y 1
显示 iic 设备地址为 0x33 对应设备为 MLX90640


流程图

工程代码
终端执行指令 touch lcd_mlx90640_display.py 新建程序文件,并添加如下代码
import time
import board
import busio
import digitalio
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import adafruit_mlx90640
from adafruit_rgb_display import st7735
import matplotlib.cm as cm
import matplotlib.colors as colors
# LCD 引脚配置
CS_PIN = digitalio.DigitalInOut(board.CE0)
DC_PIN = digitalio.DigitalInOut(board.D24)
RESET_PIN = digitalio.DigitalInOut(board.D25)
BAUDRATE = 24000000
# 传感器配置
REFRESH_RATE = adafruit_mlx90640.RefreshRate.REFRESH_4_HZ # 4Hz 刷新率
MIN_TEMP = 15.0 # 颜色映射的最小温度 (°C)
MAX_TEMP = 35.0 # 颜色映射的最大温度 (°C)
# 图像放大倍数 (传感器是 32x24,放大后更适合屏幕观看)
SCALE_FACTOR = 8
# ===========================================
def initialize_sensor():
"""初始化 MLX90640 传感器"""
i2c = busio.I2C(board.SCL, board.SDA, frequency=1000000) # 提高 I2C 速度
mlx = adafruit_mlx90640.MLX90640(i2c)
mlx.refresh_rate = REFRESH_RATE
# 读取一次以清除旧数据
frame = [0] * 768
try:
mlx.getFrame(frame)
except Exception as e:
print(f"Warning: Initial read failed: {e}")
return mlx
def initialize_display():
"""初始化 LCD 屏幕"""
spi = board.SPI()
disp = st7735.ST7735R(
spi,
rotation=90, # 根据屏幕安装方向调整 (0, 90, 180, 270)
cs=CS_PIN,
dc=DC_PIN,
rst=RESET_PIN,
baudrate=BAUDRATE,
)
# 获取屏幕尺寸
if disp.rotation % 180 == 90:
width = disp.height
height = disp.width
else:
width = disp.width
height = disp.height
return disp, width, height
def create_color_lut(min_t, max_t, cmap_name='inferno'):
"""
创建颜色查找表 (LUT)
将温度范围映射到 0-255 的索引,再映射到 RGB 颜色
"""
cmap = cm.get_cmap(cmap_name)
norm = colors.Normalize(vmin=min_t, vmax=max_t)
lut = []
# 生成 256 个颜色的查找表
for i in range(256):
# 将 0-255 映射回温度范围用于归一化 (这里反向操作,直接生成归一化值)
t_val = min_t + (max_t - min_t) * (i / 255.0)
rgba = cmap(norm(t_val))
# 转换为 0-255 的 RGB 整数
r = int(rgba[0] * 255)
g = int(rgba[1] * 255)
b = int(rgba[2] * 255)
lut.append((r, g, b))
return lut
def temperature_to_rgb(data_array, lut, min_t, max_t):
"""
将温度矩阵转换为 RGB 图像数据。
使用查找表加速转换。
"""
# 限制数据在范围内,避免索引越界
clipped_data = np.clip(data_array, min_t, max_t)
# 归一化到 0-255 索引
# (data - min) / (max - min) * 255
range_t = max_t - min_t
if range_t == 0: range_t = 0.001 # 防止除零
indices = ((clipped_data - min_t) / range_t * 255).astype(int)
# 映射 RGB
h, w = indices.shape
rgb_array = np.zeros((h, w, 3), dtype=np.uint8)
# 应用 LUT (向量化操作,速度快)
# 注意:lut 是列表,转为 numpy 数组以便索引
lut_np = np.array(lut, dtype=np.uint8)
rgb_array = lut_np[indices]
return rgb_array
def main():
print("Initializing Sensor...")
mlx = initialize_sensor()
print("Initializing Display...")
disp, screen_w, screen_h = initialize_display()
# 创建颜色查找表
print(f"Creating Color Map (Range: {MIN_TEMP}°C - {MAX_TEMP}°C)...")
lut = create_color_lut(MIN_TEMP, MAX_TEMP, cmap_name='inferno')
# 准备缓冲区
frame = [0] * 768 # 32 * 24
max_retries = 5
# 用于显示统计信息的字体
try:
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 10)
except IOError:
font = ImageFont.load_default()
print("Starting Thermal Loop...")
start_time = time.time()
frame_count = 0
while True:
t1 = time.monotonic()
retry_count = 0
success = False
# 读取传感器数据
while retry_count < max_retries:
try:
mlx.getFrame(frame)
success = True
break
except ValueError:
retry_count += 1
except RuntimeError as e:
retry_count += 1
if retry_count >= max_retries:
print(f"Sensor Error after {max_retries} retries: {e}")
break
time.sleep(0.01) # 短暂等待后重试
if not success:
continue
# 数据处理
data_array = np.reshape(frame, (24, 32))
# MLX90640
data_array = np.fliplr(data_array)
# 动态调整温度范围 (颜色随环境自动变化,取消下面两行注释,并注释固定的 MIN/MAX)
# curr_min = np.min(data_array)
# curr_max = np.max(data_array)
# 为了防止噪声导致颜色闪烁,通常建议设置一个固定的范围或使用平滑滤波
# 转换为 RGB 图像 (24x32)
rgb_small = temperature_to_rgb(data_array, lut, MIN_TEMP, MAX_TEMP)
# 将 numpy 数组转换为 PIL Image
img_small = Image.fromarray(rgb_small, mode='RGB')
# 放大图像以适应屏幕 (使用双线性插值)
target_w = 32 * SCALE_FACTOR
target_h = 24 * SCALE_FACTOR
img_large = img_small.resize((target_w, target_h), Image.BILINEAR)
# 创建一个与屏幕大小相同的黑色背景
image = Image.new("RGB", (screen_w, screen_h), (0, 0, 0))
# 计算居中位置
paste_x = (screen_w - target_w) // 2
paste_y = (screen_h - target_h) // 2
# 将热成像图粘贴到背景上
image.paste(img_large, (paste_x, paste_y))
# 绘制文字信息 (温度统计)
draw = ImageDraw.Draw(image)
current_min = np.min(data_array)
current_max = np.max(data_array)
current_avg = np.mean(data_array)
info_text = f"Min: {current_min:.1f}C\nMax: {current_max:.1f}C\nAvg: {current_avg:.1f}C"
# 在左上角绘制文字 (白色)
draw.text((5, 5), info_text, fill=(255, 255, 255), font=font)
# 显示 FPS
fps = 1.0 / (time.monotonic() - t1) if (time.monotonic() - t1) > 0 else 0
fps_text = f"FPS: {fps:.1f}"
draw.text((5, screen_h - 15), fps_text, fill=(255, 255, 0), font=font)
# 更新屏幕
disp.image(image)
# 简单的帧率控制与统计
frame_count += 1
if frame_count % 10 == 0:
elapsed = time.time() - start_time
if elapsed > 0:
print(f"Running... Avg FPS: {frame_count/elapsed:.2f}, Temp Range: {current_min:.1f}-{current_max:.1f}")
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("\nExiting...")保存代码。
效果演示
终端执行指令 python lcd_mlx90640_display.py 运行程序;
LCD 显示实时热成像图;


同时终端打印热成像温度范围


总结
本文介绍了树莓派 5 单板计算机结合 SPI 通信协议驱动 LCD 彩色显示屏、结合 IIC 协议驱动 MLX90640 热成像传感器模块,实现便携热成像仪的项目设计,为相关产品在工业物联网领域的快速开发和应用设计提供了参考。
我要赚赏金
