引言
本项目设计了一个基于STM32的太阳跟踪系统,通过光敏传感器阵列实时检测太阳位置,并控制电机驱动太阳能板或光伏板跟随太阳移动,从而最大化太阳能的利用效率。该系统使用双轴运动控制,实现水平和垂直方向的精确跟踪,使太阳能板始终对准太阳位置。
环境准备
1. 硬件设备
- STM32F103C8T6 开发板(或其他 STM32 系列)
- 4 个光敏传感器(如光敏电阻,用于检测不同方向的光强)
- L298N 电机驱动模块(用于控制双轴电机)
- 2 个直流电机(用于水平和垂直方向控制)
- PWM 控制器(用于调节电机速度)
- OLED 显示屏(用于显示当前状态和光强信息)
- 面包板和杜邦线
- USB-TTL 串口调试工具
2. 软件工具
- STM32CubeMX:用于初始化 STM32 外设。
- Keil uVision 或 STM32CubeIDE:用于编写和下载代码。
- ST-Link 驱动程序:用于下载程序到 STM32。
项目实现
1. 硬件连接
- 光敏传感器连接:将4个光敏传感器放置在太阳能板的四个角落(左上、右上、左下、右下),分别连接到 STM32 的 ADC 输入引脚(如 PA0、PA1、PA2、PA3),用于检测不同方向的光强。
- 电机驱动连接:将 L298N 电机驱动模块的输入引脚连接到 STM32 的 GPIO(如 PA8、PA9、PA10、PA11,用于水平电机控制),另一些 GPIO(如 PA12、PB0、PB1、PB2,用于垂直电机控制)。
- PWM 控制连接:将 PWM 输出引脚连接到 L298N 的使能引脚,用于调节电机速度。
- OLED 显示屏连接:将 OLED 的 SDA 和 SCL 引脚连接到 STM32 的 I2C 接口(如 PB6 和 PB7),用于显示光强和系统状态。
2. STM32CubeMX 配置
- 打开 STM32CubeMX,选择你的开发板型号。
- 配置系统时钟为 HSI,确保系统稳定运行。
- 配置 GPIO 引脚用于电机控制。
- 配置 I2C,用于与 OLED 显示屏通信。
- 配置 ADC 用于读取光敏传感器的数据。
- 配置 TIM1 生成 PWM 信号,用于调节电机速度。
- 生成代码,选择 Keil 或 STM32CubeIDE 作为工具链。
3. 编写主程序
在生成的项目基础上,编写光强检测、太阳位置判断、电机控制以及状态显示的代码。以下是太阳跟踪系统的基本代码示例:
#include "stm32f1xx_hal.h"
#include "adc.h"
#include "tim.h"
#include "oled.h"
// 定义光强阈值和误差范围
#define LIGHT_THRESHOLD 50 // 光强差异阈值
#define PWM_SPEED 80 // 电机的默认速度
// 电机控制引脚定义
#define MOTOR_HORIZON_FWD_PIN GPIO_PIN_8
#define MOTOR_HORIZON_BWD_PIN GPIO_PIN_9
#define MOTOR_VERTICAL_UP_PIN GPIO_PIN_12
#define MOTOR_VERTICAL_DOWN_PIN GPIO_PIN_13
#define MOTOR_HORIZON_PORT GPIOA
#define MOTOR_VERTICAL_PORT GPIOA
// 函数声明
void System_Init(void);
void Adjust_Position(void);
uint16_t Read_Light(uint8_t channel);
void Control_Motor(uint8_t motor, int8_t direction, uint8_t speed);
void Display_Status(uint16_t left_up, uint16_t right_up, uint16_t left_down, uint16_t right_down);
// 全局变量
uint16_t light_left_up, light_right_up, light_left_down, light_right_down;
void System_Init(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_ADC1_Init();
MX_TIM1_Init();
OLED_Init();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动 PWM 通道 1
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // 启动 PWM 通道 2
OLED_ShowString(0, 0, "Solar Tracker Ready");
}
// 读取光敏传感器数据
uint16_t Read_Light(uint8_t channel)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return value;
}
// 调节太阳能板位置
void Adjust_Position(void)
{
// 读取光强数据
light_left_up = Read_Light(0);
light_right_up = Read_Light(1);
light_left_down = Read_Light(2);
light_right_down = Read_Light(3);
// 水平方向调整
if (abs(light_left_up + light_left_down - light_right_up - light_right_down) > LIGHT_THRESHOLD)
{
if (light_left_up + light_left_down > light_right_up + light_right_down)
{
Control_Motor(0, -1, PWM_SPEED); // 左转
}
else
{
Control_Motor(0, 1, PWM_SPEED); // 右转
}
}
else
{
Control_Motor(0, 0, 0); // 停止水平电机
}
// 垂直方向调整
if (abs(light_left_up + light_right_up - light_left_down - light_right_down) > LIGHT_THRESHOLD)
{
if (light_left_up + light_right_up > light_left_down + light_right_down)
{
Control_Motor(1, 1, PWM_SPEED); // 向上
}
else
{
Control_Motor(1, -1, PWM_SPEED); // 向下
}
}
else
{
Control_Motor(1, 0, 0); // 停止垂直电机
}
// 显示当前状态
Display_Status(light_left_up, light_right_up, light_left_down, light_right_down);
}
// 控制电机,motor=0表示水平电机,1表示垂直电机,direction为1表示正向,-1表示反向
void Control_Motor(uint8_t motor, int8_t direction, uint8_t speed)
{
if (motor == 0) // 水平电机
{
if (direction == 1)
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_RESET);
}
else if (direction == -1)
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_RESET);
}
}
else if (motor == 1) // 垂直电机
{
if (direction == 1)
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_RESET);
}
else if (direction == -1)
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_RESET);
}
}
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, speed); // 调整 PWM 占空比
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, speed);
}
// 显示当前光强状态
void Display_Status(uint16_t left_up, uint16_t right_up, uint16_t left_down, uint16_t right_down)
{
OLED_Clear();
OLED_ShowString(0, 0, "LU:");
OLED_ShowNumber(32, 0, left_up, 4);
OLED_ShowString(0, 1, "RU:");
OLED_ShowNumber(32, 1, right_up, 4);
OLED_ShowString(0, 2, "LD:");
OLED_ShowNumber(32, 2, left_down, 4);
OLED_ShowString(0, 3, "RD:");
OLED_ShowNumber(32, 3, right_down, 4);
}
4. 主程序逻辑
以下是主程序的逻辑,通过不断读取光敏传感器的数据,调整太阳能板的角度,以确保太阳能板始终对准光源方向:
int main(void)
{
System_Init();
while (1)
{
Adjust_Position(); // 调整太阳能板的位置
HAL_Delay(500); // 每0.5秒更新一次光强检测和调整
}
}
5. 各模块代码
光敏传感器读取
光敏传感器通过 ADC 读取光强的电压值,并转换为数值:
#include "adc.h"
// 读取光敏传感器数据
uint16_t Read_Light(uint8_t channel)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return value;
}
电机控制
电机控制部分通过 L298N 电机驱动模块控制太阳能板的双轴运动,包括向上、向下、左转和右转:
#include "gpio.h"
#include "tim.h"
// 控制电机,motor=0表示水平电机,1表示垂直电机,direction为1表示正向,-1表示反向
void Control_Motor(uint8_t motor, int8_t direction, uint8_t speed)
{
if (motor == 0) // 水平电机
{
if (direction == 1)
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_RESET);
}
else if (direction == -1)
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_FWD_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_HORIZON_PORT, MOTOR_HORIZON_BWD_PIN, GPIO_PIN_RESET);
}
}
else if (motor == 1) // 垂直电机
{
if (direction == 1)
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_RESET);
}
else if (direction == -1)
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_UP_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_VERTICAL_PORT, MOTOR_VERTICAL_DOWN_PIN, GPIO_PIN_RESET);
}
}
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, speed); // 调整 PWM 占空比
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, speed);
}
OLED 显示
OLED 显示屏用于显示当前各个光敏传感器检测到的光强,便于调试和实时监控系统状态:
#include "oled.h"
// 初始化 OLED
void OLED_Init(void)
{
// OLED 初始化代码
}
// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, char *str)
{
// 在 OLED 上显示字符串
}
// 显示数字
void OLED_ShowNumber(uint8_t x, uint8_t y, uint16_t num, uint8_t len)
{
// 在 OLED 上显示数字
}
// 清屏
void OLED_Clear(void)
{
// 清除 OLED 上的显示内容
}
⬇帮大家整理了单片机的资料
包括stm32的项目合集【源码+开发文档】
点击下方蓝字即可领取,感谢支持!⬇
点击领取更多嵌入式详细资料
问题讨论,stm32的资料领取可以私信!
6. 系统工作原理
- 光强检测与分析:通过 4 个光敏传感器分别检测太阳能板四个方向(左上、右上、左下、右下)的光强,并通过对比这些数据,判断太阳的位置。
- 方向调整:当左侧的光强大于右侧时,太阳能板向左调整,反之则向右调整。同理,当上方的光强大于下方时,太阳能板向上调整,反之则向下调整。调整的灵敏度由
LIGHT_THRESHOLD
参数控制。 - 电机控制:系统通过 PWM 信号控制 L298N 模块的输入端,从而调节直流电机的转速,实现对太阳能板的平稳旋转。
- 状态显示:OLED 显示屏实时显示光强检测的数值,帮助用户直观了解各方向的光强差异以及系统调整的动作。
7. 常见问题与解决方法
1. 太阳能板调整不稳定
- 问题原因:光敏传感器灵敏度差异或环境光变化剧烈。
- 解决方法:通过增加
LIGHT_THRESHOLD
的值,降低系统对光强变化的敏感度,以减小不必要的频繁调整。同时,确保光敏传感器对环境光变化具有一致的响应。
2. 电机无法平稳运转
- 问题原因:PWM 信号频率设置不当或电机驱动模块功率不足。
- 解决方法:调整 PWM 频率到适合电机的范围(通常为1kHz~10kHz),并检查 L298N 驱动模块是否满足电机的电流需求。
3. 光强数据读取不准确
- 问题原因:光敏传感器安装不对称或ADC配置错误。
- 解决方法:确保光敏传感器的安装对称且角度一致,同时检查 ADC 配置是否正确(如分辨率和采样时间)。
4. OLED 显示屏不工作
- 问题原因:I2C 通信错误、连接不良或 OLED 供电不足。
- 解决方法:检查 I2C 通信线路的连接,确保 SDA 和 SCL 引脚与 STM32 的 I2C 接口正确连接,确保 OLED 显示屏的供电电压在额定范围内。
8. 扩展功能
- 远程监控与数据上传:可以增加 ESP8266 模块或其他 Wi-Fi 模块,将光强数据和电机状态上传至云端服务器,用户可以通过手机或电脑远程查看太阳能板的状态和调整情况。
- 智能算法优化:利用 PID 控制算法来优化太阳能板的调整过程,使其在调整过程中更加平稳,减少震动和能量损耗。
- 自动校准功能:加入光传感器的自动校准功能,在每天日出时段进行自动校准,使系统适应不同的光照环境。
9. 结论
通过本项目,我们成功设计了一个基于 STM32 的太阳跟踪系统,实现了双轴的太阳能板跟踪控制。该系统能够实时检测太阳位置,并通过调整电机驱动太阳能板对准太阳,从而提升光伏板的发电效率。系统的可扩展性和开放性使其适用于家庭、实验室或教学场景,是一个深入学习嵌入式控制与物联网技术的理想项目。同时,通过进一步优化系统和增加远程监控功能,可以将其应用于实际的太阳能发电系统,具有广泛的应用前景。