目录
系统采用双轴结构的设计方案,可实现在水平角度和俯仰角度对太阳光的跟踪,即可如向日葵一般追踪太阳,从而提高光伏发电效率、提高整体发电量。
目前光伏双轴跟踪的方法很多,从跟踪原理的角度可分为两类:一类是根据太阳的运动轨迹进行跟踪的视日轨迹跟踪,另一类是有光电传感器的光电跟踪。这两种跟踪算法相结合、相互补充、相辅相成,以实现不同天气场景下效益最大化。
1.1 光电跟踪算法
光电跟踪方式是利用安装在光伏跟踪装置上的光电传感单元来感光太阳位置的不同,从而由控制单元发出信号驱动跟踪执行机构来调整光伏跟踪装置的高度角和方位角,属于闭环随动系统。
1.1.1 光电跟踪的工作原理
光电传感单元内部的光敏元器件检测太阳光照强度的变化,当太阳位置产生变化时,照射在光敏元器件的光照强度发生变化,并且输出相应的偏差信号,该信号经过放大和数据处理,就能够检测出太阳光线入射角的偏差,当入射角的偏差大于所设定的某一偏差时,通过调整光伏跟踪装置的高度角和方位角,使得太阳光线入射偏差为零或在某一定误差范围内,那么跟踪执行机构停止跟踪;当太阳继续运行一段时间后,太阳光线的入射角偏差大于所设定的某一偏差时,则跟踪执行机构继续跟踪;就这样重复上述过程,通过对比太阳光线的入射角偏差和所设定的某一偏差值来实现太阳能电池板对光源的自动追踪,保持与太阳光直射角度垂直。

1.1.2 光电跟踪装置的组成
光电跟踪装置通常由光电检测单元,信号控制单元和跟踪执行机构三部分组成。光电检测单元主要由性能稳定的光敏元件组成,将太阳位置信号转化成电信号,目前应用较多的光电探测器主要有三种:基于挡板的四象限光敏电阻探测器,四象限光电探测器和光电位敏探测器;控制单元主要是以微处理器为核心,接收检测单元输送的电信号并经过分析处理,输出控制信号;执行机构是将接收到的控制信号转化成驱动跟踪装置完成自动跟踪任务。
本系统所采用的光电传感单元为——基于挡板的四象限光敏电阻探测器。具体可看此博文👇
光电传感单元(STM32学习之ADC+DMA)https://blog.csdn.net/Dkkkkk20/article/details/132385084
1.1.3 核心代码
光电跟踪的部分代码实现
void LDR_Following()
{
u16 av_up = (AD_Value[2] + AD_Value[3]) / 2; //计算上行两个LDR数值的平均
u16 av_down = (AD_Value[0] + AD_Value[1]) / 2; //计算下行两个LDR数值的平均
u16 av_left = (AD_Value[0] + AD_Value[3]) / 2; //计算左列两个LDR数值的平均
u16 av_right = (AD_Value[1] + AD_Value[2]) / 2; //计算右列两个LDR数值的平均
u16 different_1 = av_down - av_up; //将上下行的LDR平均值进行作差
u16 different_2 = av_left - av_right; //将左右列的LDR平均值进行作差
// printf("AD1=%d\r\n", AD_Value[0]); //串口打印各个LDR的数值大小,以便观察而已,当然也可使用oled、lcd屏幕显示
// printf("AD2=%d\r\n", AD_Value[1]);
// printf("AD3=%d\r\n", AD_Value[2]);
// printf("AD4=%d\r\n", AD_Value[3]);
//检查偏差是否在阈值范围内,否则改变垂直角度
if (different_1 < -1*error || different_1 > error)
{
if (av_down > av_up)
{
angle1 = angle1 - 1;
if (angle1 < servo1LimitLow) //限幅
{
angle1 = servo1LimitLow;
}
}
else if (av_down < av_up)
{
angle1= angle1 + 1;
if (angle1 > servo1LimitHigh) //限幅
{
angle1 = servo1LimitHigh;
}
}
Servo1_SetAngle(angle1);
}
//检查偏差是否在阈值范围内,否则改变水平角度
if (different_2 < -1*error || different_2 > error)
{
if (av_left > av_right)
{
angle2 = angle2 + 1;
if (angle2 > servo2LimitHigh)
{
angle2 = servo2LimitHigh;
}
}
else if (av_left < av_right)
{
angle2 = angle2 - 1;
if (angle2 < servo2LimitLow)
{
angle2 = servo2LimitLow;
}
}
Servo2_SetAngle(angle2);
}
delay_ms(react_time);
}
1.2 视日轨迹跟踪算法
阳在天空中的位置时刻在变化,但它具有一定的运动规律,视日轨迹跟踪是一种以天文算法为基础的主动跟踪方法。
对于视日轨迹跟踪算法,首先需要根据跟踪装置所处地的纬度、经度、当前的日期和时间等参数,由太阳运行的轨迹算法便可计算得出太阳日出和日落时间;
其次,由控制器计算出每天从日出到日落之间每一时刻太阳的高度角和方位角,换算成光伏跟踪装置应该转过的角度;
最后,由控制器发出信号控制舵机转动,使太阳能电池板与太阳光线尽可能垂直。

1.2.1 视日轨迹跟踪的工作原理
该算法的原理有点冗长,建议有兴趣的朋友可前往知网搜索如下论文进行了解。
1.2.2 代码浅析
对于该算法的代码实现,本人也只是复现了论文里的公式大概弄出来而已,个人感觉效果并没有十分完美,如有时间再完善完善,也欢迎各位有兴趣一起交流。😊
视日轨迹跟踪的部分代码实现
首先需要得到装置所在地的经纬度
然后还需得到实时的时间信息,因此需要调用STM32的RTC外设模块,具体请看以下博文👇
得到了实时的时间信息后便可计算太阳的时角和赤纬角
将计算所得的时角和赤纬角代入公式即可计算得到太阳的高度角和方位角,/*先计算出高度角方可计算出方位角*/、
得到了高度角和方位角后,便可转化为跟踪装置上舵机的执行角度(具体情况因人而异)
同时你也可以在写一小段代码实现规定时间内才执行此程序,因为太阳下山后执行此跟踪模式是没有意义的。
void Tracking_SunPath()
{
// 当前位置
double latitude = 41.684; //纬度
// double longitude = 123.471; //经度
int n = calculateNianJiRi();
// 计算太阳方位角和高度角
double hourAngle = ((double)(calendar.hour + calendar.min / 60.0) - 12) * 15; //时角
double theta = 23.45 * sin(toRadians(360) * (n + 284) / 365); //-11.928 赤纬角
// double sinAzimuth = sin(hourAngle) * sin(sunPosition.declination) / cos(toRadians(90) - asin(cosAzimuth));
double elevation = toDegrees(asin(sin(toRadians(theta)) * sin(toRadians(latitude)) + cos(toRadians(theta)) * cos(toRadians(latitude)) * cos(toRadians(hourAngle)))); //高度角
double azimuth = toDegrees(acos( (sin(toRadians(elevation)) * sin(toRadians(latitude)) - sin(toRadians(theta))) / (cos(toRadians(elevation)) * cos(toRadians(latitude))) )); //方位角
// double x = sin(toRadians(90));
angle1 = 170-elevation;
angle2 = 90-azimuth;
if( (double)(calendar.hour + calendar.min / 60.0) > 6.5 && (double)(calendar.hour + calendar.min / 60.0) < 17.5)
{
Servo1_SetAngle(angle1);
Servo2_SetAngle(angle2);
}
// printf("Alarm Time:%d-%d-%d %d:%d:%d\r\n\r\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
delay_ms(1000);
}
若对本文完整的工程代码感兴趣可私信获取❤
若觉得本文有帮助还请点赞、收藏支持一下❤