引言:为何需要太阳能追光?
在传统的固定式太阳能板系统中,太阳位置的变化导致能量收集效率大幅降低。研究表明,采用太阳追踪系统可以提高30-50%的能量收集效率。今天,我将分享一个基于STC12C5A60S2单片机的双轴太阳能追光系统设计方案。
系统硬件架构
1.核心控制单元
主控芯片:STC12C5A60S2单片机
-
工作频率:11.0592MHz
-
8通道10位ADC,满足光强采集需求
2.光强检测模块
+Y方向
|
光敏电阻1 | 光敏电阻2
|
-X方向 ------+------ +X方向
|
光敏电阻4 | 光敏电阻3
|
-Y方向
采用四象限布局,每个方向一个光敏电阻,通过ADC采集电压值
3.执行机构
水平方向:MG996R舵机(360°)
垂直方向:MG996R舵机(180°)
- 减速齿轮箱增加扭矩,提高稳定性

4.能源管理
-
充电芯片:CN3791 MPPT太阳能充电控制器
-
电池:12V锂电池
-
电压转换:LM2596降压模块(12V→5V)
5.机械结构
跟踪系统根据旋转自由度,可分为以下几种主要类型:
| 跟踪方式 | 旋转自由度 | 特点与发电增益 | 典型适用场景 |
|---|---|---|---|
| 水平单轴跟踪 | 1个(东西向水平旋转) | 结构较简单,性价比高,是主流方式之一;发电量提升约15-20%。 | 低纬度地区、大型地面电站 |
| 斜单轴跟踪 | 1个(与水平面呈一定夹角) | 比平单轴能更充分地利用太阳辐射,增益介于平单轴与双轴之间。 | 中纬度地区、有一定坡度的山地 |
| 双轴跟踪 | 2个(水平旋转+俯仰调节) | 可精确保持与太阳光线垂直,发电增益最高,可达40%左右。 | 对效率要求极高的场景、分布式高倍聚光(CPV)系统 |
| 垂直单轴跟踪 | 1个(垂直轴旋转) | 适用于高纬度地区或特殊安装条件,但应用相对较少。 | 高纬度地区、建筑一体化等特殊设计 |
其中,双轴跟踪 是实现全方位精确跟踪的理想方案,它通过经度轴(水平旋转)和纬度轴(俯仰调节) 的组合,使光伏板能追踪太阳一天内和一年内的轨迹变化,本次我使用的也是双轴跟踪的形式
机械结构使用3D打印
Github代码:github.com/tommyzhng/ros-antenna-tracker


系统工作流程
结构框图

1.电源电路与能源转换
一、电源电路
电源部分我采用XL4015DC-DC降压电路,将12V电源输入转成5V给单片机和舵机,之所以选用12的电池是因为后续我要给这个项目加上逆变模块,将12V的直流电转成220V交流电给后端的产品


二、能源转换
采用CN3791MPPT算法芯片最大功率点跟踪
关于CN3791的电路,详细可以看我的另一篇文章
基于CN3791的太阳能MPPT充电电路搭建_cn3791太阳能充电电路图-CSDN博客

三、误区(失败经验)
再这个太阳能追光的项目中,对于电源电路我遇到了几个误区
1.IP5306
开始我采用IP5306作为我的电源芯片,考虑到这个芯片不仅可以实现我3.7v锂电池升压5v,还能满足充电的需求
淘汰掉这个方案,也是因为我意识到,太阳能充电并不简单,光照影响充电,选用普通的充电电路,效果也不理想,还是需要Mppt算法,由于时间原因,在第一板电路只完成了,最基本移动的调试
2.FP6298
后又采用单节18650锂电池经FP6298升压至5V,理论峰值输出2A,满足静态功耗
满足静态功耗,需求还不够,舵机在堵转状态下的电流达2.5A,在我3.7v锂电池升压电路中,找不到合适的来运用到我的作品中

3. 3.7V聚合物锂电池
开始采用3.7v的电池,后发现这样的电池,无法给电机和舵机等有大启动电流的产品供电

2.四路光强调节
+Y方向
|
光敏电阻1 | 光敏电阻2
|
-X方向 ------+------ +X方向
|
光敏电阻4 | 光敏电阻3
|
-Y方向
这次我采用了4路光敏的形式,stc12c5a60s2单片机P1口自带adc采集的功能,在前期调试的阶段使用4个手调电阻来代替,OLED显示屏可以显示当前的adc值,来辅助调试

这里因为OLED显示屏刷新所以手机拍出来显示不完整
调试前期我用4路的手调电阻来模拟光敏,这样能更直观的控制adc读取值的变化

下面这个是我画的光敏底座


3.追光算法
我的这一套算法,主要就是通过,四个角上的光敏adc采集,计算得出水平差异和垂直差异,根据差异值与平均值得出的比例差异,来控制舵机的移动,开始我让舵机一次性转到位,但因为读取周期的原因有时舵机会抽动,后我添加了舵机调整步长,让180度舵机的每一步都相同,这样减少了舵机抽动的问题
水平差异 = 左-右
垂直差异 = 上-下
水平平均 = (左+右)/2
垂直平均 = (上+下)/2
水平比例差异 = 水平差异/水平平均
垂直比例差异 = 垂直差异/垂直平均光照
如果 水平比例差异 > 光照差异阈值
360度舵机向左转
如果 水平比例差异 < -光照差异阈值
360度舵机向右转
都不满足 ==》 360度舵机不转
如果 垂直比例差异 >光照差异阈值
Int 调整步长 > 固定值
设置180度舵机位置=当前位置-固定值
这是我的算法程序,360度的舵机通过最慢的移动速度移动,设置180度舵机的位置区间,防止舵机位置超程
void Track_Sun()
{
int zcgm,ycgm,scgm,xcgm,level,vertical;
float spblcy = 0,czblcy = 0;
// 计算垂直方向差异 (左右比较)
zcgm = num3 + num2 + 130;//左侧光敏
ycgm = num0 + num1; //右侧光敏
diff_horizontal = zcgm - ycgm;
// 计算垂直方向差异 (上下比较)
xcgm = num2 + num0;//下侧光敏
scgm = num3 + num1;//上侧光敏
diff_vertical = scgm - xcgm;
level = (zcgm + ycgm) / 2;
vertical = (scgm + xcgm) / 2;
if(diff_horizontal > THRESHOLD){pwm1 = 12;}
else if(diff_horizontal < -THRESHOLD){pwm1 = 14;}
else {pwm1 = 13;}
if(diff_vertical > THRESHOLD)
{
if(pwm0<=23){pwm0--;}
}
if(diff_vertical < -THRESHOLD)
{
if(pwm0>=14){pwm0++;}
}
}
4.原理图与pcb



5.代码程序
#include <STC12C5A60S2.H>
#include "oled.h"
#include "adc.h"
#define THRESHOLD 50 // 光照差异阈值
sbit dj2 = P0^4;//180°舵机
sbit dj1 = P0^5;//360°舵机
int num0,num1,num2,num3,diff_horizontal, diff_vertical;
float res0,res1,res2,res3;
int pwm0,time0,pwm1;
void delay(unsigned int ms)
{
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 110; j++);
}
void Servo_Init()
{
// 设置定时器1为16位定时器,用于舵机PWM控制
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x10; // 设置定时器1为模式1(16位定时器)
TH1 = (65536 - 100) / 256 ; // 100us中断
TL1 = (65536 - 100) % 256;
EA = 1; // 开总中断
ET1 = 1; // 开定时器1中断
TR1 = 1; // 启动定时器1
}
void ADCInit()
{
ADC_Init(ADC_PORT0);
ADC_Init(ADC_PORT1);
ADC_Init(ADC_PORT2);
ADC_Init(ADC_PORT3);
}
void ADCread()
{
res0=GetADCResult(ADC_CH1);//右下
num0 = res0*200;
res1=GetADCResult(ADC_CH0);//左下
num1 = res1*200;
res2=GetADCResult(ADC_CH2);//左上
num2 = res2*200;
res3=GetADCResult(ADC_CH3);//右上
num3 = res3*200;
}
void OLEDShow()
{
OLED_ShowNum(0,0,num3,3,16);
OLED_ShowNum(80,0,num1,3,16);
OLED_ShowNum(0,2,num2,3,16);
OLED_ShowNum(80,2,num0,3,16);
OLED_ShowNum(0,4,diff_horizontal,3,16);
OLED_ShowNum(80,4,diff_vertical,3,16);
OLED_ShowNum(0,6,pwm0,3,16);
OLED_ShowNum(80,6,pwm1,3,16);
}
void Track_Sun()
{
int zcgm,ycgm,scgm,xcgm,level,vertical;
float spblcy = 0,czblcy = 0;
// 计算垂直方向差异 (左右比较)
zcgm = num3 + num2 + 130;//左侧光敏
ycgm = num0 + num1; //右侧光敏
diff_horizontal = zcgm - ycgm;
// 计算垂直方向差异 (上下比较)
xcgm = num2 + num0;//下侧光敏
scgm = num3 + num1;//上侧光敏
diff_vertical = scgm - xcgm;
level = (zcgm + ycgm) / 2;
vertical = (scgm + xcgm) / 2;
if(diff_horizontal > THRESHOLD){pwm1 = 12;}
else if(diff_horizontal < -THRESHOLD){pwm1 = 14;}
else {pwm1 = 13;}
if(diff_vertical > THRESHOLD)
{
if(pwm0<=23){pwm0--;}
}
if(diff_vertical < -THRESHOLD)
{
if(pwm0>=14){pwm0++;}
}
}
void main()
{
OLED_Init();
ADCInit();
Servo_Init();
pwm0 = 18;
delay(500);
while(1)
{
Track_Sun();
ADCread();
OLEDShow();
}
}
void Timer1_ISR() interrupt 3
{
TH1 = (65536 - 100) / 256; // 重置100us中断
TL1 = (65536 - 100) % 256;
time0++;
time0%=200;
if(time0>=pwm0)
{dj2 = 0;}
else{dj2 = 1;}
if(time0>=pwm1)
{dj1 = 0;}
else{dj1 = 1;}
}
6.成果演示
因为光敏板的机械结构问题,光敏位置不同,会造成一些抖动
太阳能自动追光