一、所选主题和项目介绍
1.1 项目背景
在物联网应用场景中,多设备协同工作是一个常见需求。传统的物联网设备需要预先配置网络参数和设备地址,部署过程繁琐且容易出错。本项目使用M5Stack Cardputer开发板,实现一款支持智能网络发现的健康监测节点,实现设备的即插即用和自动组网,大幅简化物联网系统的部署和维护。
1.2 项目目标
本项目使用M5Stack Cardputer V1.1 (K132)开发板,实现一款智能健康监测节点,主要功能如下:
- 多传感器支持:自动扫描I2C总线,支持多个称重传感器
- 重量稳定性检测:采用滑动窗口算法检测重量稳定性
- 数据上传:通过MQTT协议将重量数据上传至服务器
- 状态显示:内置TFT显示屏实时显示设备状态
- LED指示:通过RGB LED指示传感器状态
1.3 创新点
- 自动传感器发现:自动扫描I2C总线,无需手动配置传感器地址
- 稳定性检测算法:采用滑动窗口算法,三次采样波动小于2g认为稳定
- 多传感器管理:支持多个称重传感器同时工作,自动分配ID
- 实时状态显示:TFT屏幕实时显示各传感器重量和状态
- 远程数据上报:通过MQTT协议实现数据远程上报
二、硬件介绍
2.1 主控设备
M5Stack Cardputer (SKU: K132) — 基于ESP32-S3的卡片电脑,配备56键键盘、1.14英寸TFT屏幕、Grove扩展接口,支持WiFi和I2C通信。
参数 | 规格 |
|---|---|
主控芯片 | ESP32-S3FN8,双核240MHz |
Flash | 8MB |
显示屏 | 1.14英寸 ST7789V2,240×135 |
扩展接口 | Grove HY2.0-4P (I2C)、SD卡槽 |
电池 | 内置120mAh + 底座1400mAh |
2.2 传感器模块
M5Unit-Miniscale 称重传感器 — 基于HX711的I2C称重模块,量程0-500g,精度0.1g,板载RGB LED指示,默认地址0x26(可配置0x26-0x2D)。
2.3 硬件连接
Cardputer引脚 | Miniscale引脚 | 功能 |
|---|---|---|
PORTA_SDA | SDA | I2C数据线 |
PORTA_SCL | SCL | I2C时钟线 |
3.3V | VCC | 电源正极 |
GND | GND | 电源地 |
📷 实物照片(Cardputer与Miniscale传感器连接)

┌─────────────────────────────────────────────────────────────────────────┐
│ Cardputer 主控板 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ESP32-S3 │ │ST7789 │ │QWERTY │ │USB-C │ │PORTA │ │
│ │主控芯片 │ │显示屏 │ │键盘 │ │接口 │ │I2C接口 │ │
│ └────┬────┘ └─────────┘ └─────────┘ └─────────┘ └────┬────┘ │
│ │ │ │
│ │ WiFi │ I2C │
│ │ │ │
└───────┼────────────────────────────────────────────────────────┼──────────┘
│ │
│ MQTT │
│ │
▼ ▼
┌───────────────────┐ ┌─────────────────────┐
│ MQTT Broker │ │ Miniscale传感器 │
│ (云端服务器) │ │ (多个级联) │
│ │ │ │
│ ┌─────────────┐ │ │ ┌───────────────┐ │
│ │数据接收 │ │ │ │ 0x26 - 物品1 │ │
│ │数据存储 │ │ │ │ 0x27 - 物品2 │ │
│ └─────────────┘ │ │ │ 0x28 - 物品3 │ │
└───────────────────┘ │ └───────────────┘ │
└─────────────────────┘
三、方案框图和项目设计思路
3.1 系统架构
┌─────────────────┐
│ MQTT Broker │
│ (云端服务器) │
└────────┬────────┘
│
│ MQTT
│
▼
┌─────────────────┐
│ Cardputer │
│ (监测节点) │
└────────┬────────┘
│
│ I2C
│
┌──────────────────────────┼──────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Miniscale│ │Miniscale│ │Miniscale│
│ 0x26 │ │ 0x27 │ │ 0x28 │
│ 物品1 │ │ 物品2 │ │ 物品3 │
└─────────┘ └─────────┘ └─────────┘
3.2 设备启动流程
┌─────────────┐
│ 设备启动 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 加载配置 │
│ settings.toml│
└──────┬──────┘
│
▼
┌─────────────┐
│ 连接WiFi │
└──────┬──────┘
│
▼
┌─────────────┐
│ 扫描I2C总线 │
│ 发现传感器 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 连接MQTT │
│ 订阅配置主题│
└──────┬──────┘
│
▼
┌─────────────┐
│ 主循环运行 │
│ 读取重量 │
│ 检测稳定性 │
│ 上报数据 │
└─────────────┘
3.3 重量稳定性检测算法
采用滑动窗口算法检测重量稳定性:
- 采样窗口:连续采样3次
- 稳定判定:窗口内最大值与最小值差值 ≤ 2g
- 变化检测:稳定值与上次稳定值差值 ≥ 阈值时认为有变化
四、原理图和PCB展示及介绍
4.1 硬件连接原理图
本项目使用M5Stack官方硬件,硬件连接采用I2C总线方式。为支持多个Miniscale传感器级联,设计了I2C级联扩展板。
Cardputer
┌───────────┐
│ │
3.3V ──────────┤ 3V3 │
│ │
GND ──────────┤ GND │
│ │
SCL ──────────┤ PORTA_SCL │
│ │
SDA ──────────┤ PORTA_SDA │
│ │
└───────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Miniscale│ │Miniscale│ │Miniscale│
│ 0x26 │ │ 0x27 │ │ 0x28 │
│ 牙刷 │ │ 水杯 │ │ 其他 │
└─────────┘ └─────────┘ └─────────┘
4.2 I2C级联扩展板PCB
为方便多个Miniscale传感器级联连接,设计了I2C级联扩展板(基于KiCad设计)。
📷 I2C级联扩展板PCB原理图:见附件
📷 I2C级联扩展板PCB布局图:见附件
>
4.3 I2C总线扫描
Cardputer支持多种I2C接口:
def init_i2c():
"""
初始化I2C总线
Cardputer有两个I2C接口:
- board.I2C(): 内置I2C
- board.PORTA_I2C(): PORTA接口的I2C
"""
i2c_list = []
# 尝试PORTA_I2C
if hasattr(board, 'PORTA_I2C'):
i2c = board.PORTA_I2C()
i2c_list.append(('PORTA_I2C', i2c))
# 尝试内置I2C
if hasattr(board, 'I2C'):
i2c = board.I2C()
i2c_list.append(('I2C', i2c))
# 尝试busio
i2c = busio.I2C(scl=board.G2, sda=board.G1)
i2c_list.append(('busio', i2c))
# 探测传感器
for name, i2c in i2c_list:
found = probe_sensors_quick(i2c)
if found:
return i2c
return None
五、软件流程图和关键代码介绍
5.1 主程序结构
"""
M5Stack Cardputer V1.1 - 智能重量监测终端
功能特性:
1. 自动扫描I2C称重设备
2. 重量稳定性检测
3. MQTT数据上报
4. TFT状态显示
"""
5.2 配置加载
def load_config():
"""
加载配置文件
优先级:
1. supervisor.runtime.config (如果可用)
2. settings.toml 文件
3. os.getenv (环境变量)
4. 默认值
"""
# 尝试从supervisor加载
if SUPERVISOR_AVAILABLE:
settings = supervisor.runtime.config
WIFI_SSID = settings.get("CIRCUITPY_WIFI_SSID")
MQTT_BROKER = settings.get("MQTT_BROKER")
# ...
# 尝试从settings.toml加载
if not config_loaded:
with open('/settings.toml', 'r') as f:
settings = parse_toml_simple(f.read())
5.3 传感器管理
class WeightSensor:
"""称重传感器类"""
def __init__(self, i2c, address, sensor_id):
self.i2c = i2c
self.address = address
self.sensor_id = sensor_id
self.weight = 0.0
def read_weight(self):
"""读取重量数据"""
try:
buffer = bytearray(4)
while not self.i2c.try_lock():
time.sleep(0.01)
try:
self.i2c.writeto_then_readfrom(
self.address,
bytes([0x10]),
buffer
)
weight = struct.unpack('<f', buffer)[0]
if -1000 < weight < 10000:
self.weight = weight
return weight
finally:
self.i2c.unlock()
except:
pass
return self.weight
def set_led(self, r, g, b):
"""设置LED颜色"""
data = bytes([r, g, b])
self.i2c.writeto(self.address, bytes([LED_REG]) + data)
5.4 稳定性检测
def check_stability(sensor_id, weight):
"""
检测重量稳定性
三次采样波动小于2g认为稳定
Args:
sensor_id: 传感器ID
weight: 当前重量值
Returns:
tuple: (是否稳定, 稳定值是否变化)
"""
global weight_history, stable_weights
if sensor_id not in weight_history:
weight_history[sensor_id] = []
weight_history[sensor_id].append(weight)
# 保留最近3次采样
if len(weight_history[sensor_id]) > 3:
weight_history[sensor_id] = weight_history[sensor_id][-3:]
# 检测稳定性
if len(weight_history[sensor_id]) >= 3:
max_diff = max(weight_history[sensor_id]) - min(weight_history[sensor_id])
if max_diff <= 2: # 波动小于2g
new_stable = int(round(sum(weight_history[sensor_id]) / 3))
# 检测变化
old_stable = stable_weights.get(sensor_id)
stable_weights[sensor_id] = new_stable
if old_stable is None:
return True, False
elif abs(new_stable - old_stable) >= WEIGHT_CHANGE_THRESHOLD:
return True, True
return True, False
return False, False
5.5 数据上报
def send_sensor_data():
"""
发送传感器数据
通过MQTT协议上报重量数据
"""
global sensors
for sensor_id, sensor in sensors.items():
weight = sensor.read_weight()
data = {
"device_id": BOARD_ID,
"sensor_id": sensor_id,
"weight": weight,
"timestamp": time.time()
}
# 通过MQTT上报
mqtt_client.publish(MQTT_TOPIC_WEIGHT, json.dumps(data))
六、硬件功能展示图及说明
6.1 硬件整体展示

6.2 显示界面
6.2.1 启动界面
=== Cardputer ===
Weight Monitor v1.0
Connecting WiFi...
6.2.2 运行状态
=== MONITOR ===
Sensors: 3
C1: 125g (物品1)
C2: 89g (物品2)
C3: 45g (物品3)
Uptime: 2h 35m
6.3 系统运行日志
==================================================
Cardputer Weight Monitor v1.0
Device ID: cardputer_01
==================================================
MAC: AA:BB:CC:DD:EE:FF
[Display] Init OK
[I2C] Bus init OK
[Sensor] C1 (0x26) init OK
[Sensor] C2 (0x27) init OK
[WiFi] Connecting to: YourWiFi
[WiFi] Connected, IP: 192.168.1.100
[MQTT] Connecting to broker.emqx.io:1883
[MQTT] Connected
==================================================
[Main] Running...



七、设计中遇到的难题和解决方法
7.1 I2C接口兼容性
问题描述:Cardputer的定制CircuitPython固件没有标准的board.SCL和board.SDA属性。
解决方案:
- 使用board.I2C()函数式访问
- 尝试多种I2C初始化方式
- 实现自动探测功能
# 定制固件的正确方式
i2c = board.I2C() # 函数调用,不是属性访问
# 或者使用PORTA接口
i2c = board.PORTA_I2C()
7.2 重量稳定性检测
问题描述:称重传感器读数存在波动,难以判断重量是否稳定。
解决方案:
- 采用滑动窗口算法
- 连续3次采样波动小于2g认为稳定
- 稳定后清空历史数据,重新开始检测
# 稳定性检测算法
def check_stability(weight_history):
if len(weight_history) >= 3:
max_diff = max(weight_history) - min(weight_history)
return max_diff <= 2 # 波动小于2g
return False
7.3 配置文件解析
问题描述:CircuitPython没有内置TOML解析库。
解决方案:
- 实现简单的TOML解析器
- 支持基本数据类型和嵌套结构
def parse_toml_simple(content):
"""简单解析TOML配置文件"""
config = {}
current_section = None
for line in content.split('\n'):
line = line.strip()
if not line or line.startswith('#'):
continue
# 解析节
if line.startswith('[') and line.endswith(']'):
current_section = line[1:-1].strip()
continue
# 解析键值对
if '=' in line:
key, value = line.split('=', 1)
# 处理不同类型...
7.4 MQTT连接稳定性
问题描述:MQTT连接可能因网络波动断开。
解决方案:
- 实现自动重连机制
- 断线时缓存数据
def mqtt_reconnect():
"""MQTT自动重连"""
global mqtt_client
try:
mqtt_client.connect()
print("[MQTT] Reconnected")
except Exception as e:
print("[MQTT] Reconnect failed:", e)
7.5 多传感器管理
问题描述:多个传感器同时工作需要有效管理。
解决方案:
- 使用字典存储传感器实例
- 自动分配传感器ID
- 统一的数据上报接口
# 传感器管理
sensors = {}
for addr in found_addresses:
sensor_id = "C{}".format(len(sensors) + 1)
sensors[sensor_id] = WeightSensor(i2c, addr, sensor_id)
八、心得体会
8.1 项目收获
- 物联网架构设计:深入理解了物联网系统的数据采集和上报架构
- 传感器技术:掌握了I2C传感器通信和数据处理技术
- 嵌入式开发:熟悉了CircuitPython开发环境和API
- 网络协议应用:实践了MQTT协议在物联网中的应用
- 算法设计:实现了重量稳定性检测算法
8.2 技术亮点
- 自动传感器发现:自动扫描I2C总线,无需手动配置
- 稳定性检测算法:滑动窗口算法准确检测重量变化
- 多传感器管理:支持多个传感器同时工作
- 实时状态显示:TFT屏幕实时显示各传感器状态
8.3 改进建议
- 智能网络发现:实现ESP-NOW网络自动发现和组网功能,设备开机自动检测现有网络,智能选择加入或创建网络
- 双模式通信:支持ESP-NOW局域通信和MQTT云端通信,实现网关自动选举和数据转发
- 安全配对机制:按键确认机制防止未授权设备加入网络,提高系统安全性
- 远程配置:支持通过MQTT远程更新传感器映射,实现设备配置的动态更新
- 心跳机制:定期发送心跳保持MQTT连接,实现设备在线状态监控
- 增加加密:ESP-NOW消息加密,提高数据传输安全性
- 优化功耗:实现低功耗模式,延长电池寿命
- 增强稳定性:增加断线重连和异常恢复机制
- 扩展功能:支持OTA升级和远程调试
创意方向关联
本项目的技术创新为以下创意方向提供了新的思路:
1. 人工智能在嵌入式系统中的应用
本项目的传感器数据处理技术为AI应用提供了基础:
- 故障保护:人工智能判断:稳定性检测算法可发展为AI驱动的设备健康预警系统
- 计算机视觉:结合摄像头实现设备状态可视化监控
- 图像识别:识别设备异常状态图像
2. 楼宇自动化
健康监测节点是楼宇自动化的核心组件:
- 设备状态监测:监测楼宇设备运行状态
- 能源管理:监测设备能耗,实现智能节能
- 预测性维护:提前预警设备故障
3. 无线 / 5G / WiFi-7
项目集成的MQTT通信功能:
- 无线连接在智能建筑中的应用:MQTT是智能建筑数据传输的标准协议
- 5G物联网:MQTT架构可迁移到5G物联网终端开发
- WiFi-7技术储备:高速无线通信实现实时数据上报
技术迁移价值
本项目开发的技术方案可迁移到:
- 人工智能应用:设备健康预警、异常检测
- 楼宇自动化:设备监测、能源管理、预测性维护
- 无线通信:MQTT物联网、5G终端
致谢
感谢 DigiKey 和 电子森林 提供的FastBond4活动支持,本次活动链接:https://www.eetree.cn/page/digikey-fastbond




