基于单片机的智能百叶窗设计
收藏关注不迷路!!
🌟文末获取源码+数据库🌟
感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题),项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人
一、摘要
随着科技的进步,社会发展进行加快,人们对人工智能的需求日益增长。。其中智能家居与人们的生活息息相关。是时代发展必不可少的一部分。而如何把智能与传统百叶窗系统相结合就是本文的研究目的。本设计以STM32F407ZGT6单片机、ATK-HC05蓝牙模块、紫外线强度传感器、语音模块、舵机模块、电阻触摸屏为硬件,以FreeRTOS系统、蓝牙串口APP作为软件,以达到用电阻触摸屏发送指令至单片机或者用Android APP通过ATK-HC05发送指令至单片机后控制舵机模块以调节百叶窗的目的,以此来构成基于单片机的智能百叶窗设计。本款设计不仅可以使窗帘进入智能化的领域,而且可以让人们的日常生活更加方便和舒适,从而有效利用科技,更加节能,并为市场开发提供了足够的发展空间。
二、内容设计
本设计基于单片机,然后利用LCD线连接电阻触摸屏,通过电阻触摸屏选择相对应的操作,指令传输到STM32单片机,由STM32单片机根据内部的具体编程对指令进行操作并传输到相应的舵机驱动模块,并实现相应的模式。利用紫外线强度传感器采集紫外线强度,并将信息传到单片机,单片机根据紫外线强度的高低对信息进行处理,再传输到舵机模块使得百叶窗状态发生改变。利用语音模块检测人说话的指令,并且将这一信息传输到单片机,在判断指令之后,单片机指令传输到舵机模块,让百叶窗根据指令变化。利用蓝牙模块使得手机APP与单片机之间进行无线连接,人通过手机APP选择相应指令,指令通过ATK-HC05蓝牙模块传输到单片机,由单片机根据内部的具体编程对指令进行操作并传输到舵机模块,并实现相应的功能。
系统总体设计方案
本设计基于单片机,然后通过对应接口的线材连接到电阻触摸屏,通过电阻触摸屏选择相对应的功能,系统生成对应的指令,然后由单片机根据内部的具体编程对指令进行操作并传输到相应的舵机驱动模块,并实现相应的模式。布置在阳台等位置的紫外线强度传感器同时实时采集紫外线强度,并将信息传到单片机,系统程序根据紫外线强度的高低对信息进行处理并实时展示在控制面板,以及连接系统的Android APP上。也可以根据紫外线的强度自动使得百叶窗状态发生改变。还可以通过语音模块检测人说话的指令,并且将这一信息传输到单片机,在系统判断指令之后,单片机通过控制舵机模块,让百叶窗根据指令产生对应的变化。同时还可以利用蓝牙模块使得Android APP与单片机之间进行无线连接,人通过手机APP选择对应的功能,并产生对应指令通过ATK-HC05模块传输,单片机通过串口接口与蓝牙模块连接,如果APP内部设定为手动模式,则可以手动控制窗帘的开启与关闭,如果是自动模式,则系统可自动根据设定的日出日落时间,以及紫外线强度去控制舵机模块来选择开启或关闭百叶窗帘以及开启百叶窗帘的角度。本设计研究的智能百叶窗设计的工作过程如图2-1所示。

图2-1 工作过程
三、程序设计
#include "main.h"//一些运用到的头文件
/*======================变量========================*/
u32 run_time=0;//开机时间计算
u8 run_time_flag=0;
int lcd_discolor[14]={WHITE,BLACK,BLUE,BRED,
GRED,GBLUE,RED,MAGENTA,
GREEN,CYAN,YELLOW,BROWN,
BRRED,GRAY};//LCD刷屏时使用的颜色
u8 manu_index = 3; //界面索引 会被清零
u8 read_manu=5; //界面索引 不会被清零
u8 m_flag=0; //界面计数
u8 mode=1; //1:手动模式 2:自动模式
u8 state=1; //1:开 2:关
u8 shine=1; //1:Normal 2:PWM
u8 normal_val=100; //PWM正常值
u16 shine_x=200;
u16 tarr=840,tpsc=10;
RTC_TimeTypeDef RTC_TimeStruct; //时间
RTC_DateTypeDef RTC_DateStruct; //日期
u8 occupy=1; //占用说明,为了解决颜色跳变问题
u8 m8_offset=0; //时间设置界面三角形偏移量
SaveTime svtime;
/*==================================================*/
/*定时器14中断服务函数 100us中断*/
u16 pwm = 99;u8 b1_flag = 0;
u16 blink1_count = 0;
u8 count_down=5;
void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
static u16 count = 0;
static u16 run_time_count=0;
if(TIM_GetITStatus(TIM14,TIM_IT_Update)==SET) //溢出中断
{
/*===============================
功能:PWM调节LCD背光
参数:1.pwm:设置占空比
2.count:计数
===============================*/
count++;
if(count < pwm)LCD_LED=1;
else if(count < 100)LCD_LED=0;
else count = 0;
/*===============================
功能:实现某个字段的间隔闪烁功能
参数:1.blink1_count:计数
2.b1_flag:闪烁标志位
===============================*/
switch(read_manu)
{
case 1:
{
if(blink1_count++ > 5000)//界面1的字幕 500ms闪烁
{
blink1_count = 0;
//标志位取反 以达到闪烁功能
if(b1_flag == 1)b1_flag = 0;else if(b1_flag == 0) b1_flag = 1;
if(b1_flag == 1){POINT_COLOR = BLUE;LCD_Chinese(80,145,24,(u8 *)"4602");}
else if(b1_flag == 0){LCD_Fill(80,145,80+24*4,145+24,BLACK);}
}
}break;
case 2:
{
if(m_flag==1)//如果倒计时被激活
if(blink1_count++>10000)//1S
{
blink1_count=0;
if(count_down>0)count_down-=1;
POINT_COLOR = BLUE;LCD_ShowNum(45+8*12,230,count_down,1,16);
if(count_down==0){m_flag=0;manu_index=3;}//倒计时结束都进入界面3
}
}break;
}
//STM32运行时间统计
if(run_time_flag==1){run_time_count++;if(run_time_count>10000){run_time_count=0;run_time++;}}
}TIM_ClearITPendingBit(TIM14,TIM_IT_Update); //清除中断标志位
}
/*主函数*/
int main(void)
{
MYInit();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
/*开始任务任务函数 开始任务创建 其余任务*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建TASK1任务
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
//创建TASK2任务
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
//创建RunTimeStats任务
xTaskCreate((TaskFunction_t )task3_task,
(const char* )"task3_task",
(uint16_t )TASK3_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK3_TASK_PRIO,
(TaskHandle_t* )&Task3Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
/*主要任务函数,负责屏幕刷新、触碰按键处理等任务*/
u8 time_display_flag=0;
void task1_task(void *pvParameters)
{
//界面刷新 函数
while(1)
{
/*若处于界面2 则倒计时开始 5S后自动进入界面3*/if(read_manu==2){m_flag=1;}else m_flag=0;
if(manu_index)
{
TIM_Cmd(TIM14,DISABLE); //失能定时器14 防止定时器中断打扰到界面切换
occupy = 0;//在页面切换过程其他界面操作程序不允许打扰
switch(manu_index)
{
/*界面1:提示开机界面*/ case 1:DisplayInterface_1();break;
/*界面2:5S后自动跳转进入系统*/ case 2:count_down=5;DisplayInterface_2();break;
/*界面3:应用界面 应用程序界面*/ case 3:DisplayInterface_3();break;
/*界面4:进入设置界面*/ case 4:DisplayInterface_4();break;
/*界面5:查看时间*/ case 5:DisplayInterface_5();break;
/*界面6:查看项目名称以及单片机一些参数*/ case 6:DisplayInterface_6();break;
/*界面7:亮度调节界面*/ case 7:DisplayInterface_7();break;
/*界面8:时间调节界面*/ case 8:DisplayInterface_8();break;
/*界面9:电源阈值设置*/ case 9:DisplayInterface_9();break;
}
/*固定显示小数点 CPU周围温度以及AD引脚采集的信息*/
POINT_COLOR = RED;BACK_COLOR = BLACK;
LCD_ShowString(122,249,96,16,16,(u8*)"POWER: 0.0%");
LCD_ShowString(138,267,200,16,16,(u8*)"CPU: 0.00C");
LCD_ShowString(138,285,200,16,16,(u8*)"CH5: 0.00V");
//读取当前屏幕值
switch(manu_index)
{
case 1:read_manu=1;break;
case 2:read_manu=2;break;
case 3:read_manu=3;run_time_flag=1;break;
case 4:read_manu=4;break;
case 5:read_manu=5;break;
case 6:read_manu=6;break;
case 7:read_manu=7;break;
case 8:read_manu=8;break;
case 9:read_manu=9;break;
}manu_index = 0;//清零 防止反复刷新
if(read_manu==5){time_display_flag=1;}else {time_display_flag=0;}//时间仅在界面5显示
occupy=1;//在页面切换过程其他界面操作程序不允许打扰
TIM_Cmd(TIM14,ENABLE); //使能定时器14
}
u8 return_val;//键值
switch(read_manu)//不同的界面 不同的按键处理
{
case 1:if(rtp_test(1)==M1P1){manu_index=2;}break;//若 "触碰开机" 被按下,则进入界面2
case 3:
return_val=rtp_test(3);
switch(return_val)
{
case M3P_Set :manu_index=4;break;
case M3P_Time:manu_index=5;break;
case M3P_Para:manu_index=6;break;
case M3P_AutoOrHand:manu_index=3;if(mode==1)mode=2;else mode=1;break;//模式选择
case M3P_OpenOrClose:if(mode==1){manu_index=3;if(state==1)state=2;else state=1;}break;
case M3P_NormalOrPWM:manu_index=3;if(shine==1)shine=2;else shine=1;break;
case M3_To_Off:manu_index=1;break;
}break;
case 4:return_val=rtp_test(4);
switch(return_val)
{
case M456Back3:manu_index=3; break;
case M4P_SetShine:manu_index=7;break;
case M4_SetTime:/*若设置时间被按下,则保存当前时间以及 进入时间设置界面*/
svtime.syear=RTC_DateStruct.RTC_Year;svtime.smon=RTC_DateStruct.RTC_Month;svtime.sdate=RTC_DateStruct.RTC_Date;
svtime.shour=RTC_TimeStruct.RTC_Hours;svtime.smin=RTC_TimeStruct.RTC_Minutes;svtime.ssec=RTC_TimeStruct.RTC_Seconds;
svtime.sweek=RTC_DateStruct.RTC_WeekDay;manu_index=8;break;
case M4P_Set_Power:manu_index=9;break;
}break;
case 5:if(rtp_test(5)== M456Back3){manu_index=3;}break;
case 6:if(rtp_test(6)== M456Back3){manu_index=3;}break;
case 7:
return_val=rtp_test(7);
switch(return_val)
{
case M7P_SetShine:manu_index=7;normal_val=shine_x/2;break;
case M7P_Sure:manu_index=4;break;
}break;
case 8:
return_val=rtp_test(8);//键值读取
//选择修改的内容
if(return_val==M8_Year || return_val==M8_Mon || return_val==M8_Data\
|| return_val==M8_Hour || return_val==M8_Min || return_val==M8_Sec || return_val==M8_Week){manu_index=8;}
switch(return_val)
{
case M8_SaveTime:manu_index=4;m8_offset=0;
RTC_Set_Time(svtime.shour,svtime.smin,svtime.ssec,RTC_H12_AM);
RTC_Set_Date(svtime.syear,svtime.smon,svtime.sdate,svtime.sweek);
break;
case M8_Count_plus://时间以及日期调整:数值加
switch(m8_offset)
{
case 0:if(svtime.syear<99)svtime.syear++;break;
case 1:if(svtime.smon<12)svtime.smon++;break;
case 2:if(svtime.sdate<31)svtime.sdate++;break;
case 3:if(svtime.shour<23)svtime.shour++;break;
case 4:if(svtime.smin<59)svtime.smin++;break;
case 5:if(svtime.ssec<59)svtime.ssec++;break;
case 6:if(svtime.sweek<7)svtime.sweek++;break;
}manu_index=8;break;
case M8_Count_sub://时间以及日期调整:数值减
switch(m8_offset)
{
case 0:if(svtime.syear>0)svtime.syear--;break;
case 1:if(svtime.smon>1)svtime.smon--;break;
case 2:if(svtime.sdate>1)svtime.sdate--;break;
case 3:if(svtime.shour>0)svtime.shour--;break;
case 4:if(svtime.smin>0)svtime.smin--;break;
case 5:if(svtime.ssec>0)svtime.ssec--;break;
case 6:if(svtime.sweek>1)svtime.sweek--;break;
}manu_index=8;break;
case M8_Year:m8_offset=0;break;case M8_Mon:m8_offset=1;break;case M8_Data:m8_offset=2;break;
case M8_Hour:m8_offset=3;break;case M8_Min:m8_offset=4;break;case M8_Sec:m8_offset=5;break;
case M8_Week:m8_offset=6;break;
}
break;
}vTaskDelay(20);
}
}
//task2:KEY0 按键操作函数
void task2_task(void *pvParameters)
{
u8 key;
while(1)
{
key = KEY_Scan(0);
if(key == KEY0_PRES)
{
switch(read_manu)
{
case 1:manu_index=2;break;
case 2:manu_index=3;break;
case 3:manu_index=1;break;
}
}vTaskDelay(20);
}
}
//task3:ADC值获取 以及获取时间
void task3_task(void *pvParameters)
{
short temp,volt,power;//power用于获取电源的电压,处理后以百分比显示出来
u8 tbuf[40];
while(1)
{
temp=Get_Temprate();//获取CPU周围温度值
volt=Get_Volt(); //获取PA5的电压值 预留光照传感器接口
power=Get_Power(); //获取PA4的电压值 预留电量查看口
//LCD 呼吸效果是否打开
if(shine==2){pwm=volt/3+20;}
else {pwm=normal_val;}
if(occupy==1)//解决:画笔颜色乱串bug
{
/*时间以及日期显示*/
POINT_COLOR = RED;
RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
sprintf((char*)tbuf,"Data:20%02d-%02d-%02d",\
RTC_DateStruct.RTC_Year,RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date);
if(read_manu==5 && time_display_flag==1 && manu_index==0){
BACK_COLOR = YELLOW;POINT_COLOR = BLUE;
LCD_ShowString(20,40,210,16,24,(u8*)tbuf);}
sprintf((char *)tbuf,"Week:%02d",RTC_DateStruct.RTC_WeekDay);
if(read_manu==5 && time_display_flag==1 && manu_index==0){
BACK_COLOR = YELLOW;POINT_COLOR = BLUE;
LCD_ShowString(20,74,210,16,24,(u8*)tbuf);}
RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);
sprintf((char*)tbuf,"Time:%02d:%02d:%02d",\
RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds);
if(read_manu==5 && time_display_flag==1 && manu_index==0){
BACK_COLOR = YELLOW;POINT_COLOR = BLUE;
LCD_ShowString(20,108,210,16,24,(u8*)tbuf);}
sprintf((char*)tbuf,"Run Time:%ds",run_time);
if(read_manu==5 && time_display_flag==1 && manu_index==0){
BACK_COLOR = YELLOW;POINT_COLOR = BLUE;
LCD_ShowString(20,142,210,16,24,(u8*)tbuf);}
/*固定显示部分*/
if(manu_index==0)
{
POINT_COLOR = RED;BACK_COLOR = BLACK; //bug:在变量被清零后才改变画笔颜色
LCD_ShowxNum(170,267,temp/100,2,16,0); //显示整数部分
LCD_ShowxNum(194,267,temp/10%10,1,16,0);//显示小数部分
LCD_ShowxNum(202,267,temp%10,1,16,0); //显示小数部分
LCD_ShowxNum(178,285,volt/100,1,16,0); //显示整数部分
LCD_ShowxNum(194,285,volt/10%10,1,16,0); //显示小数部分
LCD_ShowxNum(202,285,volt%10,1,16,0); //显示小数部分
}
}
vTaskDelay(250);
}
}
void MYInit(void) //初始化函数
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口
LED_Init(); //初始化LED端口
KEY_Init(); //初始化按键
LCD_Init(); //初始化LCD
tp_dev.init(); //触摸屏初始化
myADC_Init(); //初始化ADC
TIM14_Int_Init(tarr-1,tpsc-1); //100us 定时器中断函数
TIM9_PWM_Init(200-1,8400-1);
while(My_RTC_Init()); //返回0则表示初始化成功
TIM_SetCompare1(TIM9,100);
}
四、实物图




资料获取
文章下方名片联系我即可~
博主联系方式:点击我获取资料->->进我个人主页–>获取博主联系方式
更多推荐


所有评论(0)