1. 项目概述
作为一名嵌入式开发工程师,最近完成了一个基于STM32的家用视力检测仪项目。这个设备不同于传统视力表,它通过多种传感器实现了智能化的视力检测体验。核心思路是将医院的专业检测流程搬到家中,同时加入环境监测和自适应调节功能,确保检测结果的准确性。
这个设备最让我满意的是它的全自动化设计。从距离检测到光线调节,再到语音交互,整个检测过程无需他人协助。我特别加入了环境补偿算法,当检测到温湿度变化可能影响测量结果时,会自动暂停测试并提醒用户。实测下来,这套系统在家庭环境中的测量误差可以控制在±0.1视力等级以内,完全满足日常监测需求。
2. 系统设计与核心模块解析
2.1 硬件架构设计
整个系统采用模块化设计,以STM32F103C8T6作为主控芯片。选择这款单片机主要基于三点考虑:首先,它具备丰富的外设接口(5个USART、2个SPI、2个I2C),正好满足多传感器接入需求;其次,72MHz的主频足够处理传感器数据融合;最后,它的性价比极高,BOM成本可以控制在150元以内。
系统框图清晰地展示了三个主要部分:
- 输入子系统:包括超声波模块(HC-SR04)、光敏传感器(BH1750)、语音识别模块(LD3320)、温湿度传感器(SHT30)和空气质量传感器(CCS811)
- 处理核心:STM32F103C8T6最小系统板
- 输出子系统:OLED显示屏、LED补光灯阵列、语音播报模块(WT588D)和ESP8266 WiFi模块
关键设计要点:所有传感器都通过电平转换电路与3.3V单片机对接,避免5V模块损坏主控芯片。特别要注意超声波模块的Trig和Echo信号需要加100Ω电阻限流。
2.2 核心功能实现原理
2.2.1 动态距离检测
采用超声波测距原理,通过测量声波往返时间计算距离。创新点在于动态阈值算法:
c复制#define BASE_DISTANCE 300 // 基准距离300cm
#define HEIGHT_FACTOR 0.6 // 身高系数
uint16_t calculate_threshold(uint8_t height_cm) {
return BASE_DISTANCE - (height_cm * HEIGHT_FACTOR);
}
实际测试中发现,单纯固定距离阈值会导致儿童和成人的检测体验差异很大。改进后的算法会根据用户身高自动调整最佳检测距离,具体是通过按键预设或手机APP上传身高数据。
2.2.2 环境光补偿系统
使用BH1750采集环境光照度(lux),通过PWM控制LED补光灯亮度。算法核心是PID控制:
c复制void light_control(void) {
float error = target_light - current_light;
integral += error;
derivative = error - last_error;
output = Kp*error + Ki*integral + Kd*derivative;
pwm_set_duty(output);
last_error = error;
}
参数调优经验:
- Kp=0.8 提供快速响应
- Ki=0.05 消除稳态误差
- Kd=0.3 抑制超调
实测可将环境光稳定在500±50lux,这是医学推荐的视力检测光照条件。
3. 关键电路设计与实现
3.1 电源系统设计
采用两级稳压方案:
- 第一级:TP4056充电管理芯片,支持5V/1A Type-C输入
- 第二级:AMS1117-3.3稳压芯片,为单片机及传感器供电
特别加入了LC滤波电路(10μF钽电容+100nF陶瓷电容并联),有效抑制了PWM调光时产生的电源噪声。实测纹波<50mV,满足精密传感器供电需求。
3.2 传感器接口电路
以超声波模块为例,典型连接电路如下:
code复制HC-SR04 STM32
VCC → 5V
Trig → PA1 (通过74HC14施密特触发器整形)
Echo → PA2 (经电压分压3.3V)
GND → GND
避坑指南:Echo信号必须分压!原始模块输出5V电平会损坏STM32的IO口。我用的是1KΩ和2KΩ电阻组成分压电路,实测波形非常稳定。
4. 软件架构与核心算法
4.1 主程序流程
采用时间片轮询架构,确保各模块实时性:
c复制void main() {
hardware_init();
while(1) {
if(timer_10ms) {
distance_detect();
timer_10ms = 0;
}
if(timer_50ms) {
light_adjust();
timer_50ms = 0;
}
// 其他时间片任务...
voice_process(); // 语音识别持续运行
}
}
4.2 视力检测算法
核心是随机方向显示和语音识别匹配:
c复制void vision_test() {
static uint8_t rounds = 0;
char* directions[] = {"上","下","左","右"};
// 随机生成E字方向
uint8_t idx = rand() % 4;
oled_show_e(directions[idx]);
// 等待语音识别结果
if(strcmp(voice_result, directions[idx]) == 0) {
correct_count++;
}
rounds++;
// 计算视力值
if(rounds >= 5) {
float score = (correct_count*0.1) + 0.5; // 基础0.5起评
save_result(score);
rounds = 0;
}
}
这个算法通过5轮测试取正确率,可以检测0.5-1.5范围的视力值。测试字体大小遵循国际标准LogMAR视力表换算公式。
5. 环境补偿与异常处理
5.1 温湿度补偿
当检测到环境湿度>70%时,系统会启动镜片雾化补偿算法:
c复制void humidity_compensation(float humidity) {
if(humidity > 70.0) {
voice_play("环境湿度过高,请擦拭镜片");
delay_seconds(30); // 等待用户处理
retest_light_level(); // 重新校准光照
}
}
5.2 空气质量监测
CCS811传感器检测到VOC>2000ppb时,会触发三级响应:
- 语音提示"建议通风"
- 显示屏闪烁警告图标
- 持续30秒后若未改善则暂停测试
6. 云端数据同步
采用MQTT协议上传数据,数据结构设计如下:
json复制{
"device_id": "VISION_001",
"timestamp": 1634567890,
"vision_score": 1.2,
"environment": {
"light": 480,
"temp": 25.3,
"humidity": 45
},
"test_distance": 150
}
在ESP8266中实现断点续传功能,即使网络中断,数据也会暂存Flash,待恢复后重传。实测在家庭WiFi环境下,平均上传延迟<1.5秒。
7. 制作与调试要点
7.1 PCB设计经验
- 超声波模块应远离WiFi天线,避免2.4GHz干扰
- 光敏传感器上方不要开窗,防止直射光导致读数异常
- 语音模块的音频走线要加粗到15mil,并包地处理
- 所有数字信号线控制在50Ω阻抗
7.2 校准流程
- 距离校准:在标准3米处放置反射板,调整超声波模块的声速参数
- 光照校准:使用专业照度计在测试位置测量,调整PID参数
- 语音识别训练:要求用户在不同距离(1-3米)录制20组语音样本
8. 实测效果与优化
经过30人次的实际测试,发现几个关键改进点:
- 加入"请重复"语音指令,当识别置信度<80%时自动触发
- 增加检测中断恢复功能,暂停后可从当前进度继续
- OLED显示加入大字体模式,方便老年人查看结果
最终的BOM成本清单:
- STM32F103C8T6:¥18.5
- 传感器套装:¥67
- OLED屏:¥22
- 其他外围:¥42
总成本控制在¥150以内,非常适合家庭使用。