项目定位

Mill 是一套面向工业磨坊场景的控制与维护系统。它不是单一的固件工程,而是从嵌入式固件到桌面 OTA 工具、再到移动端 App 的完整链路。

整套系统解决的核心问题是:把现场数据采集、继电器控制、远程维护和固件升级这些原本分散的事情,收敛到一套可以真正落地的工程链路里。

系统以 STM32F103ZE 为主控,通过 RS485/Modbus 接入 PT100 温度传感器、称重模块、流量计和继电器设备,再经由 G780s 通信模块将数据推送到云端,最终在 Flutter 客户端上实现实时监控和历史回溯。

系统架构

整条链路可以分为四层:

┌─────────────────────────────────────────────────────┐
│  Flutter 客户端 (com.varka.mill)                     │
│  实时数据 · 历史趋势 · 告警管理 · 继电器控制          │
└──────────────────────┬──────────────────────────────┘
                       │ HTTPS / WebSocket
┌──────────────────────▼──────────────────────────────┐
│  服务端 (Node.js + Mosquitto + SQLite)               │
│  MQTT 订阅 · 数据持久化 · WS 广播 · REST API         │
└──────────────────────┬──────────────────────────────┘
                       │ MQTT over TLS (8883)
┌──────────────────────▼──────────────────────────────┐
│  G780s 通信模块                                      │
│  Modbus 主站轮询 · 边缘 JSON 组包 · MQTT 客户端      │
└──────────────────────┬──────────────────────────────┘
                       │ USART3 / Modbus RTU
┌──────────────────────▼──────────────────────────────┐
│  STM32F103ZE 控制板                                  │
│  ┌─────────────┐  ┌──────────────┐  ┌────────────┐  │
│  │ 现场采集    │  │ 继电器控制   │  │ A/B 升级   │  │
│  │ USART2      │  │ DI 去抖      │  │ Bootloader │  │
│  │ Modbus 主站 │  │ 本地按键     ���  │ YMODEM     │  │
│  └─────────────┘  └──────────────┘  └────────────┘  │
└─────────────────────────────────────────────────────┘

硬件组成

组件型号/说明角色
主控STM32F103ZE数据采集、继电器控制、Modbus 通信
温度传感器PT100 模块(4 通道)RS485 Modbus 从站
称重模块4 通道称重变送器RS485 Modbus 从站
流量计超声波流量计RS485 Modbus 从站
继电器模块多路继电器输出控制 + DI 输入
通信模块G780sModbus 主站 + MQTT 上云
通信链路RS485 共线现场总线

STM32 固件:两条总线,两个角色

STM32 同时扮演两个 Modbus 角色:

  • USART2 — Modbus 主站:轮询现场传感器,采集 PT100 温度、称重数据、流量频率和继电器状态
  • USART3 — Modbus 从站:面向 G780s,暴露 91 个寄存器,覆盖现场数据、远程配置、维护控制和诊断信息

这种设计让 G780s 只需要轮询 STM32 一台设备就能拿到所有现场数据,而不需要直接跟每个传感器打交道。

采集的传感器矩阵

传感器寄存器数据
PT100 × 40x0001 ~ 0x0004温度 ×10 ℃
称重 × 40x0005 ~ 0x000C32 位大端,每通道高/低各一个寄存器
流量计0x000D ~ 0x000F瞬时流量 ×100,累计流量 ×1000
继电器0x0010 ~ 0x0015输出位图、输入位图、控制命令

远程维护:不只是读数据

G780s 侧的 Modbus 从站不只是一个数据源。它还暴露了一套完整的远程维护机制:

  • 配置区(0x0020 ~ 0x0028):传感器采集周期、流量采样周期、DI 去抖时间、控制模式等参数,可以远程修改
  • 维护控制(0x0030 ~ 0x0037):解锁口令、命令触发、状态查询,支持 30 秒维护窗口
  • 诊断区(0x0038 ~ 0x005A):固件版本、运行时长、上电次数、重启原因、CRC 错误计数、串口异常计数、当前运行槽位等

远程维护的标准流程是:解锁 → 写配置 → 确认 → 提交保存。配置修改不会立刻写 Flash,必须显式提交才生效,避免误操作。

A/B 双槽位固件升级

这是整个系统里最值得说的设计之一。STM32 的 Flash 被分成三个区域:

0x08000000 ┌─────────────────┐
           │   Bootloader    │  32 KB
0x08008000 ├─────────────────┤
           │   Slot A        │  236 KB
0x08043000 ├─────────────────┤
           │   Slot B        │  236 KB
0x0807E000 ├─────────────────┤
           │ BootCtrl / State │  参数页
0x08080000 └─────────────────┘

升级流程:

  1. App 请求进入 Bootloader 模式,写入升级状态页
  2. Bootloader 通过 YMODEM 接收镜像,写入非运行槽位
  3. 校验镜像大小、CRC32、SHA-256、向量表合法性
  4. 标记待试运行槽位,跳转执行
  5. 如果试运行失败(连续 3 次 IWDG 复位),自动回退到上一个槽位

这个设计的核心价值是:升级失败不会变砖。即使新固件有问题,Bootloader 也能检测到并回退。

OTA 桌面工具

PC 侧的 OTA 工具是一个 .NET / WPF 应用,提供三个主要功能:

  • 本地升级:通过 USB 转 RS485 直接连接设备,发送解锁指令后用 YMODEM 传输固件
  • 远程升级:通过虚拟串口映射,走同样的升级流程
  • 远程维护帧:生成和导入 Modbus RTU 原始帧,方便调试和云平台对接

工具会自动读取寄存器 0x005A 判断当前运行槽位,然后推荐刷写对应的 App_A.binApp_B.bin

Flutter 客户端

移动端 App(com.varka.mill)是整个系统的用户界面,主要功能:

  • 实时监控:通过 WebSocket 接收服务端推送的传感器数据,卡片式展示温度、称重、流量、继电器状态
  • 历史趋势:基于 fl_chart 绘制时间序列图,支持分度值切换和视口缩放
  • 告警管理:本地告警 + 历史告警拉取,支持未读计数持久化
  • 继电器控制:手动模式下可远程控制继电器输出

技术栈:Flutter + Provider + Dio + WebSocket + sqflite。

服务端

服务端负责桥接 MQTT 设备数据和 Flutter 客户端:

  • Mosquitto:MQTT broker,TLS 加密,设备凭据 + ACL 控制
  • Node.js API:订阅 device/+/up 主题,解析 G780s 边缘 JSON,映射到内部 tele schema,持久化到 SQLite
  • WebSocket:实时广播传感器数据给在线客户端
  • REST API:历史数据查询、告警管理、用户认证(admin + user,不开放注册)

开发环境

  • 主控:STM32F103ZE
  • 固件构建:Keil MDK-ARM
  • OTA 工具:.NET SDK 10 + WPF
  • 客户端:Flutter 3.x
  • 服务端:Node.js + Mosquitto + SQLite

后续阅读