1. 项目概述
太阳能追踪系统是提升光伏发电效率的有效解决方案。相比固定安装的太阳能板,采用双轴追踪系统能够显著提升发电量20%-40%。这个基于STM32G0的项目实现了从太阳位置计算到机械追踪的完整闭环控制,特别适合作为嵌入式学习和新能源应用的实践案例。
1.1 硬件选型解析
硬件选型遵循"低成本、易获取、高可靠性"原则,所有组件均可在主流电商平台采购:
-
主控芯片:STM32G030C8T6是ST新一代高性价比MCU,64MHz主频完全满足实时计算需求,内置RTC模块为时间计算提供硬件支持。选择核心板形式(约15元)可省去外围电路设计。
-
驱动电机:28BYJ-48步进电机(约8元)配合ULN2003驱动板(约3元)组成经济型驱动方案。该电机减速比为1:64,步距角5.625°,经64细分后每步0.08789°,满足追踪精度要求。
-
功率检测:INA219模块(约12元)通过I2C接口提供16位精度的电压电流检测,最大支持26V/3.2A测量范围,内置PGA可编程增益放大器。
-
太阳能板:5V/10W多晶硅板(约25元)作为测试负载,实际应用可替换更大功率组件。注意需匹配INA219的量程范围。
关键提示:ULN2003驱动板与电机连接时,务必确保接线顺序正确。错误的相序会导致电机抖动或无法运转。建议先用杜邦线测试电机各相导通性。
1.2 开发环境配置
软件工具链采用ST官方免费方案:
-
STM32CubeIDE:集成开发环境(版本1.15.0),包含代码编辑、编译、调试全套工具。安装时注意勾选STM32G0系列支持包。
-
STM32CubeG0 HAL库(版本1.6.0):提供硬件抽象层驱动,简化外设初始化流程。通过CubeMX图形化工具可快速生成初始化代码。
-
调试工具:
- ST-Link V2编程器(兼容版约15元)
- 串口调试助手(如Putty或SSCOM)用于输出调试信息
开发环境搭建常见问题:
- 若无法识别ST-Link,需安装对应驱动
- 新建工程时务必选择正确的芯片型号(STM32G030C8T6)
- 首次使用CubeMX配置后,记得生成代码前保存.ioc文件
2. 系统架构与工作流程
2.1 系统控制逻辑
系统采用"计算-检测-调整"的闭环控制策略:
-
位置计算层:通过RTC获取本地时间,结合预设的经纬度坐标,使用天文算法计算太阳实时位置(方位角+高度角)
-
功率检测层:INA219持续监测太阳能板输出电压电流,计算瞬时功率值
-
运动控制层:比较理论太阳位置与实际功率关系,驱动步进电机调整太阳能板朝向
2.2 关键算法选择
2.2.1 太阳位置计算
采用Jean Meeus的《天文算法》中的低精度公式(误差±0.25°),在保证精度的同时降低计算负担。主要计算步骤:
- 计算儒略日(Julian Day)
- 求解太阳黄道经度
- 计算赤道坐标转换
- 最终得出地平坐标系下的方位角和高度角
2.2.2 MPPT控制
选用扰动观察法(Perturb and Observe),因其实现简单且对传感器精度要求较低。算法核心逻辑:
- 主动施加小角度扰动(±1°)
- 比较扰动前后功率变化
- 沿功率增加方向继续调整
- 当功率变化小于阈值时停止
实测技巧:将初始扰动步长设为1°,功率阈值设为0.01W。在晴天条件下,系统通常能在3-5次调整后锁定最大功率点。
3. 核心功能实现详解
3.1 太阳角度计算实现
3.1.1 天文算法代码解析
在sun_angle_calculation.c中,关键函数实现如下:
c复制// 计算儒略日(基准日期为公元前4713年)
static double CalculateJulianDay(RTC_TimeTypeDef time) {
int Y = time.year;
int M = time.month;
// 1月2月视为前一年的13月14月
if (M <= 2) { Y--; M += 12; }
int A = Y / 100;
int B = 2 - A + A / 4; // 格里高利历修正
return floor(365.25*(Y+4716)) + floor(30.6001*(M+1))
+ D + B - 1524.5 + h/24.0;
}
// 主计算函数
SunAngleTypeDef CalculateSunAngle(RTC_TimeTypeDef current_time) {
double JD = CalculateJulianDay(current_time);
double T = (JD - 2451545.0) / 36525.0; // 儒略世纪数
// 太阳平黄经(deg)
double L = fmod(280.46646 + 36000.76983*T + 0.0003032*T*T, 360.0);
// 太阳平近点角(deg)
double g = fmod(357.52911 + 35999.05029*T - 0.0001537*T*T, 360.0);
// 黄道倾角计算(考虑章动影响)
double epsilon = 23.0 + (26.0 + (21.448 - T*(46.8150 + T*(0.00059 - T*0.001813))))/60.0;
epsilon += 0.00256 * cos(DEG_TO_RAD(125.04 - 1934.136*T));
// 时角计算(本地恒星时转换)
double GMST = fmod(6.697374558 + 0.06570982441908*(JD-2451545.0)
+ current_time.hour + current_time.minute/60.0, 24.0);
double LMST = fmod(GMST*15.0 + LONGITUDE, 360.0);
// 高度角计算
double sin_elevation = sin(DEG_TO_RAD(LATITUDE))*sin(DEG_TO_RAD(delta))
+ cos(DEG_TO_RAD(LATITUDE))*cos(DEG_TO_RAD(delta))*cos(DEG_TO_RAD(H));
sun_angle.elevation = RAD_TO_DEG(asin(sin_elevation));
// 方位角修正
if (sin(DEG_TO_RAD(H)) > 0) {
sun_angle.azimuth = 360 - sun_angle.azimuth;
}
}
3.1.2 精度优化技巧
-
浮点运算优化:STM32G0没有FPU,应尽量减少浮点运算。实测将
math.h替换为ARM的arm_math.h可提升约15%计算速度。 -
经纬度设置:在
sun_angle_calculation.h中修改宏定义:
c复制#define LATITUDE 39.9f // 北京纬度
#define LONGITUDE 116.4f // 北京经度
- RTC校准:使用HSE时钟源(误差±500ppm)时,每月会产生约43秒误差。建议:
- 通过串口定期同步网络时间
- 或使用GPS模块提供时间基准
3.2 步进电机驱动实现
3.2.1 电机控制代码解析
28BYJ-48采用四相八拍驱动方式,相序表如下:
c复制// 步进电机相序表(四相八拍)
static const uint8_t step_sequence[8][4] = {
{1, 0, 0, 0}, // A相
{1, 1, 0, 0}, // AB相
{0, 1, 0, 0}, // B相
{0, 1, 1, 0}, // BC相
{0, 0, 1, 0}, // C相
{0, 0, 1, 1}, // CD相
{0, 0, 0, 1}, // D相
{1, 0, 0, 1} // DA相
};
关键驱动函数:
c复制void StepperMotor_Step(MotorDirectionTypeDef dir, uint16_t steps, uint16_t delay_ms) {
static uint8_t current_step = 0;
for(uint16_t i=0; i<steps; i++) {
// 方向控制
dir == MOTOR_DIR_CW ? current_step++ : current_step--;
current_step %= 8;
// 输出相序
HAL_GPIO_WritePin(IN1_PORT, IN1_PIN, step_sequence[current_step][0]);
// ...其他三相类似
HAL_Delay(delay_ms); // 控制转速
}
// 断电防止过热
HAL_GPIO_WritePin(IN1_PORT, IN1_PIN, GPIO_PIN_RESET);
// ...其他三相
}
3.2.2 电机调试要点
-
失步问题处理:
- 降低步进速度(增加delay_ms)
- 检查电源电压(建议5V/1A以上)
- 添加加速曲线(步进间隔从大到小渐变)
-
定位精度校准:
c复制// 角度-步数换算(512步/圈)
float steps_per_degree = 1.0f / 0.08789f;
uint16_t steps = (uint16_t)(angle_diff * steps_per_degree);
- 机械安装建议:
- 使用联轴器连接电机轴和旋转支架
- 添加限位开关防止过冲
- 亚克力支架应保证太阳能板重心在转轴中心
3.3 MPPT算法实现
3.3.1 扰动观察法实现
在mppt_control.c中核心算法:
c复制float MPPT_GetMaxPowerAngle(float current_angle) {
float current_power = CollectPower();
float power_diff = current_power - mppt_status.last_power;
if(power_diff > POWER_THRESHOLD) {
// 功率增加,继续原方向
mppt_status.best_angle = current_angle + PERTURB_STEP;
}
else if(power_diff < -POWER_THRESHOLD) {
// 功率下降,反向调整
mppt_status.best_angle = current_angle - PERTURB_STEP;
}
// 角度限幅
if(mppt_status.best_angle < 0) mppt_status.best_angle += 360;
if(mppt_status.best_angle > 360) mppt_status.best_angle -= 360;
mppt_status.last_power = current_power;
return mppt_status.best_angle;
}
3.3.2 INA219校准技巧
- 校准寄存器计算:
c复制// 校准值 = 0.04096 / (电流量程 * 分流电阻)
// 示例:1A量程,0.1Ω电阻 => 0x0800
INA219_WriteReg(INA219_CALIB_REG, 0x0800);
-
采样优化:
- 设置16x采样平均(配置寄存器0x399F)
- 每次读取前等待转换完成(约1ms)
-
噪声处理:
c复制// 多次采样取平均
float voltage = 0;
for(int i=0; i<4; i++) {
voltage += INA219_ReadVoltage();
HAL_Delay(2);
}
voltage /= 4;
4. 系统集成与调试
4.1 硬件接线规范
完整接线表示例:
| 模块 | 信号线 | STM32引脚 | 备注 |
|---|---|---|---|
| ULN2003 | IN1 | PA0 | 步进电机相位A |
| ULN2003 | IN2 | PA1 | 相位B |
| INA219 | SCL | PB6 | I2C1_SCL,需上拉4.7kΩ |
| 太阳能板 | V+ | INA219_VIN+ | 注意极性防反接 |
关键提示:I2C总线必须接上拉电阻(通常4.7kΩ),否则通信会失败。若使用模块自带的上拉电阻,需确认其阻值是否合适(过大会导致信号上升沿缓慢)。
4.2 软件调试方法
- 串口调试输出:
c复制printf("Solar Tracking System Initialized\r\n");
printf("Current Angle: %.2f° Power: %.2fW\r\n", angle, power);
-
状态监控技巧:
- 使用FreeRTOS创建监控任务(可选)
- 添加LED状态指示(如电源、通信、错误状态)
-
故障排查流程:
- 检查电源电压(5V和3.3V)
- 验证I2C通信(用逻辑分析仪抓包)
- 测试电机相序(手动单步驱动)
- 检查RTC时间是否正确
4.3 性能优化建议
-
低功耗设计:
- 夜间进入休眠模式(STOP模式)
- 降低MPPT采样频率(晴天可设为5分钟/次)
-
算法加速:
- 预计算太阳位置表(每小时一个点)
- 使用查表法替代实时计算
-
可靠性增强:
- 添加看门狗(IWDG)
- 关键参数保存到Flash防丢失
5. 实测数据与效果分析
5.1 追踪效果对比
测试条件:北京晴天,5W太阳能板
| 模式 | 日均发电量 | 效率提升 |
|---|---|---|
| 固定安装 | 23.4Wh | - |
| 单轴追踪 | 28.7Wh | +22.6% |
| 双轴追踪 | 32.1Wh | +37.2% |
5.2 典型问题记录
-
电机堵转:
- 原因:机械阻力过大
- 解决:添加减速机构,降低步进速度
-
MPPT振荡:
- 现象:角度在小范围内来回调整
- 优化:动态调整扰动步长(功率变化大时用大步长)
-
计算溢出:
- 场景:连续运行多日后儒略日数值溢出
- 修正:使用double类型存储时间相关变量
这个系统在实际部署时,建议先进行室内测试:用手电筒模拟太阳运动轨迹,验证追踪算法和MPPT响应的正确性。室外安装时要注意防水防尘,特别是电机和电路板部分需要做好防护。
