2021电赛国一——K题照度稳定可调LED台灯

目录

一、数字显示照度表

1.1、效果图

1.2、简介及程序

二、台灯整体程序

2.1、程序流程图

2.2、主函数main

2.3、自动调节程序

三、手机APP

3.1、手机APP界面效果图

3.2、功能介绍


当赛题下来后,我看了高职组和本科组的控制类赛题,IJ题因为材料短缺所以果断放弃。只剩下F和K题可以做,因为我软件控制类题目比较拿手,所以我当时是有想过做F题来挑战一些自己,但是最终还是在队友的劝说下放弃了F题,做了K题。(因为如果做了F题,首先硬件上面跟不上,而且做了F题是要和本科组比的,可能就拿不到比较好的名词。。。。。)

使用2块MSP430作为主控,其他部分我们采用手机APP控制台灯的亮灭调光,因为我主要负责软件,所以下面只说一下软件实现的思路。

整体效果图

2021电赛国一——K题照度稳定可调LED台灯_第1张图片

一、数字显示照度表

1.1、效果图

1.2、简介及程序

主控为MSP430,使用一个光敏电阻,读取其的AD值,经过均值滤波等一系列处理,最后通过串口屏显示出来。

使用430读取AD和一系列滤波就不说了,下面我把发送数据到串口屏的代码放出来。

/********************串口屏初始化********************/
void Screen_Init()
{
  UART_Init(UART0,115200);                                        //初始化UART0模块,波特率115200,TX_P33_RX_P34
  Set_Vector_Handler(VECTOR_UART0,Screen_UART_RX_IRQ_Handler);    //设置接收中断向量
  UART_ITConfig  (UART0,UART_RX_IRQn,TRUE);                       //开串口接收中断 
}

/*改变数显表的值*/
/*******************写变量地址数据,4字节数据,浮点数,长整数,一次最多更改3个*************/
//参数1:变量地址,首地址
//参数2:写数组
//参数3:数组长度  
// Screen_WriteData(0, dat, 3);
//注意4字节数据,long,float
/*
串口屏地址要隔一个50 52 54
发送浮点数float,要数据处理在发送,如下
    dat[0]=(long)(Pitch*1000);
    dat[1]=(long)(Roll*1000);
    dat[2]=(long)(Yaw*1000);
*/
char Screen_Write_Long_Data(uint16_t a, long *b, uint8_t c)
{
  int i,j;
  char Data[18] = {'\0'};
  Data[0] = 0xA5;//帧头
  Data[1] = 0x5A;
  Data[2] = c*4+3;//长度,包括指令和数据;
  Data[3] = 0x82;//写数据寄存器(变量地址)
  Data[4] = (char)(a>>8);//变量地址
  Data[5] = (char)(a & 0x00FF);
  
  for(i=6,j=0; i<(c*4+6); i+=4,j++){    //遍历数据到数组
    Data[i] = (char)(b[j]>>24);
    Data[i+1] = (char)(b[j]>>16 & 0x00FF);
    Data[i+2] = (char)(b[j]>>8 & 0x0000FF);
    Data[i+3] = (char)(b[j] & 0x000000FF);
  }
  
  UART_PutNChar(UART0,Data,6+c*4);      //发送写数据
 
  return 0;
}

二、台灯整体程序

2.1、程序流程图

分为3个模式,手动调光,自动调光,手机APP调光

2021电赛国一——K题照度稳定可调LED台灯_第2张图片

 2.2、主函数main

通过按键改变模式

手动调节:通过改变电位器的AD值,从而改变PWM输出,最终改变台灯的亮度,同时亮度按百分比显示在OLED屏上

自动调节:通过4个光敏电阻,改变PWM,改变亮度

手机APP:通过改变变量esp,改变PWM最终改变台灯亮度

#include "include.h"
uint16_t esp;   //手机APP接收数据缓存

void main()
{ 
  int   i=1;          //esp8266,初始化完成标志位
  int  fl2=0;        //自动调节,目标亮度存储标志位
  int k=0;            //滤波均值次数
  DisableInterrupts();          //禁止总中断
  Keyaaa_Init();                //按键 led初始化
  Headlight_Init();             //pwm adc pid 初始化 
  OLED_Init();                  //OLED初始化
  EnableInterrupts();           //开启总中断

  //OLED显示,模式显示,亮度显示
  OLED_DispChineseAt(FONT_CHINESE_16X16,0,0,"功能模式:");   
  OLED_DispChineseAt(FONT_CHINESE_16X16,6,0,"亮度:");   
  OLED_DispStringAt(FONT_ASCII_8X16,6,86,"%");
  
  while(1)  
  {   
    if(keyfl == 1){        //手动调节
      OLED_DispFolatAt(FONT_ASCII_8X16,6,45,Headlight_Mode1()/9.99,1);//显示台灯亮度
      fl2=0;                                                        //自适应存储未完成标志
    }else if(keyfl == 2){  //自动适应
      if(fl2==0){                                //获取目标AD值
        Lus1 = Lus2 = Lus3 = Lus4 = 0;
        for(k=0;k<20;k++){
          Lus1 += ADC_ReadChanelOnce(ADC_CH0);
          Lus2 += ADC_ReadChanelOnce(ADC_CH1);
          Lus3 += ADC_ReadChanelOnce(ADC_CH2);
          Lus4 += ADC_ReadChanelOnce(ADC_CH3);
        }
        Lus1 = (int)(Lus1/20.0);        //p60  
        Lus2 = (int)(Lus2/20.0);        //p61  
        Lus3 = (int)(Lus3/20.0);       //p62  
        Lus4 = (int)(Lus4/20.0);        //p63 
        fl2=1;
      }
      Headlight_Mode2(Lus1,Lus2,Lus3,Lus4);    //自动调节功能函数
    }else if(keyfl == 3){  //8266
      if(i){                    //判断是否是第一次初始化,因为只需要一次初始化
        ESP8266_Init();
        i=0;
      }
      esp = ESP8266_dataintfl();    //获取数据
      if(esp > 999){esp = 999;}    //输出限幅
      if(esp < 1 ){esp = 0;}
      Esp_Headlight(esp);               //改变亮度
      OLED_DispFolatAt(FONT_ASCII_8X16,6,45,esp/9.99,1);//显示亮度
      fl2=0;
    }else{
      //空模式
    }
  }
}

2.3、自动调节程序

通过4个光敏,改变一路pwm(本来打算控制4路PWM的,最终因为材料短缺,只能4AD控制1PWM)

大体思路:判断4个AD值的变化,最终判断是哪个方向照射过来的光线,最后使用最优的一个光敏来改变PWM控制亮度

/**************************自动调节************************/
//参数1234:分别为4个光敏的目标AD值
void Headlight_Mode2_Pid(uint16_t Hlangle1,uint16_t Hlangle2,uint16_t Hlangle3,uint16_t Hlangle4)
{
  int a=0,aa=0;   //a第一大,aa第二大
  int p[4]={0};  //差值存放数组
  int i=0;       //滤波用
  uint16_t ad1=0,ad2=0,ad3=0,ad4=0;
  
  //均值滤波
  for(i=0;i<50;i++){
      
    ad1 += ADC_ReadChanelOnce(ADC_CH0);        //p60  
    ad2 += ADC_ReadChanelOnce(ADC_CH1);        //p61  
    ad3 += ADC_ReadChanelOnce(ADC_CH2);        //p62  
    ad4 += ADC_ReadChanelOnce(ADC_CH3);        //p63 
  }
  ad1 = (uint16_t)(ad1/50.0);        //p60  
  ad2 = (uint16_t)(ad2/50.0);        //p61  
  ad3 = (uint16_t)(ad3/50.0);       //p62  
  ad4 = (uint16_t)(ad4/50.0);        //p63  

  
  //比较,判断使用哪一个光敏,a第一大,aa第二大
  if(flag111==0){                    //flag111,选取光敏标志位,选取成功为1
    //目标值和当前值,差值存储在数组p
    for(i=0;i<20;i++){
      p[0]+=(Hlangle1-ad1);
      p[1]+=(Hlangle2-ad2);
      p[2]+=(Hlangle3-ad3);
      p[3]+=(Hlangle4-ad4);  
    }
    p[0]=p[0]/20;
    p[1]=p[1]/20;
    p[2]=p[2]/20;
    p[3]=p[3]/20;
    a = 0;
    aa = 0;
    //最大值的角标放入a变量
    for(i=1;i<4;i++){
      if(p[a]3)&&(flag111==0)){//浮动达到3并且没确定使用光敏,判断用哪个光敏控制亮度
    if((p[a] - p[aa]) > 5){//第一和第二比较,相差大用第二aa,小用第一a
      b=aa;
    }else{
      b=a;
    }
    flag111=1;
  }
  
  //使用上面判断的结果,调整灯
  if(b!=-1){
    if((ad1Hlangle1-HlightStable) )//当稳定在一个区域,关闭pid控制
    {
      Headlight_flage=1;
      s_PID.SumError=0;
    }else
    {
            Headlight_flage=0;		
    }
    if((ad2Hlangle2-HlightStable) )//当稳定在一个区域,关闭pid控制
    {
      Headlight_flage2=1;
      s2_PID.SumError=0;
    }else
    {
            Headlight_flage2=0;		
    }
    if((ad3Hlangle3-HlightStable) )//当稳定在一个区域,关闭pid控制
    {
      Headlight_flage3=1;
      s3_PID.SumError=0;
    }else
    {
            Headlight_flage3=0;		
    }
    if((ad4Hlangle4-HlightStable) )//当稳定在一个区域,关闭pid控制
    {
      Headlight_flage4=1;
      s4_PID.SumError=0;
    }else
    {
            Headlight_flage4=0;		
    }
    
    //使用pid改变pwm值
    if((b == 0)&&(Headlight_flage==0)){
      Motor2 -= (int)PID_Cal(&s_PID,ad1);
      if(Motor2 > 999){Motor2 = 999;s_PID.SumError=0;}
      if(Motor2 < 0 ){Motor2 = 0;s_PID.SumError=0;}
    }
    if((b == 1)&&(Headlight_flage2==0)){
      Motor2 -= (int)PID_Cal(&s2_PID,ad2);
      if(Motor2 > 999){Motor2 = 999;s2_PID.SumError=0;}
      if(Motor2 < 0 ){Motor2 = 0;s2_PID.SumError=0;}
    }
    if((b == 2)&&(Headlight_flage3==0)){
      Motor2 -= (int)PID_Cal(&s3_PID,ad3);
      if(Motor2 > 999){Motor2 = 999;s3_PID.SumError=0;}
      if(Motor2 < 0 ){Motor2 = 0;s3_PID.SumError=0;}
    }
    if((b == 3)&&(Headlight_flage4==0)){
      Motor2 -= (int)PID_Cal(&s4_PID,ad4);
      if(Motor2 > 999){Motor2 = 999;s4_PID.SumError=0;}
      if(Motor2 < 0 ){Motor2 = 0;s4_PID.SumError=0;}
    }
  }

  //亮度达到910,继续判断使用哪一个光敏
  if(Motor2 > 910){
      flag111=0;
  }

  Esp_Headlight(Motor2);    //改变pwm函数
}

三、手机APP

3.1、手机APP界面效果图

2021电赛国一——K题照度稳定可调LED台灯_第3张图片

3.2、功能介绍

具体制作及代码可以参考我前面的博文安卓APP,项目

睡觉模式:固定亮度3%,适合晚上睡觉

固定调节亮度:20%,40%。。。。。

在固定调节亮度的基础上可以微调亮度,1%的亮度加减

你可能感兴趣的:(项目,单片机,MSP430,mcu,c语言,eclipse)