【Beetle ESP32-C6开发板】网页热成像仪

2026-04-0487
AI 快速预览详细 收起
本文介绍了使用Beetle ESP32-C6开发板结合MLX90640模块和WiFi基站功能,实现网页热成像仪的设计。项目包括准备工作、硬件连接、驱动代码和效果演示。通过详细的步骤和代码示例,用户可以轻松实现热成像画面的实时显示。该项目适用于工业监控、智能家居和科研实验等多种场景。

【Beetle ESP32-C6开发板】网页热成像仪

 

本文介绍了 Beetle ESP32-C6 开发板结合 MLX90640 模块和 WiFi 基站功能,实现网页热成像仪的项目设计。

 

项目介绍

 

准备工作:MLX90640 驱动程序、功能测试等;

硬件连接:使用杜邦线连接传感器模块、USB转TTL工具、RP2350开发板;

工程代码:包括板端执行代码、网页设计代码;

效果演示:运行程序和网页,实现热成像画面帧的实时显示。

 

MLX90640

 

MLX90640 是一款高性能的 32x24 像素红外热成像传感器,支持非接触式温度测量,广泛应用于工业监控、智能家居和科研实验等领域。

 

mlx90640_view.jpg

 

详见:远红外热传感器阵列(32x24 RES)I Melexis .

 

模块设计

 

为了便于设备连接,设计 PCB 模块。

 

mlx90640_module_3D.jpg

 

原理图

 

SCH_mlx90640.jpg

 

实物图

 

mlx90640_module.jpg

 

这里使用 MLX90640 模块,详见:MLX90640热成像传感器 - 立创开源硬件平台 .

 

准备工作

 

包括驱动代码和功能测试。

 

驱动代码

 

下载 并上传 mlx90640 驱动代码文件至开发板根目录;

 

这里使用 uPyPi 开发的 mlx90640 驱动程序;

 

uPyPi 是类似 PyPI 的 MicroPython 软件包仓库;

 

uPyPi 是面向 MicroPython 生态的专属包管理中心,旨在简化 MicroPython 库和驱动的发现、共享与部署流程。

 

详见:FreakStudioCN/upypi: micropython index .

 

功能测试

 

运行 Thonny IDE 新建文件,添加如下代码

 

保存代码。

 

效果

 

运行测试代码,终端输出初始化传感器信息、温度统计信息等;

 

mlx90640_demo_print.jpg

 

详见: https://upypi.net/en/pkgs/mlx_90640_driver .

 

硬件连接

 

包括 MLX90640 模块与 ESP32-C6 开发板的连接。

 

MLX90640 模块

ESP32-C6MLX90640 moduleNote
SCL (Pin 20)SCLSerial Clock
SDA (Pin 19)SDASerial Data
GNDGNDGround
3.3VVCCPower

 

实物图

 

mlx90640_connect.jpg

 

流程图

 

flowchart_mlx90640_web.jpg

 

工程代码

 

运行 Thonny IDE 新建文件,添加如下代码


**********代码见底部文件***********

 ​

保存代码。

 

效果演示

 

运行程序,根据终端提示,获得网页对应地址;

 

在浏览器地址栏输入 192.168.31.115 打开网页;

 

mlx90640_web_print.jpg

 

网页显示实时热成像帧画面;

 

mlx90640_web_show.jpg

==================

mlx90640_web_show_hello.jpg

改变手势动作,呈现相应效果;

mlx90640_web_show_hand.jpg

=======

mlx90640_web_show_yeah.jpg

 

=========

mlx90640_web_show_ok.jpg

 

 

总结

 

本文介绍了 Beetle ESP32-C6 开发板结合 MLX90640 模块和 WiFi 通信,实现网页热成像仪的项目设计,为相关产品的快速开发和应用设计提供了参考。

 

代码
from machine import I2C
import time
import network
import socket
from mlx90640 import MLX90640, RefreshRate

# ==================== 配置 ====================
WIFI_SSID = "xxx"
WIFI_PASSWORD = "xxx"
I2C_SCL = 20
I2C_SDA = 19
# ==============================================

temperature_frame = [0.0] * 768
min_temp = 25.0
max_temp = 35.0

# WiFi连接
def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print("Connecting WiFi...")
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        for _ in range(20):
            if wlan.isconnected(): break
            time.sleep(0.5)
            print(".", end="")
    if wlan.isconnected():
        ip = wlan.ifconfig()[0]
        print("\nIP:", ip)
        return ip
    print("\nWiFi 失败")
    return None

# 传感器初始化
def init_sensor():
    i2c = I2C(0, scl=I2C_SCL, sda=I2C_SDA, freq=100000)
    addr = None
    for d in i2c.scan():
        if 0x31 <= d <= 0x35:
            addr = d
            break
    if not addr:
        print("未找到传感器")
        raise SystemExit()
    cam = MLX90640(i2c, addr)
    cam.refresh_rate = RefreshRate.REFRESH_2_HZ
    cam.emissivity = 0.92
    print("传感器就绪")
    return cam

# 读取一次温度
def read_temp(cam):
    global min_temp, max_temp
    try:
        cam.get_frame(temperature_frame)
        min_temp = min(temperature_frame)
        max_temp = max(temperature_frame)
    except:
        pass

# 平滑渐变色
def get_color(temp):
    r = (temp - min_temp) / ((max_temp - min_temp) or 1)
    if r < 0.2:
        return "#0000FF"
    elif r < 0.4:
        return "#00AFFF"
    elif r < 0.6:
        return "#00FF80"
    elif r < 0.8:
        return "#FFDD00"
    else:
        return "#FF4000"

# 发送顺滑居中的热成像网页
def send_page(conn):
    try:
        conn.send(b"HTTP/1.1 200 OK\r\n")
        conn.send(b"Content-Type: text/html\r\n")
        conn.send(b"Cache-Control: no-cache, no-store, must-revalidate\r\n")
        conn.send(b"Pragma: no-cache\r\n")
        conn.send(b"Expires: 0\r\n")
        conn.send(b"Connection: close\r\n\r\n")

        # 整体居中、大像素、更平滑的样式
        conn.send(b"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>热成像仪</title>
<style>
    *{margin:0;padding:0;box-sizing:border-box;}
    body{
        background:#111;
        color:#fff;
        font-family:Arial;
        display:flex;
        flex-direction:column;
        align-items:center;
        justify-content:center;
        min-height:100vh;
        padding:10px;
    }
    .thermal{
        display:grid;
        grid-template-columns: repeat(32, 8px);
        gap:2px;
        background:#222;
        padding:10px;
        border-radius:6px;
        margin:12px 0;
    }
    .pixel{
        width:8px;
        height:8px;
        border-radius:2px;
    }
    .info{
        text-align:center;
        margin:8px 0;
        font-size:16px;
        color:#0ff;
    }
    a{
        color:#ff0;
        text-decoration:none;
        font-size:16px;
        padding:6px 12px;
        border:1px solid #ff0;
        border-radius:4px;
        margin-top:8px;
    }
</style>
</head>
<body>
    <h3>ESP32-C6 热成像仪</h3>
    <div class="info">
""")

        conn.send(b"MIN: ")
        conn.send(str(round(min_temp, 1)).encode())
        conn.send(b"°C    MAX: ")
        conn.send(str(round(max_temp, 1)).encode())
        conn.send(b"°C")

        conn.send(b"""
    </div>
    <a href="/">刷新画面</a>
    <div class="thermal">
        """)

        # 逐点输出大像素色块
        for t in temperature_frame:
            c = get_color(t)
            conn.send(f'<div class="pixel" style="background:{c};"></div>'.encode())

        conn.send(b"""
    </div>
</body>
</html>
        """)
    except:
        pass

# 主程序
def main():
    print("启动...")
    time.sleep(1)
    cam = init_sensor()
    ip = connect_wifi()
    if not ip:
        return

    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(("0.0.0.0", 80))
    s.listen(1)
    s.settimeout(0.1)

    while True:
        try:
            conn, addr = s.accept()
            read_temp(cam)
            send_page(conn)
            conn.close()
            print("已刷新")
        except OSError:
            pass

if __name__ == "__main__":
    main()

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -