1. 项目概述与核心功能解析
在商场、车站等公共场所,人流控制一直是个让人头疼的问题。去年我参与某商业综合体项目时,亲眼目睹了传统人工管控的种种不便——高峰期排队混乱、突发情况响应迟缓、数据统计全靠估算。这促使我开始研究基于单片机的人流控制器系统,经过三个版本迭代,最终形成了这套稳定可靠的解决方案。
这套系统的核心在于将硬件感知与智能决策相结合。主控采用STM32F103C8T6单片机,通过红外对管实时检测人流,配合MLX90614非接触式红外测温模块实现体温筛查。当检测到人员接近时,第一道闸门(由SG90舵机驱动)立即开启;体温正常者第二道闸门放行,异常者触发语音报警。所有数据通过ESP8266 WiFi模块上传至腾讯云物联网平台,管理人员可通过小程序远程监控和调控。
关键设计亮点:双闸门缓冲设计能有效防止尾随,限流算法避免人群过度聚集,离线缓存机制确保网络中断时基础功能不受影响。
2. 硬件架构深度拆解
2.1 主控电路设计要点
选择STM32F103C8T6主要基于三点考量:首先,72MHz主频足够处理多传感器数据流;其次,内置的硬件SPI接口可驱动OLED实现60fps流畅刷新;最重要的是其丰富的外设资源(5个USART、2个I2C、3个SPI)完美适配本项目多模块协同需求。实际布线时需注意:
- 在NRST引脚加0.1μF去耦电容
- BOOT0引脚通过10K电阻下拉
- 晶振电路尽量靠近芯片(我的PCB布局中控制在15mm内)
2.2 传感器选型对比
红外对管测试了三种方案:
- E18-D80NK(漫反射式):安装简便但易受环境光干扰
- TCST2103(槽型光电):精度高但检测距离仅5mm
- ITR9909(对射式):最终选用方案,10cm检测距离,抗干扰强
测温模块选用MLX90614ESF-BAA,其医疗级精度(±0.5℃)远超DS18B20等接触式传感器。需注意:
- I2C总线需加1K上拉电阻
- 传感器视角角为35°,安装时需保持水平
- 定期用酒精棉清洁光学窗口
2.3 电源系统优化
实测发现舵机启动瞬间电流可达1.2A,为此设计了两级供电:
- 第一级:AMS1117-3.3V给MCU和传感器供电
- 第二级:LM2596可调降压模块单独给舵机供电
在PCB布局时将两种地平面用0Ω电阻隔离,噪声降低约40%。
3. 关键代码实现剖析
3.1 主程序状态机设计
采用时间片轮询架构,确保各任务实时性:
c复制void main() {
HAL_Init();
SystemClock_Config();
while(1) {
static uint32_t tick = 0;
if(HAL_GetTick() - tick >= 10) { // 10ms周期
tick = HAL_GetTick();
Key_Scan(); // 按键扫描
Sensor_Update(); // 传感器更新
FSM_Handler(); // 状态机处理
OLED_Refresh(); // 显示刷新
}
WiFi_Process(); // 网络处理(非阻塞)
}
}
3.2 双闸门控制算法
创新性地采用"缓冲-放行"机制:
c复制void Gate_Control() {
if(people_count >= limit_count) {
Close_Gate(BOTH_GATES);
return;
}
if(gate1_triggered && !temp_check_done) {
Open_Gate(GATE1);
Start_Temp_Check();
}
if(temp_normal && gate1_opened) {
Delay_ms(800); // 确保人员完全进入缓冲区域
Open_Gate(GATE2);
people_count++;
}
}
3.3 温度补偿算法
实测发现环境温度会影响红外测温精度,因此加入补偿:
c复制float Get_Compensated_Temp() {
float ambient = mlx90614.readAmbientTemp();
float object = mlx90614.readObjectTemp();
// 补偿公式通过实验数据拟合得出
if(ambient < 25.0f)
return object + (25.0f - ambient)*0.12f;
else
return object - (ambient - 25.0f)*0.08f;
}
4. 物联网平台对接实战
4.1 腾讯云物联网平台配置
- 在腾讯IoT Explorer创建新产品
- 定义数据模板:
- 属性:当前人数/温度/工作模式(RO)
- 行为:设置阈值/远程开闸(WO)
- 生成设备三元组(ProductID/DeviceName/DeviceSecret)
4.2 ESP8266固件开发
使用AT指令集实现数据上报:
c复制void WiFi_Report_Data() {
char json[256];
sprintf(json, "{\"method\":\"report\",\"params\":{\"count\":%d,\"temp\":%.1f}}",
people_count, current_temp);
ESP_Send("AT+MQTTPUB=0,\"$thing/up/property/XXXXXX\",%d,0", strlen(json));
ESP_Send(json);
}
4.3 小程序开发关键点
- 使用wx.connectWifi()实现AP配网
- 通过wx.onBLEConnectionStateChange监听设备状态
- 数据绑定采用observers设计模式实现实时更新
5. 常见问题排查手册
5.1 红外对管误触发
现象:无人经过时闸门自动开启
排查步骤:
- 用万用表测量接收管输出电压(正常应>3V)
- 检查发射管电流是否在20mA左右
- 在代码中加入软件防抖:
c复制if(Read_IR() == TRIGGERED) {
if(++trigger_count > 3) { // 连续3次检测到才确认
Set_Trigger_Flag();
}
}
5.2 WiFi频繁掉线
解决方案:
- 在ESP8266电源引脚并联470μF电容
- 修改AT指令为:
c复制AT+CIPRECONNCFG=1,500,10 // 自动重连配置
- 添加心跳包机制(每30秒发送0xAA)
5.3 舵机卡顿
根本原因:电源压降导致扭矩不足
优化措施:
- 在舵机电源线正负极间加2200μF电容
- 修改PWM控制曲线:
c复制void Set_Gate_Angle(uint8_t angle) {
// 分段控制避免突变
for(int i=current_angle; i!=angle; i+= (angle>i)?1:-1) {
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 500 + i*10);
HAL_Delay(20);
}
}
6. 实测性能数据对比
在万达广场进行的72小时连续测试显示:
| 指标 | 传统方案 | 本系统 |
|---|---|---|
| 通行效率 | 35人/分钟 | 58人/分钟 |
| 体温漏检率 | 12% | 0.3% |
| 峰值功耗 | 45W | 18W |
| 网络中断恢复时间 | - | <3s |
特别在2023年元旦跨年活动中,系统成功应对了单小时超2000人次的流量压力,期间通过小程序动态调整限流人数阈值6次,未发生任何拥堵事件。
这个项目给我最深的体会是:硬件设计必须预留30%的性能余量,关键传感器一定要做冗余校验。下次迭代我计划加入3D-ToF传感器辅助人数统计,并尝试用RT-Thread实现更高效的任务调度。