高精度伺服驱动太阳能跟踪平台:最大化光能捕获
组件与物料清单
| 组件 | 数量 | 备注 |
|---|---|---|
| 光敏电阻 (LDR) | 4 | 分别安装在太阳能板四角 |
| RGB NeoPixel LED (或等效全彩 LED) | 4 | 指示系统状态 |
| 12mm 轻触开关 | 2 | 红/绿按钮,启用/禁用跟踪 |
| 温度传感器 | 1 | 监测环境/面板温度 |
| Arduino UNO | 1 | |
| 180° 舵机 (如 Futaba S3003) | 2 | 水平旋转 + 垂直俯仰 |
| 10kΩ 电阻 | 6 | 按钮上拉、LDR 分压 |
| 220Ω 电阻 | 1 | LED 限流 |
| 100µF 电容 | 2 | 舵机供电滤波 |
| 80mm×80mm 太阳能电池板 | 1 | 可在 Amazon 等购买 |
所需工具与辅助材料
- 手工具、螺丝螺母(制作支架)
- 木块(作为水平舵机固定底座)
- 3mm 厚铝条(约 2cm 宽,折弯成 L 型支架)
- 薄钢带(风管固定带,预留安装孔,连接面板与俯仰舵机)
软件工具
- Arduino IDE
- Microsoft Excel(记录实验数据)
项目原理
采用双 180° 舵机 + 四角光敏电阻实现太阳能板双轴跟踪。控制器读取四角光照差异,驱动舵机微调面板姿态,使四角光照均衡(即面板正对光源)。系统包含:
- 状态指示 RGB LED(绿=跟踪中,红=禁用,蓝=诊断模式)
- 两枚按钮:绿键启用跟踪,红键禁用并脱离舵机
- 串口命令接口:支持手动定位、平滑移动、自动跟踪开关等指令
核心算法:光照差分跟踪
读取四 LDR 值:LDR1(左上)、LDR2(右上)、LDR3(左下)、LDR4(右下)
- 水平(扭转)轴:比较左侧平均
(LDR1+LDR3)/2与右侧平均(LDR2+LDR4)/2,亮侧方向转动。 - 垂直(俯仰)轴:比较上侧平均
(LDR1+LDR2)/2与下侧平均(LDR3+LDR4)/2,亮侧方向转动。 - 每次扫描步进 5°,配合 125ms 循环周期,实现平滑跟踪。
平滑移动机制
舵机直接写入目标角度会全速运动,导致机械冲击。代码实现 smoothMoveTwist() 与 smoothMoveTilt():每循环仅步进 1°,直到到达目标角度,避免剧烈抖动。
串口命令协议
格式:CCCCVVV(前 2 位命令类,后 3 位参数值)
| 命令类 | 参数值 | 功能 |
|---|---|---|
| 10 (杂项) | 0/1 | 开启/关闭诊断模式(蓝灯指示) |
| 10 | 2 | 上报产品信息 |
| 10 | 3-8 | 红/绿/蓝 LED 单独开关 |
| 10 | 9-12 | 显示 4 个 LDR 实时数值 |
| 10 | 13/14 | 启用/禁用舵机跟踪 |
| 10 | 19 | 双舵机复位 90° |
| 10 | 21/22 | 开启/关闭自动跟踪光源 |
| 11 (水平舵机) | 0-179 | 直接指定水平角度(平滑移动) |
| 12 (垂直舵机) | 0-179 | 直接指定垂直角度(平滑移动,限幅 45-135°) |
完整 Arduino 代码 (Q2 v2.0)
// Scott Mangiacotti, Tucson, Arizona, May 2018
#include <Servo.h>
const int GIVE_BACK_TIME = 125; // 主循环让出时间 ms
// 引脚定义
const int I_RED_BUTTON_PIN = 4;
const int I_GREEN_BUTTON_PIN = 2;
const int I_LDR1_PIN = A3; // 左上
const int I_LDR2_PIN = A2; // 右上
const int I_LDR3_PIN = A1; // 左下
const int I_LDR4_PIN = A0; // 右下
const int O_RED_LED_PIN = 9;
const int O_GREEN_LED_PIN = 11;
const int O_BLUE_LED_PIN = 10;
const int O_TWIST_SERVO_PIN = 5;
const int O_TILT_SERVO_PIN = 6;
// 全局变量
bool gRunning = false;
bool gTrackToLightEnabled = false;
bool gVerboseDiagMode = false;
Servo gServoTwist; int gServoTwistPositionCommand; bool gServoTwistMoveIP;
Servo gServoTilt; int gServoTiltPositionCommand; bool gServoTiltMoveIP;
int gLDR1, gLDR2, gLDR3, gLDR4;
void setup() {
Serial.begin(9600);
pinMode(I_RED_BUTTON_PIN, INPUT);
pinMode(I_GREEN_BUTTON_PIN, INPUT);
pinMode(O_RED_LED_PIN, OUTPUT);
pinMode(O_GREEN_LED_PIN, OUTPUT);
pinMode(O_BLUE_LED_PIN, OUTPUT);
startup();
}
void loop() {
// 串口命令处理
if (Serial.available() > 0) {
int code = Serial.parseInt();
processSerialMessage(code);
}
// 绿键启用
if (digitalRead(I_GREEN_BUTTON_PIN) == HIGH && !gRunning) { enableTracking(); gTrackToLightEnabled = true; }
// 红键禁用
if (digitalRead(I_RED_BUTTON_PIN) == HIGH && gRunning) { disableTracking(); }
readPhotoResistors();
if (gRunning) {
if (gTrackToLightEnabled) trackToLightSensors();
else { smoothMoveTwist(); smoothMoveTilt(); }
}
delay(GIVE_BACK_TIME);
}
// 启用跟踪:挂载舵机、绿灯亮
void enableTracking() {
gRunning = true;
gServoTwist.attach(O_TWIST_SERVO_PIN);
gServoTilt.attach(O_TILT_SERVO_PIN);
digitalWrite(O_GREEN_LED_PIN, HIGH); digitalWrite(O_RED_LED_PIN, LOW);
Serial.println("servos enabled");
}
// 禁用跟踪:卸载舵机、红灯亮
void disableTracking() {
gRunning = false; gTrackToLightEnabled = false;
gServoTwist.detach(); gServoTilt.detach();
gServoTwistPositionCommand = gServoTwist.read(); gServoTwistMoveIP = false;
gServoTiltPositionCommand = gServoTilt.read(); gServoTiltMoveIP = false;
digitalWrite(O_RED_LED_PIN, HIGH); digitalWrite(O_GREEN_LED_PIN, LOW);
Serial.println("servos disabled");
}
// 自动跟踪光源核心逻辑
void trackToLightSensors() {
float fTop = (gLDR1 + gLDR2) / 2.0;
float fBottom = (gLDR3 + gLDR4) / 2.0;
float fLeft = (gLDR1 + gLDR3) / 2.0;
float fRight = (gLDR2 + gLDR4) / 2.0;
int moveAmt = 5;
int twistCmd = gServoTwist.read();
int tiltCmd = gServoTilt.read();
if (fLeft > fRight) twistCmd += moveAmt; else if (fRight > fLeft) twistCmd -= moveAmt;
if (fTop > fBottom) tiltCmd += moveAmt; else if (fBottom > fTop) tiltCmd -= moveAmt;
twistCmd = constrain(twistCmd, 0, 179);
tiltCmd = constrain(tiltCmd, 45, 135); // 俯仰限幅防机械干涉
gServoTwist.write(twistCmd);
gServoTilt.write(tiltCmd);
if (gVerboseDiagMode) {
Serial.print("LDRs: "); Serial.print(gLDR1); Serial.print(","); Serial.print(gLDR2); Serial.print(","); Serial.print(gLDR3); Serial.print(","); Serial.println(gLDR4);
Serial.print("Avg: "); Serial.print(fTop); Serial.print(","); Serial.print(fBottom); Serial.print(","); Serial.print(fLeft); Serial.print(","); Serial.println(fRight);
Serial.print("Cmd: "); Serial.print(twistCmd); Serial.print(","); Serial.println(tiltCmd);
}
}
// 读取四路 LDR
void readPhotoResistors() {
gLDR1 = analogRead(I_LDR1_PIN);
gLDR2 = analogRead(I_LDR2_PIN);
gLDR3 = analogRead(I_LDR3_PIN);
gLDR4 = analogRead(I_LDR4_PIN);
}
// 平滑移动水平舵机
void smoothMoveTwist() {
const int step = 1;
int cur = gServoTwist.read();
if (cur == gServoTwistPositionCommand) { gServoTwistMoveIP = false; return; }
gServoTwistMoveIP = true;
int next = cur + (cur < gServoTwistPositionCommand ? step : -step);
next = constrain(next, 0, 179);
gServoTwist.write(next);
}
// 平滑移动垂直舵机
void smoothMoveTilt() {
const int step = 1;
int cur = gServoTilt.read();
if (cur == gServoTiltPositionCommand) { gServoTiltMoveIP = false; return; }
gServoTiltMoveIP = true;
int next = cur + (cur < gServoTiltPositionCommand ? step : -step);
next = constrain(next, 0, 179);
gServoTilt.write(next);
}
// 串口命令分发
void processSerialMessage(int code) {
int cmd = code / 1000;
int val = code % 1000;
Serial.print("code: "); Serial.println(code);
Serial.print("cmd: "); Serial.println(cmd);
Serial.print("val: "); Serial.println(val);
if (cmd == 10) { // 杂项
switch (val) {
case 0: gVerboseDiagMode = true; digitalWrite(O_BLUE_LED_PIN, HIGH); Serial.println("diag on"); break;
case 1: gVerboseDiagMode = false; digitalWrite(O_BLUE_LED_PIN, LOW); Serial.println("diag off"); break;
case 2: reportProductInfo(); break;
case 3: digitalWrite(O_RED_LED_PIN, HIGH); break;
case 4: digitalWrite(O_RED_LED_PIN, LOW); break;
case 5: digitalWrite(O_GREEN_LED_PIN, HIGH); break;
case 6: digitalWrite(O_GREEN_LED_PIN, LOW); break;
case 7: digitalWrite(O_BLUE_LED_PIN, HIGH); break;
case 8: digitalWrite(O_BLUE_LED_PIN, LOW); break;
case 9: Serial.print("LDR1: "); Serial.println(gLDR1); break;
case 10: Serial.print("LDR2: "); Serial.println(gLDR2); break;
case 11: Serial.print("LDR3: "); Serial.println(gLDR3); break;
case 12: Serial.print("LDR4: "); Serial.println(gLDR4); break;
case 13: enableTracking(); break;
case 14: disableTracking(); break;
case 19: if (gRunning && !gServoTwistMoveIP && !gServoTiltMoveIP) { gServoTwistPositionCommand = 90; gServoTiltPositionCommand = 90; Serial.println("home 90°"); } break;
case 21: if (gRunning) { gTrackToLightEnabled = true; Serial.println("track on"); } break;
case 22: gTrackToLightEnabled = false; Serial.println("track off"); break;
default: Serial.print("invalid val: "); Serial.println(val);
}
} else if (cmd == 11 && val >= 0 && val <= 179) { // 水平舵机
if (gRunning && !gServoTwistMoveIP) { gServoTwistPositionCommand = val; gServoTwistMoveIP = true; Serial.print("twist->"); Serial.println(val); }
} else if (cmd == 12 && val >= 0 && val <= 179) { // 垂直舵机
if (gRunning && !gServoTiltMoveIP) { gServoTiltPositionCommand = val; gServoTiltMoveIP = true; Serial.print("tilt->"); Serial.println(val); }
}
Serial.println("-----");
}
// 自检启动序列
void startup() {
int d = 500;
reportProductInfo(); delay(d);
processSerialMessage(10003); delay(d); // 红灯亮
processSerialMessage(10004); processSerialMessage(10005); delay(d); // 红灭绿亮
processSerialMessage(10006); processSerialMessage(10007); delay(d); // 绿灭蓝亮
processSerialMessage(10008); processSerialMessage(10009); processSerialMessage(10010); processSerialMessage(10011); processSerialMessage(10012); delay(d); // 显示4 LDR
enableTracking(); delay(d);
processSerialMessage(10019); delay(d); // 归中
disableTracking();
Serial.println("startup done");
}
void reportProductInfo() {
Serial.println("q version 2");
Serial.println("tucson, arizona usa");
Serial.println("may 2018");
Serial.println("checksum 58BA-D969-2F82-08FD-2078-2777-396D-E1AA");
}
3D 打印/机械结构文件
装配细节 STEP/ZIP 包:q2_assembly_details_RCbi893qzA.zip
原理图
Fritzing 原理图文件:q2_schematic_TVp7kakwNa.fzz
制造工艺
- 太阳能供暖系统:从被动式到主动式的可持续家居供暖方案
- 太阳能电池:从早期实验到现代光伏技术的演进与未来展望
- Arduino 实时太阳能电池板监测:低成本数据采集系统
- 智能窗帘:基于Arduino与太阳能的自动光控系统
- 物联网双轴太阳能跟踪器:基于 Arduino 与 Cayenne 的智能能源管理
- SmartPostBox:基于 Sigfox 的物联网智能信箱系统
- 双轴太阳能跟踪器:自动/手动模式切换,高效光伏追踪系统
- 便携式太阳能跟踪手机充电器:Arduino + 舵机自动追光
- 超声波眼睛:双 8×8 LED 矩阵跟随人体移动的互动装置
- 太阳能利用全指南:清洁可靠电力的获取与应用
- 光伏组件质量管控三大支柱:电池片/封装工艺/运维体系的关键控制点
- 太阳能电池组件制造全流程:从导电玻璃制备到层压装框的标准化生产