这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » M5Paperv1.1-结果贴称重监控系统-M5Paper综合应用成果

共1条 1/1 1 跳转至

M5Paperv1.1-结果贴称重监控系统-M5Paper综合应用成果

工程师
2026-05-14 10:54:05     打赏
在之前的 Calculator 过程贴中,我掌握了 Canvas 渲染和触摸交互的基础,为开发最终的整合应用打下了坚实基础。

今天这篇结果贴,将介绍一个基于 MQTT 协议的多设备体重称重监控系统。

项目概述

体重称重监控系统的设计目标很简单:用 M5Paper 实时显示多台秤的称重数据。用户可以一眼看到家里各台秤的当前读数、在线状态,而不用逐个去查看。

核心亮点:

  • 2x2 网格布局:同时监控最多 4 台称重设备

  • MQTT 实时通信:通过 公共 Broker 进行数据交换

  • 自动设备发现:I2C 地址扫描,即插即用

  • E-Ink 灰度优化:浅底深字的墨水屏友好配色

  • 离线超时检测:15 秒无数据自动标记离线

系统架构

整个系统分为三层:

┌─────────────────────────────────────────────────────┐
│                    M5Paper 显示层                      │
│   ┌──────────┐  ┌──────────┐                         │
│   │ Slot 1   │  │ Slot 2   │  2x2 网格显示            │
│   │ 123.4g   │  │ 456.7g   │  Canvas 渲染              │
│   │ online   │  │ online   │  5秒刷新间隔              │
│   ├──────────┤  ├──────────┤                         │
│   │ Slot 3   │  │ Slot 4   │                         │
│   │ ---      │  │ 789.0g   │                         │
│   │ offline  │  │ online   │                         │
│   └──────────┘  └──────────┘                         │
└──────────────────────┬──────────────────────────────┘
                        │ MQTT Subscribe
                        ▼
┌─────────────────────────────────────────────────────┐
│               MQTT Broker (broker.emqx.io)           │
│              Topic: scales/bridge/+/weight           │
└──────────────────────┬──────────────────────────────┘
                        │ MQTT Publish
                        ▼
┌─────────────────────────────────────────────────────┐
│             称重传感器节点 (ESP32 + MiniScale)         │
│   I2C 地址: 0x26 ~ 0x2D                              │
│   每 2 秒发布一次称重数据                              │
└─────────────────────────────────────────────────────┘
硬件连接

M5Paper 通过 PORT.A(HY2.0-4P 接口)连接外部称重传感器:

接口

引脚

连接

Yellow

G25 (SDA)

I2C 数据线

White

G32 (SCL)

I2C 时钟线

Red

5V

电源正极

Black

GND

电源负极

I2C 会自动扫描以下已知地址范围的称重传感器:

KNOWN_WEIGHT_SENSOR_ADDRESSES = [
    0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x30
]
代码架构详解

整个应用采用单文件结构,按功能模块划分:

# === 1. 配置区 ===
MQTT_SERVER = "broker.emqx.io"
MQTT_PORT = 1883
MQTT_TOPIC_PREFIX = "scales/bridge"
MQTT_SUB_TOPIC = "scales/bridge/+/weight"
DISPLAY_INTERVAL = 5        # E-Ink 刷新间隔(秒)
OFFLINE_TIMEOUT = 15        # 离线超时(秒)

# 屏幕参数
SCREEN_W = 960
SCREEN_H = 540
COLS = 2
ROWS = 2
GAP = 8
MARGIN = 8

# === 2. MQTT 回调 ===
def mqtt_event(topic, msg):
    """接收远程称重数据,更新缓存"""
    data = json.loads(msg)
    weight = float(data['weight'])
    device_id = data['device_id']
    
    # 查找空闲 slot 或更新已有设备
    for i in range(4):
        if remote_devices[i] == device_id:
            remote_weights[i] = weight
            remote_states[i] = "online"
            break

核心数据结构:

# 4 个 slot 的状态
remote_weights = [0.0, 0.0, 0.0, 0.0]     # 重量值
remote_states = ["offline"] * 4            # 在线状态
remote_devices = ["", "", "", ""]          # 设备 ID
remote_last_time = [0, 0, 0, 0]           # 最后更新时间
2x2 网格渲染

M5Paper 的 E-Ink 屏幕必须通过 Canvas 缓冲才能正确显示:

def setup_ui():
    """创建 2x2 网格 UI"""
    global canvas
    
    Display.setEpdMode(EPD_MODE_TEXT)
    canvas = M5.Lcd.newCanvas(SCREEN_W, SCREEN_H, 8, True)
    canvas.fillScreen(COLOR_BG)
    
    for row in range(ROWS):
        for col in range(COLS):
            idx = row * COLS + col
            x = MARGIN + col * (CELL_W + GAP)
            y = MARGIN + row * (CELL_H + GAP)
            draw_cell(canvas, idx, x, y, CELL_W, CELL_H, "", 0.0, "offline")
    
    canvas.push(0, 0)

def draw_cell(canvas, idx, x, y, w, h, device_id, weight_val, state):
    """绘制单个设备格子"""
    bg_color = BG_CELL[idx]
    canvas.fillRect(x, y, w, h, bg_color)
    canvas.drawRect(x, y, w, h, COLOR_DARK_GRAY)
    
    # 标题
    canvas.setTextColor(CLR_TITLE, bg_color)
    canvas.setTextSize(3)
    canvas.setCursor(x + 10, y + 10)
    canvas.print("Slot {}".format(idx + 1))
    
    # 设备 ID
    canvas.setTextColor(CLR_ID, bg_color)
    canvas.setTextSize(2)
    canvas.setCursor(x + 10, y + 40)
    canvas.print("ID: {}".format(device_id if device_id else "---"))
    
    # 重量数值
    canvas.setTextColor(CLR_WEIGHT, bg_color)
    canvas.setTextSize(3)
    canvas.setCursor(x + 10, y + h // 2)
    canvas.print("{:.1f} g".format(weight_val))
    
    # 在线状态
    status_color = CLR_STATUS_ONLINE if state == "online" else CLR_STATUS_OFFLINE
    canvas.setTextColor(status_color, bg_color)
    canvas.setTextSize(2)
    canvas.setCursor(x + 10, y + h - 35)
    canvas.print("Status: {}".format(state))

每个格子的视觉层次从高到低:

  1. 标题(Slot 1):深灰色,指引用户

  2. 设备 ID:中灰色,信息性内容

  3. 重量数值(123.4g):黑色粗体,最醒目

  4. 状态(online/offline):绿色/灰色,状态指示

E-Ink 刷新策略

称重监控场景采用两级 EPD 刷新模式:

阶段

EPD 模式

说明

初始绘制

EPD_TEXT (1)

高质量首次显示

数据更新

EPD_FAST (2)

每 5 秒快速更新

设备上线/离线

EPD_TEXT (1)

状态变化时清晰显示

def update_display():
    """更新 E-Ink 显示"""
    Display.setEpdMode(EPD_MODE_FAST)
    
    for i in range(4):
        row = i // COLS
        col = i % COLS
        x = MARGIN + col * (CELL_W + GAP)
        y = MARGIN + row * (CELL_H + GAP)
        draw_cell(canvas, i, x, y, CELL_W, CELL_H,
                  remote_devices[i], remote_weights[i], remote_states[i])
    
    canvas.push(0, 0)
MQTT 通信协议

系统使用轻量级的 MQTT 协议进行设备间通信:

发布主题:scales/bridge/{device_id}/weight

消息格式(JSON):

{
    "weight": 123.4,
    "unit": "g",
    "timestamp": 1714000000000,
    "device_id": "device_26",
    "status": "normal"
}

订阅主题:scales/bridge/+/weight(+ 为通配符,匹配任意设备)

自动设备发现

M5Paper 启动时会自动扫描 I2C 总线上的设备:

def discover_weight_sensors():
    """自动发现连接到 I2C 总线的称重传感器"""
    sensors = []
    devices = i2c0.scan()
    
    for addr in devices:
        if addr in KNOWN_WEIGHT_SENSOR_ADDRESSES:
            try:
                data = i2c0.readfrom_mem(addr, 0x00, 4)
                weight_raw = int.from_bytes(data, 'big', True)
                if -50000000 < weight_raw < 50000000:
                    sensors.append({
                        'addr': addr,
                        'name': "device_{:02X}".format(addr)
                    })
            except:
                pass
    
    return sensors
离线检测机制

15 秒内没有收到某设备的数据更新,自动标记为离线:

# 主循环中的离线检测
for i in range(4):
    if remote_states[i] == "online" and remote_last_time[i] > 0:
        if current_time - remote_last_time[i] >= OFFLINE_TIMEOUT:
            remote_states[i] = "offline"
            remote_weights[i] = 0.0
实际运行效果

M5Paper 通过 WiFi 连接到 MQTT Broker 后,会自动订阅所有称重设备的数据。当有称重数据发布时,在 2x2 网格中对应的 slot 会实时更新重量值和状态。

屏幕采用横屏 960x540 显示,放在桌面上可以一目了然地看到所有设备的状态。

踩坑记录

1. I2C 引脚复用问题

M5Paper 有两组 I2C:内部(G21/G22)和外部(G25/G32)。一开始我用错了引脚,连接到内部 I2C 上,和 GT911 触摸芯片冲突了。

解决:确认 PORT.A 的 I2C 引脚为 G25(SDA)和 G32(SCL)。

2. E-Ink 反色问题

首次绘制时,Canvas 背景色设置不当,导致格子背景和文字反色显示。

解决:采用浅底深字配色方案,背景用 0xeeeeee,文字用 0x000000。

3. MQTT 重连

WiFi 偶尔断连,MQTT 客户端需要自动重连。

解决:加入重连机制,每 5 秒检查一次连接状态。

总结与展望

体重称重监控系统充分利用了 M5Paper 的 ESP32 WiFi 能力和 E-Ink 低功耗特性,作为一个桌面信息终端非常实用。

后续可扩展的方向:

  • 接入 HomeAssistant 智能家居平台

  • 增加历史数据趋势图(利用 E-Ink 灰度显示)

  • 集成 Web 配置界面,无需修改代码即可配置 MQTT 参数

  • 添加称重数据超限报警功能

感谢大家阅读,欢迎在评论区交流讨论!


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]