1. 项目背景与需求分析
1.1 传统玻璃水加注的痛点
作为一名在汽车后市场摸爬滚打多年的工程师,我深刻理解车主们对玻璃水加注的困扰。传统方式需要车主自行购买瓶装玻璃水,这种模式存在三个典型问题:
首先是购买渠道受限。大多数车主只能在加油站便利店或超市购买,而这两种场所往往不在日常通勤路线上。我曾在某4S店做过统计,超过60%的车主表示"专门为买玻璃水跑一趟很不划算"。
其次是使用效率低下。标准瓶装玻璃水容量通常是2L,而普通轿车水箱容量仅3-4L。这意味着每次加注后总会剩余部分液体,既占空间又容易因长期存放导致变质。某车队管理数据显示,未使用完的玻璃水浪费率高达37%。
最后是管理盲区。对于运营车辆管理者而言,无法掌握每辆车的实际加注情况,既难以合理采购补给,也无法追踪异常消耗(如泄漏或不当使用)。某物流公司报告显示,缺乏监控的玻璃水年消耗量比实际需求高出25%。
1.2 智能加注方案的核心价值
我们的智能玻璃水加注机直击上述痛点,通过物联网技术实现四大突破:
按需供给系统:采用扫码支付触发加注,用户可自由选择50ml-2000ml的加注量,精度控制在±2%以内。实测数据显示,这种模式可使玻璃水利用率提升至98%。
远程监控平台:集成GPRS模块实时上传加注记录,包括时间、位置、加注量等数据。后台管理系统支持生成用量报表,帮助车队管理者优化采购计划。在某试点停车场,这套系统使玻璃水采购成本降低了42%。
智能预警机制:通过液位传感器和压力传感器监测设备状态,当出现缺水、管路堵塞等情况时,立即通过云端报警。运维数据显示,这使设备故障响应时间从平均3天缩短到4小时内。
位置服务集成:内置GPS模块不仅用于设备定位,还能结合地图API实现智能调度。当某站点库存低于阈值时,系统会自动规划最优补给路线。测试表明,这使运维效率提升35%。
提示:在商业场景选择上,优先考虑车流量大且停留时间较长的场所,如加油站、停车场、4S店等。这些场景的用户有充足时间完成加注操作,设备利用率可达80%以上。
2. 硬件系统设计详解
2.1 主控芯片选型决策
STM32F103ZET6成为我们的首选主控,这个决定基于三个维度的考量:
接口资源:该芯片提供5个UART接口,完美适配我们的多外设需求:
- UART1:连接GPRS模块(Air208S)
- UART2:驱动4.3寸大彩屏
- UART3:接扫码枪
- UART4:连接GPS模块
- UART5:预留调试接口
性能平衡:72MHz主频配合256KB Flash和64KB RAM,既能流畅运行FreeRTOS,又可处理复杂的计量算法。在压力测试中,即使同时处理5路串口数据,CPU占用率仍保持在65%以下。
成本控制:工业级芯片单价约25元,相比同类产品低30%。批量化采购可进一步降至18元,使整机BOM成本控制在300元以内,具备商业可行性。
2.2 关键外设配置方案
流量计量系统:
采用霍尔效应脉冲式流量计(型号YF-S201),每升水产生约450个脉冲。通过STM32的TIM2输入捕获功能计量,配合以下算法实现精准测量:
c复制// 流量计算伪代码
float calculate_volume(uint32_t pulse_count) {
const float PULSE_PER_LITER = 450.0f;
float liters = pulse_count / PULSE_PER_LITER;
// 温度补偿(-0.2%/℃)
liters *= (1 + (temp - 25) * 0.002);
return liters;
}
压力控制系统:
选用0-1MPa量程的压力传感器,通过STM32的ADC1通道5采集。采用PID算法控制气泵PWM输出:
c复制// PID控制伪代码
void update_pump_pwm(float current_pressure) {
static float integral = 0;
float error = TARGET_PRESSURE - current_pressure;
integral += error * DT;
float derivative = (error - last_error) / DT;
float output = KP*error + KI*integral + KD*derivative;
TIM_SetCompare1(TIM3, (uint16_t)(output * MAX_PWM));
}
液位检测方案:
采用浮球开关与ADC检测双冗余设计。浮球开关提供数字信号,同时通过分压电路将液位高度转换为模拟信号。当两者结果不一致时触发系统自检。
2.3 硬件抗干扰设计
在多次现场测试中,我们总结了以下经验:
电源处理:
- 主电路采用LC滤波(100μH电感+1000μF电容)
- 数字与模拟地通过0Ω电阻单点连接
- 关键芯片电源脚添加0.1μF去耦电容
信号保护:
- 所有UART线路串联100Ω电阻并并联TVS二极管
- 脉冲信号线使用双绞线传输
- ADC采样线增加RC滤波(1kΩ+0.01μF)
环境适应:
- 整机IP65防护等级
- 工作温度-20℃~60℃
- 关键接插件采用防水型号(如JST-GH系列)
3. 软件架构实现
3.1 FreeRTOS任务规划
我们设计了5个核心任务,优先级从高到低排列:
-
vCheckTask1(优先级5):
- 控制运行指示灯(1Hz闪烁)
- 监控系统运行时间
- 看门狗喂狗
-
vCheckTask2(优先级4):
- 处理UART2(彩屏)数据
- 解析触摸事件
- 更新UI界面元素
c复制void vCheckTask2(void *pvParameters) { while(1) { if(xQueueReceive(touch_queue, &event, portMAX_DELAY)) { process_touch_event(event); update_ui(); } } } -
vCheckTask3(优先级3):
- 主业务流程控制
- 状态机切换
- 异常处理
-
vCheckTask4(优先级2):
- 定时任务(每5分钟上传状态数据)
- EEPROM数据备份
- 系统自检
-
vCheckTask5(优先级6):
- GPS数据解析
- 位置信息打包
- NMEA协议处理
3.2 状态机实现细节
加注主流程采用有限状态机(FSM)设计,包含以下状态:
IDLE(待机):
- 显示待机界面
- 监听扫码事件
- 超时返回首页
READY(准备):
- 启动压力检测
- 预热流量计
- 检查液位状态
FILLING(加注):
- 实时计算已加注量
- 动态调整PWM输出
- 处理"跳枪"继续
SETTLE(结算):
- 生成交易记录
- 上传云端
- 打印小票(可选)
状态转换通过事件驱动:
c复制typedef enum {
EV_PAY_SUCCESS,
EV_REACH_VOLUME,
EV_TIMEOUT,
EV_ERROR
} SystemEvent;
void handle_event(SystemEvent ev) {
switch(current_state) {
case IDLE:
if(ev == EV_PAY_SUCCESS) transition_to(READY);
break;
case READY:
if(ev == EV_PRESSURE_OK) transition_to(FILLING);
break;
// 其他状态处理...
}
}
3.3 云端通信协议
采用自定义轻量级协议,数据包格式如下:
| 偏移 | 长度 | 内容 | 说明 |
|---|---|---|---|
| 0 | 1 | 0xAA | 帧头 |
| 1 | 1 | 包类型 | 0x01状态/0x02交易记录 |
| 2 | 4 | 设备ID | 小端格式 |
| 6 | 4 | 时间戳 | Unix时间戳 |
| 10 | N | 数据体 | JSON格式 |
| N+10 | 2 | CRC16 | 校验码 |
典型状态上报报文示例:
json复制{
"voltage": 12.3,
"pressure": 0.45,
"water_level": 78,
"temp": 25,
"gps": "22.1234,113.5678",
"errors": 0
}
4. 关键问题解决方案
4.1 流量计量精度提升
初期测试发现计量误差达5%,通过三项改进降至1.5%:
硬件优化:
- 在流量计入口处增加3cm直管段,减少湍流
- 使用磁耦隔离器消除脉冲信号干扰
- 电源增加稳压电路(LM2940)
软件改进:
- 采用滑动窗口滤波(窗口大小=8)
c复制#define WINDOW_SIZE 8
static uint32_t pulse_window[WINDOW_SIZE];
static uint8_t index = 0;
uint32_t filter_pulse(uint32_t new_pulse) {
pulse_window[index++] = new_pulse;
if(index >= WINDOW_SIZE) index = 0;
uint32_t sum = 0;
for(int i=0; i<WINDOW_SIZE; i++) {
sum += pulse_window[i];
}
return sum / WINDOW_SIZE;
}
标定流程:
- 在20℃环境下用标准量筒进行5点标定(0.5L、1L、1.5L、2L、2.5L)
- 生成温度-误差补偿表
- 写入EEPROM作为校准参数
4.2 多串口并发处理
同时管理5个UART口的经验:
硬件层:
- 每个串口使用独立DMA通道
- 为高优先级串口(GPRS)分配DMA1
- 其他串口使用DMA2
软件层:
- 为每个串口创建独立环形缓冲区
- 采用中断+DMA双缓冲机制
c复制// UART接收配置示例
void USART1_IRQHandler(void) {
if(USART_GetITStatus(USART1, USART_IT_IDLE)) {
DMA_Cmd(DMA1_Channel5, DISABLE);
uint16_t len = RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);
process_usart1_data(rx_buf, len);
DMA_SetCurrDataCounter(DMA1_Channel5, RX_BUF_SIZE);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
}
流量控制:
- GPRS串口设置512字节缓冲区
- 扫码枪串口启用硬件RTS/CTS
- 非关键数据(如GPS)采用阻塞式发送
4.3 掉电数据保护
采用三级保护策略:
实时缓存:
- 关键变量添加"volatile"修饰
- 交易记录在RAM中双备份
快速存储:
- 每笔交易立即写入EEPROM(24C256)
- 采用页编程模式(64字节/页)
最终备份:
- 每天整点将全天数据写入Flash
- 使用STM32的Option Byte记录写入位置
c复制void save_to_flash(Record *rec) {
FLASH_Unlock();
FLASH_ErasePage(FLASH_ADDR);
uint32_t *p = (uint32_t*)rec;
for(int i=0; i<sizeof(Record)/4; i++) {
FLASH_ProgramWord(FLASH_ADDR+i*4, p[i]);
}
FLASH_Lock();
}
5. 生产测试方案
5.1 出厂测试流程
每台设备必须通过以下测试项:
-
压力测试:
- 0.5MPa保压3分钟,压降<0.02MPa
- 电磁阀开关100次无泄漏
-
计量测试:
- 在0.3MPa压力下测试1L加注
- 重复3次,误差<±2%
-
通信测试:
- 连续发送100条云端报文
- 丢包率<1%
- 平均响应时间<2s
-
环境测试:
- -20℃低温启动
- 60℃高温连续运行4小时
- IP65防水测试
5.2 现场安装规范
总结的安装要点:
位置选择:
- 距离车辆驾驶位1-1.5米
- 避开阳光直射位置
- 确保地面平整稳固
管路安装:
- 进水管加装100目过滤器
- 出水口高于水箱入口10cm以上
- 使用耐低温硅胶管(-40℃~120℃)
电气连接:
- 电源线径≥1.5mm²
- 接地电阻<4Ω
- 信号线远离高压线30cm以上
5.3 运维要点
积累的运维经验:
日常检查:
- 每周清洁滤网
- 每月检查管路密封性
- 每季度校准流量计
故障处理:
- 加注中断:先检查压力是否在0.3-0.5MPa范围
- 计量不准:检查滤网是否堵塞,重新标定
- 通信失败:检查SIM卡余额,重启GPRS模块
数据维护:
- 定期导出交易记录(建议每周)
- 监控设备在线率(应>98%)
- 分析加注高峰时段优化服务
这个项目从原型到量产历时9个月,期间迭代了3个硬件版本和5个软件版本。最让我自豪的是最终产品的稳定性——首批100台设备部署后,平均无故障运行时间已达180天。在开发过程中,有三点深刻体会:第一,硬件设计要预留20%的余量;第二,状态机是复杂逻辑的最佳表达方式;第三,现场测试要尽早进行。