目录
一、数字显示照度表
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控制台灯的亮灭调光,因为我主要负责软件,所以下面只说一下软件实现的思路。
整体效果图
主控为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;
}
分为3个模式,手动调光,自动调光,手机APP调光
通过按键改变模式
手动调节:通过改变电位器的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{
//空模式
}
}
}
通过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%,适合晚上睡觉
固定调节亮度:20%,40%。。。。。
在固定调节亮度的基础上可以微调亮度,1%的亮度加减