1. 项目概述与核心功能解析
这个基于STM32和RFID的智能仓库管理系统,是我在工业物联网领域实践过的一个典型应用案例。系统通过RFID技术实现货物身份识别,结合压力传感器完成重量校验,构建了一套完整的物资追踪解决方案。最让我印象深刻的是它的模块化设计思路——将复杂的仓库管理分解为数据采集、本地处理和远程监控三个层次,用不到200元的硬件成本实现了商业级管理系统80%的核心功能。
系统硬件架构采用经典的"三明治"结构:
- 感知层:RC522 RFID模块+DHT11+压力传感器构成环境感知网络
- 控制层:STM32F103C8T6作为主控,负责数据融合与逻辑判断
- 应用层:OLED本地显示+ESP8266 WiFi模块实现云端同步
在实际部署中,我们发现三个设计亮点特别值得分享:
- 双校验机制:RFID识别货物类型后,必须通过压力传感器验证重量匹配才执行出入库,避免空卡操作
- 环境自适应:温湿度阈值可动态调整,适合不同品类货物的存储要求
- 离线缓存:在网络中断时,系统自动将操作记录暂存Flash,恢复连接后自动同步
2. 硬件设计与关键器件选型
2.1 主控芯片选型对比
选择STM32F103C8T6是经过多维度评估的结果:
- 性能参数:72MHz主频、64KB Flash、20KB RAM,足够处理RFID数据解析和简单算法
- 接口资源:3个USART(分别接RFID/WiFi/调试)、2个I2C(OLED+传感器)、1个SPI(备用)
- 成本控制:零售价约12元,相比STM32F4系列性价比突出
经验提示:C8T6的PA11/PA12用作USB时,会与某些RFID模块的SPI引脚冲突,建议提前规划引脚分配
2.2 RFID模块深度适配
RC522模块的软件配置需要特别注意:
c复制// SPI初始化关键参数
void RFID_Init(void) {
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 模块要求时钟极性低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 数据在第一个边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // 约1.125MHz
SPI_Init(SPI1, &SPI_InitStructure);
}
实测发现两个优化点:
- 天线匹配电路中的电阻R7建议改为可调电阻,不同环境下载波强度需要微调
- 卡片识别距离不稳定时,可尝试在3.3V电源端并联100μF电解电容
2.3 传感器网络搭建
重量检测方案对比表:
| 传感器类型 | 量程 | 精度 | 接口 | 单价 | 适用场景 |
|---|---|---|---|---|---|
| HX711+应变片 | 50kg | ±0.1% | 串行 | 25元 | 精确称重 |
| 电阻式压力传感器 | 100kg | ±1% | 模拟 | 8元 | 预算有限 |
| 薄膜压力传感器 | 10kg | ±5% | I2C | 15元 | 轻量物品 |
最终选择电阻式方案,因其成本优势明显,且通过软件校准可达到±0.5%的实用精度。校准方法如下:
- 空载时记录ADC值V0
- 放置1kg标准砝码记录V1
- 计算斜率k=(V1-V0)/1000
- 重量=(当前ADC值-V0)/k
3. 软件架构与核心算法实现
3.1 主程序状态机设计
系统采用事件驱动型状态机,关键状态转换如图:
code复制[待机] --RFID刷卡--> [身份验证] --验证通过--> [操作选择]
[操作选择] --按键输入--> [出入库处理] --完成--> [数据同步]
[数据同步] --成功--> [待机]
--失败--> [本地存储]
对应的代码框架:
c复制while(1) {
switch(sysState) {
case STANDBY:
if(RFID_Detect()) {
VerifyCard();
sysState = VERIFY;
}
break;
case VERIFY:
if(Verify_OK) {
ShowOperationMenu();
sysState = OPERATION;
}
break;
// 其他状态处理...
}
EnvMonitor(); // 后台持续监测环境
}
3.2 数据存储方案优化
货物信息存储面临两个挑战:
- RFID卡容量有限(MF1S50仅1KB)
- 需要记录操作日志
我们的解决方案:
- 卡片数据:采用自定义紧凑格式
code复制[头标志(2B)] [货物ID(4B)] [名称(16B)] [初始重量(4B)] [校验和(2B)] - 本地日志:使用STM32内部Flash模拟EEPROM
- 划分Page126和Page127为日志区
- 采用循环写入策略,每个记录包含时间戳+操作类型
避坑指南:Flash写入前必须先擦除整个页,建议累计满10条记录再统一写入,避免频繁擦除
3.3 云端通信协议设计
WiFi模块采用AT指令透传模式,自定义了轻量级协议:
code复制[START][LEN][CMD][DATA][CRC][END]
0xAA 1B 1B N 2 0x55
常见指令示例:
- 0x01:上传环境数据(温度+湿度)
- 0x02:同步出入库记录
- 0x03:远程阈值设置
实测中发现ESP8266在连续传输时容易丢包,建议:
- 每个数据包添加序列号
- 重要数据需要应答机制
- 设置500ms的发送间隔
4. 系统调试与性能优化
4.1 RFID抗干扰实战
在金属货架环境中遇到识别率下降问题,通过以下措施改善:
- 在天线外围加装3mm厚的ABS塑料隔离层
- 调整Mifare_Request()函数的等待超时从5ms增至20ms
- 在寻卡阶段添加重试机制:
c复制do {
status = MFRC522_Request(PICC_REQIDL, &TagType);
if(status == MI_OK) break;
DelayMs(10);
} while(retry++ < 3);
4.2 功耗控制技巧
虽然系统接市电,但为预防停电做了低功耗设计:
- 空闲时关闭RFID模块电源(GPIO控制MOS管)
- DHT11采样间隔从1s调整为5s
- OLED启用局部刷新模式
实测电流对比:
| 模式 | 电流 | 持续时间占比 |
|---|---|---|
| 全速运行 | 85mA | 15% |
| RFID激活 | 120mA | 5% |
| 低功耗待机 | 35mA | 80% |
4.3 压力传感器校准实录
重量检测的准确性直接影响库存管理,我们的校准步骤:
- 准备标准砝码组(1kg/5kg/10kg)
- 每个重量等级采集10次ADC值取平均
- 用最小二乘法拟合曲线:
python复制# 校准数据处理示例
import numpy as np
weights = np.array([0, 1000, 5000, 10000]) # 克
adc_values = np.array([102, 1050, 5012, 10030])
coeff = np.polyfit(adc_values, weights, 1)
print(f"斜率:{coeff[0]:.4f} 截距:{coeff[1]:.2f}")
将得到的斜率k和截距b写入STM32的Flash,上电时读取。
5. 典型问题排查指南
5.1 RFID读卡失败排查流程
mermaid复制graph TD
A[读卡失败] --> B[检查电源电压]
B -->|正常| C[测试SPI通信]
B -->|异常| D[检查LDO和滤波电容]
C -->|正常| E[测量天线谐振频率]
C -->|异常| F[检查引脚连接和配置]
E -->|偏离13.56MHz| G[调整匹配电路]
E -->|正常| H[检查卡片类型]
5.2 常见错误代码速查表
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| ERR01 | RFID通信超时 | 检查模块供电/SPI接线 |
| ERR02 | 重量校验不匹配 | 重新校准传感器/检查货物摆放 |
| ERR03 | WiFi连接失败 | 重置ESP8266/检查AT指令序列 |
| ERR04 | 存储空间不足 | 清理历史记录/扩展存储 |
| ERR05 | 温湿度传感器异常 | 检查DHT11接线/更换模块 |
5.3 云端连接不稳定优化
我们最终采用的稳健连接方案:
- 双网络冗余:同时保存最近可用的两个AP信息
- 心跳包机制:每30秒发送0x00指令维持连接
- 断线自恢复:检测到三次发送失败后自动重启模块
对应的AT指令处理流程:
c复制void WiFi_Recovery(void) {
ESP8266_SendCmd("AT+RST", 1000);
DelayMs(3000);
ESP8266_SendCmd("AT+CWMODE=1", 500);
ESP8266_SendCmd("AT+CWJAP=\"SSID1\",\"PWD1\"", 3000);
if(WaitResponse("FAIL", 1000)) {
ESP8266_SendCmd("AT+CWJAP=\"SSID2\",\"PWD2\"", 3000);
}
}
这个项目给我的深刻启示是:工业级可靠性需要从硬件选型、软件容错到运维策略的全链条设计。现在系统已稳定运行超过180天,累计处理了3200多次出入库操作,期间仅因电网波动重启过2次。对于想要复现的朋友,建议重点关注电源滤波和通信协议的健壮性设计。