单片机交流
直播中

蔡鼎瑾

7年用户 976经验值
私信 关注
[问答]

怎样去设计一种基于单片机的智能窗帘呢

怎样去设计一种基于单片机的智能窗帘呢?怎样去编写其主函数代码呢?

回帖(1)

蔡鼎瑾

2021-10-22 15:06:59
  终于是暑假了,开始有点时间了,把以前做的一些小东西总结一下,其实大创是很早就已经完成了,只不过学校一直到四月份才开始验收结题。项目比较简单,也很方便就能验证功能,比较适合初学者练手,所以大概分享一下。
  大创项目全称就是 基于单片机的智能窗帘的研究与设计 这是一个很老也很简单的项目了,当时大二寻找题目申请大创的时候,还是个连51单片机都才学一般的菜鸟,总怕自己最后做不出来,大创结题不了(事实证明,想要结题还是很容易的,毕竟学校也不想让你毕不了业),所以一直在找哪种名字听起来比较高级,实际比较简单的题目,于是就找到了这个题目。
  一开始是想用51单片机做的,毕竟网上资料也比较多,但是很快就发现,其实51单片机的市场应用已经太久了,比较老了,既然学校有经费资助,于是我就想从头开始学性能更好,资源更加多的STM32单片机了,因为之前学过51了,所以在学习32时概念理解上会比较快,比较容易上手,其实去学后会发现在库函数的帮助下,32用起来不会比51难很多,我当时也是直接买了正点的mini板开始自学,后来参加电设也用上了,所以还是比较值的,不过我觉得学任何东西还是要有目标的去学,比如说要完成一个什么功能,一个什么项目这种,不能拿来视频就开始看,虽然随便一个视频可能都是你没学过的,但是没有项目来督促或则说激励你,要么就会学不下去,要么学完很快就忘了,我学习51就是这样,自己买了开发板开始学,看完视频感觉自己开发板已经掌握的差不多了就搁那不管了,到申请大创项目时,我脑子里也没有一个基本的程序思路。以后想深入学习下matlab,也是想先找几个项目开始学,目标是完成项目,所以就要先学项目所需要的一些功能。
  下面开始说这个项目把。这个智能窗帘要完成的功能也比较简单,就是有手动控制模式和自动控制模式,手动通过红外遥控器实现,自动就是通过光敏电阻测光强度来自动调整窗帘位置,这个项目比较适合用上下升降的窗帘。在手动模式下,只能通过红外遥控控制,但是光强等其它一些参数还是会测量显示;自动模式下,就是先测光强,然后更设定阈值进行比较,然后调整窗帘升降,阈值可以通过按键或者遥控器设置。TFT-LCD屏幕的显示界面如下,界面其实是可以优化一下的,比较懒就没去弄。
  然后验证功能我用的是28BYJ-48步进电机,但是单片机直接驱动不了,需要一个驱动,我用的是ULN2003,演示的时候还是搭了一个模型的,不过已经被我拆了,没有照片了。
  
  贴个主函数吧,完整的工程我用百度云分享。
  我MDK里是有打注释的,不过一复制到外面就乱码了,变量含义我截图放一下,其他不清楚就下载工程看一下吧
  
  主函数代码如下:
  顺便说一下我编整个程序的思路,可以看到我设置了很多标志位或者变量,因为我从显示界面开始编写的,有时候也会从按键开始,然后期间每用到一个参数或需要判断的标志就定义一个变量,然后显示界面跟按键写完后,然后根据设置的需要的变量去编写这些参数来源的代码,如光强度通过ADC读取光敏电阻两端电压换算而来,然后再慢慢把用到的变量的来源补充完整,整个程序就慢慢成形了,其他再修修补补就好了。先写显示的代码其实是为了后面写代码过程中可以将一些参数暂时显示出来,这样方便找错,或验证程序运行是否正确。
  #include “led.h”
  #include “delay.h”
  #include “sys.h”
  #include “usart.h”
  #include “lcd.h”
  #include “remote.h”
  #include “rtc.h”
  #include “stdio.h”
  #include “adc.h”
  #include “key.h”
  #include “motor.h”
  #include “ds18b20.h”
  #define Left 0
  #define Right 1
  ************************************±äÁ¿¶¨Òå************************************//
  u8 Remote_scan; //ºìÍâɨÃè·µ»Ø¼üÖµ
  u8 Remote_Cmd=0; //0Ϊ×Ô¶¯Ä£Ê½£¬1ΪºìÍâÒ£¿Øģʽ
  u8 Remote_Left_Right; //0 left 1 right
  u8* Remote_Key_Str;
  u8 Time_Record=0; //
  u8 Motor_Update=1;
  u8 Motor_CW_Cmd=1;
  u8 Motor_CCW_Cmd=1;
  u8 Key_Scan_Cmd=1;
  u8 Key_Scan;
  u8 RTC_Sec=0; //RTC Ãë¸üÐÂ
  //u8 LCD_dir=1;
  u8 LCD_Display_Update=1; //LCD ¸üÐÂÏÔʾ
  u8 LCD_Display_Page=0; //LCDÏÔʾҳÃæ
  u8 LCD_Display_Line=1; //LCDÏÔʾҳÃæ
  u8 LCD_Clear_Old=0;
  u8 LCD_Clear_New=0;
  u8 Temp_Light_Get_Cmd=1;
  float Light_voltage; //ADC»»ËãµçѹºóÖ
  float Light_Intensity=0; //0-100 ¹âÇ¿¶È
  u8 Light_HighLimit=35; //µÚ¶þÒ³¹âÇ¿ÉÏÏÞ
  u8 Light_LowLimit=30; //µÚ¶þÒ³¹âÇ¿ÏÂÏÞ
  short DS18B20_Temperature; //18B20Ëù²âζÈ
  u8 Temperature_HighLimit=30;//µÚ¶þҳζÈÉÏÏÞ
  u8 Temperature_LowLimit=10; //µÚ¶þҳζÈÏÂÏÞ
  u8 LCD_Str[30]; //ÏÔʾ×Ö·ûÔÝ´æÊý×é
  u8 Motor_Opendegree=0; //´°Á±¿ªºÏ³Ì¶È
  //************************************º¯Êý¶¨Òå************************************//
  int main(void)
  {
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  delay_init(); //ÑÓʱº¯Êý³õʼ»¯
  uart_init(9600); //´®¿Ú³õʼ»¯Îª9600
  LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú
  KEY_Init();
  Adc_Init();
  Moto_Init();
  Remote_Init();
  Motor_Locate(100,2000); // ÉèÖà ´°Á±³õ ʼλÖÃ
  LCD_Init();
  LCD_Display_Dir(1);
  POINT_COLOR=BLUE;
  LCD_DrawRectangle(20,20,300,220); //»­·½¿ò x1 y1; x2 y2
  // while(DS18B20_Init())
  // {
  // LCD_ShowString(40,100,60,12,12,“DS18B20 error!!!”);
  // delay_ms(500);
  // }
  while(RTC_Init()) / RTC³õʼ»¯£¬ÉèÖÿªÊ¼Ê±¼ä
  {
  LCD_ShowString(20,20,60,12,12,“error!!!”);
  delay_ms(800);
  }
  LCD_ShowString(30,180,300,16,16,“real time : - - ”);
  LCD_ShowString(30,200,300,16,16,“real time : : : ”);
  POINT_COLOR=BLUE;
  LCD_ShowNum(126,180,calendar.w_year,4,16);
  LCD_ShowNum(166,180,calendar.w_month,2,16);
  LCD_ShowNum(190,180,calendar.w_date,2,16);
  LCD_ShowNum(142,200,calendar.hour,2,16);
  LCD_ShowNum(166,200,calendar.min,2,16);
  LCD_ShowNum(192,200,calendar.sec,2,16);
  DS18B20_Temperature=DS18B20_Get_Temp();
  while(1)
  {
  if(RTC_Sec!=calendar.sec)
  {
  RTC_Sec=calendar.sec;
  POINT_COLOR=BLUE;
  LCD_ShowNum(126,180,calendar.w_year,4,16);
  LCD_ShowNum(166,180,calendar.w_month,2,16);
  LCD_ShowNum(190,180,calendar.w_date,2,16);
  LCD_ShowNum(142,200,calendar.hour,2,16);
  LCD_ShowNum(166,200,calendar.min,2,16);
  LCD_ShowNum(192,200,calendar.sec,2,16);
  LED0=!LED0;
  Temp_Light_Get_Cmd=1;
  }
  //µç»úÐýתλÖÃÏÞÖÆ
  if(current_angle《100) Motor_CCW_Cmd=0;
  else if(current_angle》2100) Motor_CW_Cmd=0;
  else
  {
  Motor_CCW_Cmd=1;
  Motor_CW_Cmd=1;
  }
  //ºìÍâÒ£¿ØɨÃè
  Remote_scan=Remote_Scan();//Remote_State
  if(Remote_scan)
  {
  switch(Remote_scan) //ºìÍâ°´¼üʶ±ð
  {
  case 0:Remote_Key_Str=“ERROR ”;break;
  case 162: Remote_Key_Str=“POWER ”;
  LCD_Clear_Old--;
  Remote_Cmd=!Remote_Cmd;break;
  case 98:Remote_Key_Str=“UP ”;
  if(Remote_Cmd==0)
  {
  if(LCD_Display_Page==1)
  {
  switch(LCD_Display_Line)
  {
  case 1: Temperature_HighLimit++;
  Temperature_HighLimit=(Temperature_HighLimit》40)?40:Temperature_HighLimit;
  break;
  case 2: Temperature_LowLimit++;
  Temperature_LowLimit=(Temperature_LowLimit》Temperature_HighLimit)?(Temperature_HighLimit-1):Temperature_LowLimit;
  break;
  case 3: Light_HighLimit++;
  Light_HighLimit=(Light_HighLimit》100)?100:Light_HighLimit;
  break;
  case 4: Light_LowLimit++;
  Light_LowLimit=(Light_LowLimit》Light_HighLimit)?(Light_HighLimit-1):Light_LowLimit;
  break;
  default:break;
  }
  }
  }break;
  case 2:Remote_Key_Str=“PLAY ”;break;
  case 226:Remote_Key_Str=“ALIENTEK”;break;
  case 194:Remote_Key_Str=“RIGHT ”;
  Remote_Left_Right=Right;break;
  case 34:Remote_Key_Str=“LEFT ”;
  Remote_Left_Right=Left;break;
  case 224:Remote_Key_Str=“VOL- ”;break;
  case 168:Remote_Key_Str=“DOWN ”;
  if(Remote_Cmd==0)
  {
  if(LCD_Display_Page==1)
  {
  switch(LCD_Display_Line)
  {
  case 1: Temperature_HighLimit--;
  Temperature_HighLimit=(Temperature_HighLimit《Temperature_LowLimit)?(Temperature_LowLimit+1):Temperature_HighLimit;
  break;
  case 2: Temperature_LowLimit--;
  Temperature_LowLimit=(Temperature_LowLimit《10)?10:Temperature_LowLimit;
  break;
  case 3: Light_HighLimit--;
  Light_HighLimit=(Light_HighLimit《Light_LowLimit)?(Light_LowLimit+1):Light_HighLimit;
  break;
  case 4: Light_LowLimit--;
  Light_LowLimit=(Light_LowLimit《10)?10:Light_LowLimit;
  break;
  default:break;
  }
  }
  }break;
  case 144:Remote_Key_Str=“VOL+ ”;break;
  case 104:Remote_Key_Str=“1 ”;break;
  case 152:Remote_Key_Str=“2 ”;break;
  case 176:Remote_Key_Str=“3 ”;break;
  case 48:Remote_Key_Str=“4 ”;break;
  case 24:Remote_Key_Str=“5 ”;break;
  case 122:Remote_Key_Str=“6 ”;break;
  case 16:Remote_Key_Str=“7 ”;break;
  case 56:Remote_Key_Str=“8 ”;break;
  case 90:Remote_Key_Str=“9 ”;break;
  case 66:Remote_Key_Str=“0 ”;break;
  case 82:Remote_Key_Str=“DELETE ”;break;
  }
  }
  //Ò£¿ØÆ÷ÊÖ¶¯¿ØÖÆ Ä£Ê½******************************************************************
  if(Remote_Cmd==1)
  {
  if(LCD_Clear_Old==LCD_Clear_New) //ÇåÆÁ×ÔËø£¬²»È»ÏÔʾµÄÎÄ×Ö»áÉÁ˸
  {
  LCD_Clear_New--;
  LCD_Fill(22,22,298,178,WHITE); //Çå³þ֮ǰµÄÏÔʾ
  }
  LCD_ShowString(30,120,200,24,24,“SYMBOL:”);
  LCD_ShowString(126,120,14*12,24,24,Remote_Key_Str); //ÏÔʾSYMBOL
  sprintf((char*)LCD_Str,“Motor Angle: %d ”,current_angle-100); // “Open Degree: %d%% ”
  LCD_ShowString(30,150,20*8,16,16,LCD_Str);
  if(Motor_CCW_Cmd==1||Motor_CW_Cmd==1)
  {
  switch(Remote_Left_Right)
  {
  case Left: Remote_Left_Right=3;
  if(current_angle》(-50))
  {
  Motorccw_angle(50,2000);break; //Ò£¿ØÆ÷°´ÏÂ×ó,ÒÔ2000ËÙ¶ÈÕý´«360¶È
  }
  case Right: Remote_Left_Right=3;
  if(current_angle《2200)
  {
  Motorcw_angle(50,2000);break;
  }
  }
  }
  }
  //×Ô¶¯¿ØÖÆ Ä£Ê½********************************************************************
  else if(Remote_Cmd==0)
  {
  if(LCD_Clear_Old==LCD_Clear_New)
  {
  LCD_Clear_New--;
  LCD_Fill(22,22,298,178,WHITE); //Çå³þ֮ǰµÄÏÔʾ
  }
  //ζȻñÈ¡×Ó³ÌÐò
  if(Temp_Light_Get_Cmd==1)
  {
  Temp_Light_Get_Cmd=0;
  //DS18B20_Temperature=DS18B20_Get_Temp();
  Light_voltage=Get_Adc(1)*3.3/4096;
  Light_Intensity=(3.3-Light_voltage)*100/3.3;
  LCD_Display_Update=1; //»ñÈ¡ÍêζȹâÇ¿ÐèÒª¸üÐÂÏÔʾÒÔ¼°µç»úλÖÃ
  Motor_Update=1;
  }
  //¸ù¾Ý¹âÇ¿¶Èµ÷½Úµç»úλÖÃ
  if(Motor_CW_Cmd==1&&(Light_Intensity《Light_LowLimit))
  {
  Motorcw_angle(10,2000);
  }
  else if(Motor_CCW_Cmd&&(Light_Intensity》Light_HighLimit))
  {
  Motorccw_angle(10,2000);
  }
  °´¼ü×Ó³ÌÐò ÿ50msɨÃèÒ»´Î
  //if(Time_Record%2==0) Key_Scan_Cmd=1;
  Key_Scan_Cmd=1;
  if(Key_Scan_Cmd==1)
  {
  Key_Scan_Cmd=0;
  Key_Scan=KEY_Scan(0);
  if(Key_Scan!=0) LCD_Display_Update=1; //ÈôÓа´¼ü±»°´Ï£¬ÐèÒª¸üÐÂÏÔʾ
  switch(Key_Scan)
  {
  case KEY0_PRES: if(LCD_Display_Page==1)
  {
  switch(LCD_Display_Line)
  {
  case 1: Temperature_HighLimit++;
  Temperature_HighLimit=(Temperature_HighLimit》40)?40:Temperature_HighLimit;
  break;
  case 2: Temperature_LowLimit++;
  Temperature_LowLimit=(Temperature_LowLimit》Temperature_HighLimit)?(Temperature_HighLimit-1):Temperature_LowLimit;
  break;
  case 3: Light_HighLimit++;
  Light_HighLimit=(Light_HighLimit》100)?100:Light_HighLimit;
  break;
  case 4: Light_LowLimit++;
  Light_LowLimit=(Light_LowLimit》Light_HighLimit)?(Light_HighLimit-1):Light_LowLimit;
  break;
  default:break;
  }
  }
  break;
  case KEY1_PRES: if(LCD_Display_Page==1)
  {
  switch(LCD_Display_Line)
  {
  case 1: Temperature_HighLimit--;
  Temperature_HighLimit=(Temperature_HighLimit《Temperature_LowLimit)?(Temperature_LowLimit+1):Temperature_HighLimit;
  break;
  case 2: Temperature_LowLimit--;
  Temperature_LowLimit=(Temperature_LowLimit《10)?10:Temperature_LowLimit;
  break;
  case 3: Light_HighLimit--;
  Light_HighLimit=(Light_HighLimit《Light_LowLimit)?(Light_LowLimit+1):Light_HighLimit;
  break;
  case 4: Light_LowLimit--;
  Light_LowLimit=(Light_LowLimit《10)?10:Light_LowLimit;
  break;
  default:break;
  }
  }break;
  case WKUP_PRES: if(LCD_Display_Page==0) LCD_Display_Page=1;
  else
  {
  LCD_Display_Line++;
  if(LCD_Display_Line==5)
  {
  LCD_Display_Line=1;
  LCD_Display_Page=0;
  }
  }break;
  default:break;
  }
  }
  if(LCD_Display_Update==1)
  {
  LCD_Display_Update=0;
  if(LCD_Display_Page==0)
  {
  LCD_ShowString(25,40,400,16,16,“ ”);
  LCD_ShowString(128,40,72,16,16,“Parameter”);
  sprintf((char*)LCD_Str,“Light : %.1f ”,Light_Intensity); //
  LCD_ShowString(30,80,25*8,16,16,LCD_Str);
  sprintf((char*)LCD_Str,“Temperature: %2d.%d C ”,DS18B20_Temperature/10,DS18B20_Temperature%10);
  LCD_ShowString(30,120,25*8,16,16,LCD_Str);
  sprintf((char*)LCD_Str,“Motor Angle: %d ”,current_angle-100); // “Open Degree: %d%% ”
  LCD_ShowString(30,150,20*8,16,16,LCD_Str);
  }
  else //if(LCD_Display_Page==1)
  {
  POINT_COLOR=BLUE;
  if(LCD_Display_Line==1) POINT_COLOR=RED;
  sprintf((char*)LCD_Str,“Temp_HighLimit : %d C ”,Temperature_HighLimit); //
  LCD_ShowString(30,40,25*8,16,16,LCD_Str);
  POINT_COLOR=BLUE;
  if(LCD_Display_Line==2) POINT_COLOR=RED;
  sprintf((char*)LCD_Str,“Temp_LowLimit : %d C ”,Temperature_LowLimit);
  LCD_ShowString(30,80,25*8,16,16,LCD_Str);
  POINT_COLOR=BLUE;
  if(LCD_Display_Line==3) POINT_COLOR=RED;
  sprintf((char*)LCD_Str,“Light_HighLimit: %d ”,Light_HighLimit); //
  LCD_ShowString(30,120,25*8,16,16,LCD_Str);
  POINT_COLOR=BLUE;
  if(LCD_Display_Line==4) POINT_COLOR=RED;
  sprintf((char*)LCD_Str,“Light_HighLimit: %d ”,Light_LowLimit); //
  LCD_ShowString(30,150,25*8,16,16,LCD_Str);
  POINT_COLOR=BLUE;
  }
  }
  Time_Record++;
  if(Time_Record==100) Time_Record=0;
  delay_ms(10);
  }
  }
  }
  刚开始的时候,感觉结题这个项目都有困难,但是慢慢学习单片机,了解了一些这方面的资料后,就会发现这个项目很简单,因为不怎么需要硬件方面的知识,现在支持STM32的各种模块非常多,基本不用自己搭电路,一开始光敏电阻的模拟以及数字苏输入我是想自己买光敏电阻搭电路的,后来发现模块非常的便宜,也比自己搭的肯定要稳定,毫不犹豫就买了模块。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分