在这里插入代码片
最近设计了一个项目家用视力检测仪,与大家分享一下:
一、基本介绍
项目名:家用视力检测仪
项目编号:mcuclub-dz-1056
单片机类型:STM32F103C8T6
具体功能:
1.超声波传感器测距离(检测人的距离、距离阈值动态调整:根据用户身高和检测场景,通过按键或APP设置个性化距离阈值)
2.光敏传感器测光线以及补光(太暗了就调亮 太亮了就调暗 正常就提示:光线正常 可以正常测试)
3.语音播报模块(开始检测的提示、站的太远或太近的提示、光线的提示、测量结果播报等)
4.语音识别(用户说上、下、左、右)
5.温湿度传感器(监测检测环境温湿度,补偿因环境变化导致的测量误差如镜片雾化影响成像等、监测环境干扰(当环境光变化>10%时暂停测试并播报环境异常,避免因镜片雾化导致误判)、空气质量预警(VOC>2000ppb触发通风建议(语音播报提醒)))
6.显示屏也显示测试结果
7.数据云端同步:通过Wi-Fi模块上传检测数据至云端,生成长期视力健康报告。
二、32实物图
单片机型号:STM32F103C8T6
板子为绿色PCB板,两层板,厚度1.2,上下覆铜接地。元器件基本上为插针式,个别降压芯片会使用贴片式。
供电接口:TYPE-C
三、原理图
软件版本:AD2013
电路连线方式:网络标号连线方式
注意:原理图只是画出了模块的引脚图,而并不是模块的内部结构原理图
本设计以STM32F103C8T6单片机为核心控制器,结合多种模块构建家用视力检测系统,系统包括中控部分、输入部分和输出部分。中控部分采用STM32F103C8T6单片机,其主要功能是采集输入数据并进行处理,进而控制输出部分。输入部分由以下模块组成:第一部分是超声波测距模块,用于检测用户距离并支持动态阈值调整;第二部分是光照检测模块,用于环境光线检测;第三部分是语音识别模块,用于接收用户方向指令;第四部分是温湿度检测模块,用于环境监测;第五部分是空气质量检测模块,用于空气质量检测;第六部分是按键模块,用于参数设置;第七部分是供电模块,为系统提供电源支持。输出部分由以下模块组成:第一部分是LED灯模块,用于自动调节检测环境亮度;第二部分是语音播报模块,用于提供操作引导和结果播报;第三部分是显示模块,用于显示检测结果和环境参数;除此之外还有WiFi模块,用于将检测数据同步至云端。系统框图如图3.1所示。
四、PCB图
由原理图导出,封装很大一部分都是作者自己绘制,不提供封装库,只提供连接好的源文件。中间有一个项目编号,隐藏在单片机底座下,插入单片机后不会看到。
两层板,上下覆铜接地。
五、系统框图
本设计以STM32F103C8T6单片机为核心控制器,结合多种模块构建家用视力检测系统,系统包括中控部分、输入部分和输出部分。中控部分采用STM32F103C8T6单片机,其主要功能是采集输入数据并进行处理,进而控制输出部分。输入部分由以下模块组成:第一部分是超声波测距模块,用于检测用户距离并支持动态阈值调整;第二部分是光照检测模块,用于环境光线检测;第三部分是语音识别模块,用于接收用户方向指令;第四部分是温湿度检测模块,用于环境监测;第五部分是空气质量检测模块,用于空气质量检测;第六部分是按键模块,用于参数设置;第七部分是供电模块,为系统提供电源支持。输出部分由以下模块组成:第一部分是LED灯模块,用于自动调节检测环境亮度;第二部分是语音播报模块,用于提供操作引导和结果播报;第三部分是显示模块,用于显示检测结果和环境参数;除此之外还有WiFi模块,用于将检测数据同步至云端。系统框图如图3.1所示。
六、软件设计流程
七、部分程序展示
软件版本:keil5
逻辑程序和驱动程序分开,分布于main.c和其他.c文件
/**********************************
函数名:处理函数
传参值:无
返回值:无
**********************************/
void Manage_Function(void)
{
if(display_num == 0) //测量界面
{
if(flag_zb == 1)
{
if(light_value > light_max) //光照大于设置最大值,关闭灯光
{
if(time_num % 10 == 0)
{
if(flag_gear > 0)
flag_gear --;
}
}
else if(light_value < light_min) //光照小于设置最小值,灯光最亮
{
if(time_num % 10 == 0)
{
if(flag_gear < 10)
flag_gear++;
}
}
else //光照处于设置的上下限值之间,根据光照值调节灯光亮度
{
Huart2_Send_Str(" 光线正常 可以正常测试");
Delay_ms(3000);
flag_zb = 2;
}
}
else if(flag_zb == 2)
{
if(distance_value < distance_min)
{
if(time_num % 100 == 0)
{
Huart2_Send_Str(" 距离过近");
}
}
else if(distance_value > distance_max)
{
if(time_num % 100 == 0)
{
Huart2_Send_Str(" 距离过远");
}
}
else
{
if(temp_value > temp_max*10 || temp_value < temp_min*10)
{
Huart2_Send_Str(" 温度异常 停止测试");
flag_zb = 0;
}
else if(humi_value > humi_max*10 || humi_value < humi_min*10)
{
Huart2_Send_Str(" 湿度异常 停止测试");
flag_zb = 0;
}
else
{
Huart2_Send_Str(" 距离正常,温湿度正常 开始测试");
Delay_ms(3000);
light_jl = light_value;
flag_zb = 3;
huart3_data = 0x00;
}
}
}
else if(flag_zb == 3) //开始测试
{
if(flag_answer == 1) //开始回答
{
flag_timer_begin = 1;
if(huart3_data != 0x00) //有按键按下时计时清零
{
time_5s = 0;
if(flag_buf == 0) //显示灯指示数组0
{
if(dir_buf0[flag_index] == huart3_data) //如果按到正确的按键,且没有错位,继续往下测试,反之记错
{
if(flag_error == 0)
flag_index++;
}
else
flag_error++;
}
else if(flag_buf == 1) //显示灯指示数组1
{
if(dir_buf1[flag_index] == huart3_data)
{
if(flag_error == 0)
flag_index++;
}
else
flag_error++;
}
else if(flag_buf == 2) //显示灯指示数组2
{
if(dir_buf2[flag_index] == huart3_data)
{
if(flag_error == 0)
flag_index++;
}
else
flag_error++;
}
else //显示灯指示数组3
{
if(dir_buf3[flag_index] == huart3_data)
{
if(flag_error == 0)
flag_index++;
}
else
flag_error++;
}
flag_broadcast = 1;
huart3_data = 0x00;
}
else //计时五秒钟,超时算错一次
{
if(flag_1s == 1)
{
flag_1s = 0;
time_5s++;
}
if(time_5s >= 10)
{
time_5s = 0;
flag_error++;
flag_broadcast = 1;
}
}
if(flag_broadcast == 1)
{
flag_broadcast = 0;
switch(flag_error) //判断错了几次
{
case 0: //错误次数为0,则一直测试,直到测到最后一个后播报相应的视力值,停止答题
if(flag_index >= 13)
{
Huart2_Send_Str("本次测试结束,您的视力值为:%d点%d",sco_buf[flag_index/2] / 10,sco_buf[flag_index/2] % 10);
flag_sl = sco_buf[flag_index/2];
Aliyun_Send_Data_sl();
flag_index = 12;
flag_answer = 0;
}
else
Huart2_Send_Str("回答正确");
break;
case 1: //错误次数为1,则判断是不是第一个灯,是则直接播报视力
if(flag_index == 0)
{
Huart2_Send_Str("本次测试结束,您的视力值为:%d点%d",sco_buf[flag_index/2] / 10,sco_buf[flag_index/2] % 10);
flag_sl = sco_buf[flag_index/2];
Aliyun_Send_Data_sl();
flag_answer = 0;
}
else //错误次数为1,且不为第一个灯,判断是那一行的第一个还是第二个灯,错的是第一个则播报回答错误后再判断一次视力
{
if(flag_index % 2 == 1)
{
Huart2_Send_Str("回答错误");
flag_index++;
}
else //错的是第二个灯则播报视力值
{
Huart2_Send_Str("本次测试结束,您的视力值为:%d点%d",sco_buf[flag_index/2] / 10,sco_buf[flag_index/2] % 10);
flag_sl = sco_buf[flag_index/2];
Aliyun_Send_Data_sl();
flag_answer = 0;
}
}
break;
case 2: //错两个则播报上一行的视力值
Huart2_Send_Str("本次测试结束,您的视力值为:%d点%d",sco_buf[flag_index/2 - 1] / 10,sco_buf[flag_index/2 - 1] % 10);
flag_sl = sco_buf[flag_index/2];
Aliyun_Send_Data_sl();
flag_answer = 0;
break;
default:
break;
}
}
if(((light_value - light_jl) > light_jl / 10.0) || ((light_jl - light_value) > light_jl / 10.0) || humi_value > humi_max*10 || humi_value < humi_min*10 || temp_value > temp_max*10 || temp_value < temp_min*10)
{
flag_answer = 0;
Huart2_Send_Str(" 环境异常,本次测试结束,测试结果无效");
flag_zb = 0;
HC595_Function(0xFFFFFFFF);
flag_timer_begin = 0;
}
}
else //停止回答
{
flag_timer_begin = 0; //停止计时
flag_zb = 0;
}
}
if(TVOC_value > TVOC_max) //空气质量预警(VOC>2000ppb触发通风建议(语音播报提醒)))
{
if(time_num % 100 == 0)
{
Huart2_Send_Str(" 空气质量过高,请打开通风");
}
}
}
else //设置界面,关闭加热、制冷及声光报警
{
flag_timer_begin = 0;
}
if(flag_finish_5s == 1) //5秒上传一次数据
{
flag_begin_5s = 0;
Aliyun_Send_Data();
flag_begin_5s = 1;
}
}