前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于单片机设计的太阳能跟踪器

基于单片机设计的太阳能跟踪器

作者头像
DS小龙哥
发布于 2023-11-02 05:15:21
发布于 2023-11-02 05:15:21
43400
代码可运行
举报
运行总次数:0
代码可运行

一、前言

随着对可再生能源的需求不断增长,太阳能作为一种清洁、可持续的能源形式,受到越来越多的关注和应用。太阳能光板通常固定在一个固定的角度上,这限制了它们对太阳光的接收效率。为了充分利用太阳能资源,提高太阳能光板的收集效率,需要设计一个能够自动跟踪太阳光的系统。

本项目采用基于单片机的设计方案,主控芯片选择STC89C52。在太阳能光板的四个角上,安装了四个光敏电阻,它们用于检测四个方向太阳光的最强位置。每个光敏电阻通过PCF8591模块与主控芯片相连,利用模数转换器(ADC)采集各个通道的数据值。

通过对四个光敏传感器采集到的数据进行处理和比较,主控芯片能够确定太阳光的最强位置所在。然后,通过控制两个28BYJ-48-5V步进电机的运动,太阳能光板可以实现左右和上下方向的旋转。通过调整太阳能光板的倾斜角度,使其与太阳光保持垂直,以获得最大的太阳能收集效率。

该太阳能跟踪器的设计旨在实现自动化的太阳光追踪,以提高太阳能光板的能源收集效率。通过使用光敏电阻、ADC转换和步进电机控制等技术手段,系统能够准确地确定太阳光的位置,并自动调整太阳能光板的朝向。这将大大提高太阳能系统的能源输出,并为可再生能源的利用做出贡献。

二、系统设计思路

2.1 硬件选型

【1】主控芯片:STC89C52 STC89C52是一款高性价比的单片机,具有丰富的外设和强大的计算能力。采用基于MCS-51内核的8位单片机架构,拥有存储容量大(8KB Flash和256B RAM)和丰富的IO口(32个),适合控制太阳能跟踪器系统的各种功能。

【2】光敏电阻:选择具有高灵敏度和较小尺寸的光敏电阻,并根据光照条件进行选择。通过与PCF8591模块连接,可以将光敏电阻的电阻值变化转换为相应的模拟电压信号。

【3】ADC模块:PCF8591 PCF8591是一款常用的4通道12位ADC模块,适用于将模拟信号转换为数字信号。通过连接4个光敏电阻到PCF8591的4个输入通道上,可以实现数据的采集和转换。

【4】步进电机:28BYJ-48-5V 28BYJ-48-5V步进电机是一个小型、低功耗的步进电机,适用于低速应用。使用两个步进电机可以控制太阳能光板在水平和垂直方向上的旋转,为太阳能跟踪器提供多个方向的调整。

2.2 设计思路

【1】硬件连接:根据项目需求,将STC89C52主控芯片与PCF8591模块、ULN2003驱动模块、28BYJ-48-5V步进电机、光敏电阻等进行正确的引脚连接。

【2】初始化设置:在主函数开始部分,进行必要的初始化设置,例如设置I/O口方向、定义引脚连接、初始化I2C总线等。

【3】光敏电阻采集:通过PCF8591模块采集4个光敏电阻的数据。使用I2C通信协议,向PCF8591模块发送控制字节,选择光敏电阻通道,并通过ADC转换获取光敏电阻的数值。将采集到的数据存储在名为lightSensor的数组中,每个元素对应一个光敏电阻通道。

【4】确定最强光位置:根据采集到的光敏电阻数据,通过比较找到最强光的位置。遍历lightSensor数组,记录最大值的索引,表示最强光所在的方向。

【5】步进电机控制:根据最强光的位置控制步进电机的旋转,使太阳能光板朝向最大光的方向。根据最大光位置的索引,使用条件语句判断旋转方向,然后调用StepperMotor_Rotate函数控制步进电机旋转。根据需求,可以设置旋转步数和旋转方向,以实现精确的转动控制。

【6】延时等待:在步进电机旋转完成后,可以添加适当的延时,以等待太阳能光板调整到新的位置。可以根据实际情况调整延时时间,确保光板稳定后进行下一次采集和控制。

【7】循环执行:将上述步骤放置在一个无限循环中,以实现持续的太阳能跟踪。程序将不断采集光敏电阻数据、确定最强光位置,并通过步进电机控制太阳能光板旋转,以获得最大的太阳能收集效率。

三、项目代码

3.1 PCF8591采集代码

以下是利用PCF8591的光敏电阻采集并通过串口打印的实现代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <reg52.h>
#include <intrins.h>

// 定义PCF8591模块地址
#define PCF8591_ADDR 0x90

// 定义光敏电阻通道
#define LDR_CHANNEL_1 0x00
#define LDR_CHANNEL_2 0x01
#define LDR_CHANNEL_3 0x02
#define LDR_CHANNEL_4 0x03

// 定义波特率
#define BAUDRATE 9600

// 函数声明
void delay(unsigned int time);
void uartInit();
void uartSendByte(unsigned char dat);
void uartSendString(unsigned char *str);
void pcf8591Init();
unsigned char pcf8591ReadChannel(unsigned char channel);

void main() {
    unsigned char ldr1, ldr2, ldr3, ldr4;
    unsigned char str[20];
  
    uartInit();  // 初始化串口
    pcf8591Init();  // 初始化PCF8591模块
    
    while(1) {
        // 读取光敏电阻数据
        ldr1 = pcf8591ReadChannel(LDR_CHANNEL_1);
        ldr2 = pcf8591ReadChannel(LDR_CHANNEL_2);
        ldr3 = pcf8591ReadChannel(LDR_CHANNEL_3);
        ldr4 = pcf8591ReadChannel(LDR_CHANNEL_4);
      
        // 打印光敏电阻数据到串口
        sprintf(str, "LDR1: %d, LDR2: %d, LDR3: %d, LDR4: %d\r\n", ldr1, ldr2, ldr3, ldr4);
        uartSendString(str);
      
        delay(1000);  // 延时一段时间后再进行下一次采集和打印
    }
}

// 延时函数
void delay(unsigned int time) {
    unsigned int i, j;
  
    for(i = 0; i < time; i++) {
        for(j = 0; j < 125; j++);
    }
}

// 初始化串口
void uartInit() {
    TMOD = 0x20;  // 设置定时器1为模式2
    SCON = 0x50;  // 设置串口工作方式1,允许接收
    TH1 = 256 - _cror(_cror(FOSC/12, 4), 4) / BAUDRATE;  // 设置波特率
    TR1 = 1;  // 启动定时器1
}

// 串口发送单个字节
void uartSendByte(unsigned char dat) {
    SBUF = dat;
    while (!TI);  // 等待发送完成
    TI = 0;       // 清除发送完成标志位
}

// 串口发送字符串
void uartSendString(unsigned char *str) {
    while (*str) {
        uartSendByte(*str);
        str++;
    }
}

// 初始化PCF8591模块
void pcf8591Init() {
    // 发送启动转换命令
    I2C_Start();                     
    I2C_Send_Byte(PCF8591_ADDR);     // 发送设备地址
    I2C_Wait_Ack();
    I2C_Send_Byte(0x40);             // 发送转换命令,选择通道0
    I2C_Wait_Ack();
    I2C_Stop();
}

// 读取PCF8591模块的指定通道的数据值
unsigned char pcf8591ReadChannel(unsigned char channel) {
    unsigned char value;
  
    I2C_Start();
    I2C_Send_Byte(PCF8591_ADDR);      // 发送设备地址
    I2C_Wait_Ack();
    I2C_Send_Byte(channel);           // 发送通道号
    I2C_Wait_Ack();
    I2C_Start();                      // 重新启动
    I2C_Send_Byte(PCF8591_ADDR + 1);  // 发送读取命令
    I2C_Wait_Ack();
    value = I2C_Read_Byte();           // 读取数据
    I2C_Send_NAck();
    I2C_Stop();
  
    return value;
}

3.2 主项目框架代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <reg52.h>

// 定义PCF8591模块的引脚连接
#define PCF8591_ADDRESS 0x90  // PCF8591模块的I2C地址
#define PCF8591_CONTROL 0x00  // PCF8591模块的控制寄存器地址

// 定义步进电机的引脚连接
sbit IN1 = P1^0;  // 步进电机引脚1
sbit IN2 = P1^1;  // 步进电机引脚2
sbit IN3 = P1^2;  // 步进电机引脚3
sbit IN4 = P1^3;  // 步进电机引脚4

// 定义步进电机旋转方向
#define CW 0  // 顺时针
#define CCW 1  // 逆时针

// 定义光敏电阻通道
#define CHANNEL_0 0  // 光敏电阻通道0
#define CHANNEL_1 1  // 光敏电阻通道1
#define CHANNEL_2 2  // 光敏电阻通道2
#define CHANNEL_3 3  // 光敏电阻通道3

// 延时函数
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

// I2C总线启动
void I2C_Start() {
    SDA = 1;
    SCL = 1;
    delay(1);
    SDA = 0;
    delay(1);
    SCL = 0;
    delay(1);
}

// I2C总线停止
void I2C_Stop() {
    SDA = 0;
    SCL = 1;
    delay(1);
    SDA = 1;
    delay(1);
}

// I2C发送一个字节的数据
void I2C_SendByte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        SDA = (dat & 0x80) >> 7;
        dat <<= 1;
        delay(1);
        SCL = 1;
        delay(1);
        SCL = 0;
        delay(1);
    }
    SDA = 1;
    delay(1);
    SCL = 1;
    delay(1);
    while (SDA) continue;
    SCL = 0;
}

// 从PCF8591读取一个字节的数据
unsigned char PCF8591_ReadByte() {
    unsigned char i, dat = 0;
    SDA = 1;
    for (i = 0; i < 8; i++) {
        dat <<= 1;
        SCL = 0;
        delay(1);
        SCL = 1;
        delay(1);
        if (SDA) dat |= 0x01;
    }
    SCL = 0;
    return dat;
}

// 设置PCF8591的控制字节
void PCF8591_SetControl(unsigned char ctrl) {
    I2C_Start();
    I2C_SendByte(PCF8591_ADDRESS);
    I2C_SendByte(PCF8591_CONTROL);
    I2C_SendByte(ctrl);
    I2C_Stop();
}

// 读取光敏电阻的数据
unsigned int ReadLightSensor(unsigned char channel) {
    unsigned int value;
    PCF8591_SetControl(0x40 | channel);  // 选择光敏电阻通道
    delay(10);  // 延时等待转换完成
    I2C_Start();
    I2C_SendByte(PCF8591_ADDRESS | 0x01);  // 续上一段

    value = PCF8591_ReadByte();  // 读取高字节
    value = (value << 8) + PCF8591_ReadByte();  // 读取低字节
    I2C_Stop();
    return value;
}

// 控制步进电机旋转
void StepperMotor_Rotate(unsigned char direction, unsigned int steps) {
    unsigned int i;
    for (i = 0; i < steps; i++) {
        // 顺时针旋转
        if (direction == CW) {
            IN1 = 1; IN2 = 0; IN3 = 0; IN4 = 0;
            delay(10);
            IN1 = 0; IN2 = 1; IN3 = 0; IN4 = 0;
            delay(10);
            IN1 = 0; IN2 = 0; IN3 = 1; IN4 = 0;
            delay(10);
            IN1 = 0; IN2 = 0; IN3 = 0; IN4 = 1;
            delay(10);
        }
        // 逆时针旋转
        else if (direction == CCW) {
            IN1 = 0; IN2 = 0; IN3 = 0; IN4 = 1;
            delay(10);
            IN1 = 0; IN2 = 0; IN3 = 1; IN4 = 0;
            delay(10);
            IN1 = 0; IN2 = 1; IN3 = 0; IN4 = 0;
            delay(10);
            IN1 = 1; IN2 = 0; IN3 = 0; IN4 = 0;
            delay(10);
        }
    }
}

// 主函数
void main() {
    unsigned int lightSensor[4];
    unsigned char maxIndex;
    
    while (1) {
        // 采集光敏电阻数据
        lightSensor[0] = ReadLightSensor(CHANNEL_0);
        lightSensor[1] = ReadLightSensor(CHANNEL_1);
        lightSensor[2] = ReadLightSensor(CHANNEL_2);
        lightSensor[3] = ReadLightSensor(CHANNEL_3);
        
        // 确定最强光位置
        maxIndex = 0;
        if (lightSensor[1] > lightSensor[maxIndex]) maxIndex = 1;
        if (lightSensor[2] > lightSensor[maxIndex]) maxIndex = 2;
        if (lightSensor[3] > lightSensor[maxIndex]) maxIndex = 3;
        
        // 控制步进电机旋转
        if (maxIndex == 0) {
            StepperMotor_Rotate(CW, 100);  // 右转
        } else if (maxIndex == 1) {
            StepperMotor_Rotate(CCW, 100);  // 左转
        } else if (maxIndex == 2) {
            StepperMotor_Rotate(CW, 100);  // 右转
            StepperMotor_Rotate(CW, 100);  // 右转
        } else if (maxIndex == 3) {
            StepperMotor_Rotate(CCW, 100);  // 左转
            StepperMotor_Rotate(CCW, 100);  // 左转
        }
        
        delay(1000);  // 延时一段时间
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
​利用腾讯云轻量应用服务器Nextcloud应用镜像快速搭建私有同步云盘
Nextcloud是一款开源免费的云存储网盘软件,可以帮助您快速便捷地搭建一套属于自己或团队共享的云同步网盘,从而实现跨平台跨设备文件同步、共享、版本控制、团队协作等功能。
青阳
2021/03/22
13.9K1
​利用腾讯云轻量应用服务器Nextcloud应用镜像快速搭建私有同步云盘
腾讯云轻量快速搭建个人网盘
现在市面上的网盘大多数都限速,并且文件可能不安全,所以拥有一个自己的服务器就可以搭建轻便的个人网盘了,最方便的是你不需要任何tx服务器的知识,因为腾讯云轻量应用服务器已经把镜像安排好了,那么话不多说,我们马上开始吧!
星橙
2021/07/17
12.1K0
腾讯云轻量快速搭建个人网盘
基于腾讯云lighthouse搭建私有网盘Cloudreve【超高性价比】
很多小伙伴都有使用网盘存储的习惯,在本地存储不够的时候,将东西存储在网盘中,既可以随时备份,也不占用本地空间。
炒香菇的书呆子
2024/11/15
9200
基于腾讯云lighthouse搭建私有网盘Cloudreve【超高性价比】
轻量锐驰 x 轻量对象存储 搭建不限速网盘
大多数第三方网盘在进行分享时无法保障下载用户也享受高速下载的权益,而高昂的会员费+限速政策使不管是自己使用还是分享他人都会有不愉快的体验
小宇-xiaoyu
2025/01/21
6990
轻量锐驰 x 轻量对象存储 搭建不限速网盘
【5分钟玩转Lighthouse】这可能是全网最容易搭建的网盘
Cloudreve是一款开源的网盘软件,支持服务器本机、腾讯云COS等多种存储方式,提供离线下载、拖拽上传、在线预览等功能,可以帮助用户快速搭建个人或多人使用的网盘系统。Lighthouse Cloudreve应用镜像集合了Cloudreve、Nginx、MariaDB、宝塔Linux面板和Aria2。省去了安装Docker和Cloudreve的步骤,鼠标点一点,五分钟将您的Lighthouse变身云盘!
Scott1
2021/06/09
8.7K3
【5分钟玩转Lighthouse】这可能是全网最容易搭建的网盘
腾讯云轻量应用服务器快速搭建一个专属网盘
云盘我想大家接触的一定不会少。云盘很好地解决了文件存储和共享的问题,但随着大量云盘厂商的退出,剩余的云盘服务也越来越少。有些云盘虽然上传速度快,但是下载速度较慢,不开通会员基本无法使用。同时还存在云盘被破解、文件被盗的问题。考虑到文件存储、共享以及保证文件安全的问题,我也就产生了自己搭建云盘的想法。
青阳
2021/04/02
4K0
利用腾讯云轻量搭建属于自己的博客小程序
现在是QQ和微信内部流量的时代,如果你分享的链接可以在QQ和微信正常打开还好,但是如果变白或者变红那么就没有人愿意打开了,就像这样:
星橙
2021/09/09
4.3K0
利用腾讯云轻量搭建属于自己的博客小程序
自定义开源 Piwigo 相册——分享生活、记录漫漫人生路中的美好时光和感动
首先,你要拥有一台云服务器,这里购买的是腾讯云的轻量应用服务器。专属优惠购买连接:轻量应用服务器Lighthouse。新老用户同享!
星橙
2021/08/20
3.2K0
【玩转腾讯云】用轻量应用服务器搭建网站
不少小伙伴应该知道,腾讯云正在内测轻量应用服务器,而且马上就要公测了!我提前申请到了一台内测机器,那就来告诉大家,在公测后购买腾讯云轻量应用服务器之后如何玩转它吧,比如搭建静态或者动态网站!
Bess Croft
2020/06/12
11.9K2
【玩转腾讯云】用轻量应用服务器搭建网站
基于腾讯云轻量应用服务器和Umami部署网站流量统计后台
想知道自己网站,每天有多少人浏览?或者想更直观的查看自己网站的访客统计?很多人会使用Google Analytics等工具进行统计。一般统计的数据:
Mintimate
2022/03/01
5.9K2
基于腾讯云轻量应用服务器和Umami部署网站流量统计后台
腾讯云轻量应用服务器|3分钟带你快速搭建电商独立站
大家都知道,今年的经济形势比较严峻,那么作为夹缝中求生的中小企业就显得更加困难。在这种情况下,从企业的角度来考虑,如果还是像以往一样购买物理服务器,部署搭建基础的数据库服务,应用服务等,对于企业来说,确实是一笔不小的开支。那么在这样的情况下,企业上云无疑是最好的选择,于是腾讯云双十一首次推出了拼团GO活动,中小企业可以基于自身的业务场景需求来购买自己需要的云服务器、数据库、Redis等云产品服务,双十一钜惠活动地址:https://cloud.tencent.com/act/pro/double11-2024?fromSource=gwzcw.8891757.8891757.8891757
六月的雨在Tencent
2024/11/24
1K0
腾讯轻量应用服务器快速搭建一个高效博客
大家知道的是,我一直是腾讯云的忠实粉丝,现在的应用都是基于腾讯云的 Lighthouse。那么理所当然我下面讲的都是基于腾讯云的轻量应用服务器。
青阳
2021/03/22
1.9K0
腾讯轻量应用服务器快速搭建一个高效博客
腾讯云轻量应用服务器配置及建网站教程
腾讯云轻量应用服务器如何使用?新手站长以搭建WordPress为例,使用宝塔镜像,先在防火墙开通端口。腾讯云百科来详细说下腾讯云服务器从购买、配置到网站上线全流程,包括轻量服务器配置选择、应用镜像选择、重置密码、防火墙开放端口教程等详细教程:
用户9264446
2022/08/10
9.6K0
腾讯云轻量应用服务器配置及建网站教程
【好玩儿的Docker项目】用腾讯云轻量应用服务器10分钟搭建一个轻量的视频分享网站——Fireshare
文章首发于:https://blog.laoda.de/archives/docker-compose-install-fireshare
二十五画生
2022/11/10
3.8K0
【好玩儿的Docker项目】用腾讯云轻量应用服务器10分钟搭建一个轻量的视频分享网站——Fireshare
锐驰云端 轻速上云 腾讯云锐驰型轻量云服务器简单测评及其一应用——部署PhotoPrism
继2024年12月26日阿里云上架了200M峰值带宽不限制流量的轻量云服务器后,昨晚22:30,腾讯云也正式推出并全量发售自家的200M峰值带宽不限制流量的轻量云服务器——“腾讯云轻量应用服务器锐驰型套餐”,那么,小俊第一时间自费自购了一台2C2G200M的机器,接下来就带大家来抢先实机测评一下腾讯云轻量应用服务器锐驰型套餐以及小俊想到的其中一个主要应用场景吧!
小俊是我
2025/01/22
1.3K0
锐驰云端 轻速上云 腾讯云锐驰型轻量云服务器简单测评及其一应用——部署PhotoPrism
腾讯云— 轻量应用服务器实践
l只有地域,没有可用区,实际上轻量应用服务器的VPC,可用性组也是不存在的,默认完成创建并且不可定义。
Chris Fei
2021/06/26
15.4K0
腾讯云— 轻量应用服务器实践
腾讯云轻量应用服务器搭建一个Hexo静态博客
Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。 部署Hexo推荐使用【腾讯云】1核2G5M轻量应用服
zuantou
2022/04/25
1.1K1
腾讯云轻量应用服务器搭建一个Hexo静态博客
【玩转Lighthouse】使用 Cloudreve镜像快速搭建自己的私人网盘
1.首先得购买一台Lighthouse服务器,直接选择Cloudreve应用镜像(如已有Lighthouse服务器,重装系统选择该应用即可)。
用户5277074
2022/04/13
2K3
腾讯云轻量应用服务器和CVM云服务器有什么区别?
腾讯云轻量服务器和云服务器有什么区别?为什么轻量应用服务器价格便宜?是因为轻量服务器CPU内存性能比云服务器CVM性能差吗?轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境,云服务器CVM适合更复杂如高并发网站、大数据计算、机器学习等复杂应用场景。轻量服务器网从性能测试、网络带宽、计费价格、应用搭建及适合用户等方面来详细说明腾讯云轻量应用服务器和云服务器CVM区别:
上云小秘书
2023/04/10
9.9K0
腾讯云轻量应用服务器和CVM云服务器有什么区别?
双十一腾讯云轻量服务器成就个人网站
一直以来,我都渴望拥有一个属于自己的个人网站,用于记录生活点滴、分享兴趣爱好和专业知识。在众多的服务器选择中,我最终将目光锁定在了腾讯云的轻量级应用服务器上。
Khan安全团队
2024/11/23
4420
推荐阅读
相关推荐
​利用腾讯云轻量应用服务器Nextcloud应用镜像快速搭建私有同步云盘
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档