基于51单片机的简易太阳能追踪系统Proteus仿真如图所示。
系统主控核心为AT89C51单片机;
动作执行部分为两个0-360度舵机;
4个电位器模拟光敏电阻检测阵列;
模拟电压采集部分使用74HC4051+ADC0804组成多通道模式转换器;
采用蜂鸣器+LED组成声光报警电路;
采用外部EEPROM存储器实现掉电存储数据的功能;
显示部分采用LCD1602显示实时的角度信息和电压信息。
运行仿真后蜂鸣器会响一声,LCD显示器的第一行上会显示出4个通道采集到的电压值;第二行显示出2个舵机的初始角度。
仿真中利用电位器模拟光敏电阻,设定当光线变弱时光敏电阻的输出电压会降低。当对应光敏电阻输出电压低于4.5V时,系统会控制相应方向的舵机进行角度变换,直到该电位器电压恢复后系统停止舵机的角度变换,从而达到追踪阳光的目的。
每一次成功矫正位置后,系统都会将舵机当前的角度值存储到外部的EEPROM中,下一次重启运行时会从EEPROM中读取出该角度,并将舵机设置为该初始角度。
当系统的光敏电阻输出电压有两组以上小于设定值时,系统会通过蜂鸣器和LED发出报警提示。
部分代码如下:
int main(void)
{
uchar num[15]={0},n,i;
LCD_Init(); //lcd显示初始化
DelayMs(5); //延时5ms
LCD_Clear(); //清空显示
DelayMs(5); //延时5ms
ADCOUTPUT=0xff; //P0口置高电平,准备读数据
Switch_1 = 0 ;
Switch_2 = 0 ; //设置转换通道0
timer0_init(); //定时器初始化
error = 0 ;
error1 = 0 ; //故障变量清0
Init_IIC(); //初始化IIC
angle = read_add(1)<<8|read_add(0); //读取角度1
if(angle<0)
angle= 180;
if(angle>360)
angle=180;
angle1 = read_add(3)<<8|read_add(2); //读取角度2
if(angle1<0)
angle1=180;
if(angle1>360)
angle1=180;
DelayMs(500); //延时500毫秒
scnt = 0 ;
ADC0804Start(); //启动ADC,进行数据转换
BEE_LED = 0 ;
Set_DutyCycle_To((angle*D+1)*5); //控制舵机去指定角度
Set_DutyCycle_To1((angle1*D+1)*5); //控制舵机去指定角度
while(1)
{
if(scnt<1000) //采样周期计数值
{
scnt++;
}else
{
scnt = 0 ;
}
if(scnt==0) //周期开始
{
switch(range_temp)
{
case 0 : Switch_1 = 0 ; Switch_2 = 0 ; break ; //切换对应通道
case 1 : Switch_1 = 1 ; Switch_2 = 0 ; break ;
case 2 : Switch_1 = 0 ; Switch_2 = 1 ; break ;
case 3 : Switch_1 = 1 ; Switch_2 = 1 ; break ;
}
}else if(scnt==200)
{
ADC0804Start(); //启动ADC,进行数据转换
}else if(scnt==400)
{
_nop_();
_nop_();
ADRD=1; //读数据控制端拉高,准备读取数据
_nop_();
ADRD=0; //读数据控制端拉低,读取数据
_nop_();
n=ADCOUTPUT; //读取转换数据
}else if(scnt==800)
{
switch(range_temp) //读取对应通道转换结果。并计算实际电压
{
case 0 : v1 = BD*n ; range_temp = 1 ; break ;
case 1 : v2 = BD*n ; range_temp = 2 ; break ;
case 2 : v3 = BD*n ; range_temp = 3 ; break ;
case 3 : v4 = BD*n ; range_temp = 0 ; break ;
}
}else if(scnt==900) //对电压进行显示
{
num[0]=v1/100%10;
num[1]=v1/10%10;
num[2]=v2/100%10;
num[3]=v2/10%10;
num[4]=v3/100%10;
num[5]=v3/10%10;
num[6]=v4/100%10;
num[7]=v4/10%10;
sprintf(temp,"%d.%d %d.%d %d.%d %d.%d",(int)num[0],(int)num[1],(int)num[2],(int)num[3],(int)num[4],(int)num[5],(int)num[6],(int)num[7]);
LCD_Write_String(0,0,temp); //刷新显示数据
ADRD=1; //读取数据完毕
if(buff<10)
buff ++ ;
}else if(scnt==950&&buff>8)
{
if(v1<450&&v2>450) //如果1一侧光线弱
{
if(angle<360) //角度增大
{
angle = angle+1 ;
}
Set_DutyCycle_To((angle*D+1)*5);
error = 0 ;
ast =0 ;
}else if(v1>450&&v2<450) //另外一侧弱。
{
if(angle>0) //角度减小
{
angle = angle-1 ;
}
Set_DutyCycle_To((angle*D+1)*5);
error = 0 ;
ast =0 ;
}else if(v1<450&&v2<450) //如果两侧光线都弱,进行报警,另外一路舵机控制原理类似
{
error = 1 ;
}else
{
if(ast==0)
{
ast =1 ;
write_add(0x00,angle); //将报警阈值写入到EEPROM中,其中低位写入到地址0,高位写入到地址1
DelayMs(5);
write_add(0x01,angle>>8);
DelayMs(5);
}
}
if(v3<450&&v4>450)
{
if(angle1<360)
{
angle1 = angle1+1 ;
}
Set_DutyCycle_To1((angle1*D+1)*5);
error1 = 0 ;
ast1 =0 ;
}else if(v3>450&&v4<450)
{
if(angle1>0)
{
angle1 = angle1-1 ;
}
Set_DutyCycle_To1((angle1*D+1)*5);
error1 = 0 ;
ast1 =0 ;
}else if(v3<450&&v4<450)
{
error1 = 1 ;
}else
{
if(ast1==0)
{
ast1 =1 ;
write_add(0x02,angle1); //将报警阈值写入到EEPROM中,其中低位写入到地址0,高位写入到地址1
DelayMs(5);
write_add(0x03,angle1>>8);
DelayMs(5);
}
}
num[0]=angle/100%10;
num[1]=angle/10%10;
num[2]=angle%10;
num[3]=angle1/100%10;
num[4]=angle1/10%10;
num[5]=angle1%10;
sprintf(temp,"deg1:%d%d%ddeg2:%d%d%d",(int)num[0],(int)num[1],(int)num[2],(int)num[3],(int)num[4],(int)num[5]);
LCD_Write_String(0,1,temp); //刷新显示数据
}
if(error==1||error1==1)
{
BEE_LED = 1 ;
}else
{
BEE_LED = 0 ;
}
}
}
基于51单片机的简易太阳能跟踪系统-单片机文档类资源-CSDN文库https://download.csdn.net/download/xitianqu/86977414