一.系统概述
1. 模块概述:系统集成了语音模块、传感器数据采集模块和蓝牙模块,支持自动/手动模式切换。
2. 自动模式功能:系统启动后进入自动模式,传感器开始检测数据。根据检测到的温度、光照和烟雾数据,判断是否需要开启门窗以保持室内环境。当室内温度超过设定阈值、可燃气体浓度超标或光照弱时,系统自动控制驱动舵机模拟门窗的开合操作。
3. 蓝牙模块控制:使用蓝牙模块实现自动模式和手动模式的切换。通过手机发送字符"3"切换到自动模式,发送字符"4"切换到手动模式。
4. 手动模式功能:在手动模式下,可以使用语音识别模块控制门窗的开关。用户可以说“关”来关闭门窗,说“开”来打开门窗。另外,也可以通过手机蓝牙连接控制门窗,发送字符"1"来打开门窗,发送字符"2"来关闭门窗。
二.电路设计
电路图采用Altium Designer进行设计:
1. 通过STM32F103C8T6单片机作为系统主控,最小系统电路是整个电路的核心;
2. 通过DS18B20进行温度检测,并通过单总线与单片机完成数据通信;
3. 使用光敏电阻模块进行光强检测,传感器的模拟端与单片机的模拟输入端相接;
4. 使用MQ-2进行烟雾浓度检测并将模块的模拟输出脚与单片机的模拟输入脚相接;
5. 通过0.96寸的OLED12864进行数据显示,采用IIC总线的形式与单片机进行通信;
6. 使用LU-ASR01高精度语音识别模块进行语音指令检测,并通过UART串口与单片机进行通信;
7. 通过ESP8266-01S将检测到数据上传到上位机,通过UART串口与单片机进行通信;
8. 通过舵机控制窗户的打开和关闭,舵机的控制线与单片机GPIO口进行连接。
三.程序设计
void qianjian(void)
{
u16 count=0;
while(count<=15)
{
ULN2003_GPIOA_Contol_Moto_Foreward(2);
count++;
}
}
void houtui(void)
{
u16 count=0;
while(count<=15)
{
ULN2003_GPIOA_Contol_Moto_Reversal(2);
count++;
}
}
/************************************
OLED显示屏
************************************/
void OLED_Display_Cotrol(void) //系统显示控制功能实现 OLED显示
{
static u8 timeCount = 0;
static char pl[16]="";
static u8 c = 0;
static float smo;
static u16 light = 0;
static u8 flag = 0;//自动
static u8 flags = 0;//窗帘
static u8 flagsss = 0;//语音
static u8 temperature,humidity;
u8 key_choice=0;
char p1[16]=" ";
static u16 key_value[8] = {30,50,50,1000}; //0 年 1月 2日 3 时 4分 5秒 6药品a 7药品b
u16 count=0;
light = Get_adc_light();
Get_Adc_Convert_mq_so2(&smo);
sprintf((char*)p1,":%d ",(int)light);
OLED_ShowStr(32,2,p1,2);
sprintf((char*)p1,":%d ",(int)smo);
OLED_ShowStr(32,4,p1,2);
DHT11_Read_Data(&temperature,&humidity);
sprintf((char*)p1,":%d ",(int)temperature);
OLED_ShowStr(32,0,p1,2);
sprintf((char*)p1,":%d ",(int)humidity);
OLED_ShowStr(96,0,p1,2);
key_choice = KEY_Scan(0);
if(key_choice==1)
{
c++;
if(c==4)
{
c=0;
}
}
else if(key_choice==2)
{
key_value[c]++;
}
else if(key_choice==3)
{
key_value[c]--;
}
if(c==0)
OLED_ShowCN(48,6,4);
else if(c==1)
OLED_ShowCN(48,6,6);
else if(c==2)
OLED_ShowCN(48,6,8);
else if(c==3)
OLED_ShowCN(48,6,18);
sprintf((char*)pl,"%d ",key_value[c]);
OLED_ShowStr(80,6,pl,2);
OLED_ShowStr(0,6,"SET:",2);
if(flag==0)//自动模式
{
OLED_ShowCN(80,2,16);
OLED_ShowCN(96,2,17);
if(temperature<key_value[0]||humidity<key_value[1])
Relay_0=0;
else
Relay_0=1;
if(smo>key_value[3])
Relay_1=0;
else
Relay_1=1;
if(light>50&&flags==0)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Foreward(2);
count++;
}
flags=1;
count=0;
}
else if(light<50&&flags==1)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Reversal(2);
count++;
}
flags=0;
count=0;
}
}
else if(flag == 1)//手动模式
{
OLED_ShowCN(80,2,14);
OLED_ShowCN(96,2,15);
ASR01_Uart1_HandleD(&flagsss);
if(flags==0&&flagsss==1)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Foreward(2);
count++;
}
flags=1;
count=0;
flagsss=0;
}
else if(flags==1&&flagsss==2)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Reversal(2);
count++;
}
flags=0;
count=0;
flagsss=0;
}
}
timeCount++;
if(timeCount==3){send_datas(&temperature,&humidity);}
else if(timeCount==5){send_datass(&light,&smo);}
else if(timeCount==8){send_datasss(&key_value[0],&key_value[1]);}
else if(timeCount==10){timeCount=0;send_datassss(&key_value[2],&key_value[3]);}
if (Serial_GetRxFlag() == 1)
{
if(CommBuff[0]==0xA5)
{
if(CommBuff[1]==0xFF&&CommBuff[2]==0xFF)
flag = 1;
else if(CommBuff[1]==0xEE&&CommBuff[2]==0xEE)
flag = 0;
if(flag == 1)
{
if(CommBuff[1]==0xAA&&CommBuff[2]==0xAA)
{
key_value[0]++;
}
else if(CommBuff[1]==0xBB&&CommBuff[2]==0xBB)
{
key_value[0]--;
}
else if(CommBuff[1]==0xCC&&CommBuff[2]==0xCC)
{
key_value[1]++;
}
else if(CommBuff[1]==0xDD&&CommBuff[2]==0xDD)
{
key_value[1]--;
}
else if(CommBuff[1]==0x11&&CommBuff[2]==0x11&&flags==0)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Foreward(2);
count++;
}
flags=1;
count=0;
}
else if(CommBuff[1]==0x22&&CommBuff[2]==0x22&&flags==1)
{
while(count<=1000)
{
ULN2003_GPIOA_Contol_Moto_Reversal(2);
count++;
}
flags=0;
count=0;
}
memset(CommBuff,0,BUFFER_SIZE);
}
}
}
}