• 方案介紹
    • 一、前言
    • 二、系統(tǒng)設(shè)計(jì)思路
    • 三、項(xiàng)目代碼
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STC89C52單片機(jī)設(shè)計(jì)的太陽能跟蹤器

5小時(shí)前
175
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請聯(lián)系.docx

共1個(gè)文件

一、前言

隨著對可再生能源的需求不斷增長,太陽能作為一種清潔、可持續(xù)的能源形式,受到越來越多的關(guān)注和應(yīng)用。太陽能光板通常固定在一個(gè)固定的角度上,這限制了它們對太陽光的接收效率。為了充分利用太陽能資源,提高太陽能光板的收集效率,需要設(shè)計(jì)一個(gè)能夠自動(dòng)跟蹤太陽光的系統(tǒng)。

本項(xiàng)目采用基于單片機(jī)的設(shè)計(jì)方案,主控芯片選擇STC89C52。在太陽能光板的四個(gè)角上,安裝了四個(gè)光敏電阻,它們用于檢測四個(gè)方向太陽光的最強(qiáng)位置。每個(gè)光敏電阻通過PCF8591模塊與主控芯片相連,利用模數(shù)轉(zhuǎn)換器ADC)采集各個(gè)通道的數(shù)據(jù)值。

通過對四個(gè)光敏傳感器采集到的數(shù)據(jù)進(jìn)行處理和比較,主控芯片能夠確定太陽光的最強(qiáng)位置所在。然后,通過控制兩個(gè)28BYJ-48-5V步進(jìn)電機(jī)的運(yùn)動(dòng),太陽能光板可以實(shí)現(xiàn)左右和上下方向的旋轉(zhuǎn)。通過調(diào)整太陽能光板的傾斜角度,使其與太陽光保持垂直,以獲得最大的太陽能收集效率。

該太陽能跟蹤器的設(shè)計(jì)旨在實(shí)現(xiàn)自動(dòng)化的太陽光追蹤,以提高太陽能光板的能源收集效率。通過使用光敏電阻、ADC轉(zhuǎn)換和步進(jìn)電機(jī)控制等技術(shù)手段,系統(tǒng)能夠準(zhǔn)確地確定太陽光的位置,并自動(dòng)調(diào)整太陽能光板的朝向。這將大大提高太陽能系統(tǒng)的能源輸出,并為可再生能源的利用做出貢獻(xiàn)。

image-20230823173509365

image-20230823173630278

二、系統(tǒng)設(shè)計(jì)思路

2.1 硬件選型

【1】主控芯片:STC89C52 STC89C52是一款高性價(jià)比的單片機(jī),具有豐富的外設(shè)和強(qiáng)大的計(jì)算能力。采用基于MCS-51內(nèi)核的8位單片機(jī)架構(gòu),擁有存儲(chǔ)容量大(8KB Flash和256B RAM)和豐富的IO口(32個(gè)),適合控制太陽能跟蹤器系統(tǒng)的各種功能。

【2】光敏電阻:選擇具有高靈敏度和較小尺寸的光敏電阻,并根據(jù)光照條件進(jìn)行選擇。通過與PCF8591模塊連接,可以將光敏電阻的電阻值變化轉(zhuǎn)換為相應(yīng)的模擬電壓信號。

【3】ADC模塊:PCF8591 PCF8591是一款常用的4通道12位ADC模塊,適用于將模擬信號轉(zhuǎn)換為數(shù)字信號。通過連接4個(gè)光敏電阻到PCF8591的4個(gè)輸入通道上,可以實(shí)現(xiàn)數(shù)據(jù)的采集和轉(zhuǎn)換。

【4】步進(jìn)電機(jī):28BYJ-48-5V 28BYJ-48-5V步進(jìn)電機(jī)是一個(gè)小型、低功耗的步進(jìn)電機(jī),適用于低速應(yīng)用。使用兩個(gè)步進(jìn)電機(jī)可以控制太陽能光板在水平和垂直方向上的旋轉(zhuǎn),為太陽能跟蹤器提供多個(gè)方向的調(diào)整。

2.2 設(shè)計(jì)思路

【1】硬件連接:根據(jù)項(xiàng)目需求,將STC89C52主控芯片與PCF8591模塊、ULN2003驅(qū)動(dòng)模塊、28BYJ-48-5V步進(jìn)電機(jī)、光敏電阻等進(jìn)行正確的引腳連接。

【2】初始化設(shè)置:在主函數(shù)開始部分,進(jìn)行必要的初始化設(shè)置,例如設(shè)置I/O口方向、定義引腳連接、初始化I2C總線等。

【3】光敏電阻采集:通過PCF8591模塊采集4個(gè)光敏電阻的數(shù)據(jù)。使用I2C通信協(xié)議,向PCF8591模塊發(fā)送控制字節(jié),選擇光敏電阻通道,并通過ADC轉(zhuǎn)換獲取光敏電阻的數(shù)值。將采集到的數(shù)據(jù)存儲(chǔ)在名為lightSensor的數(shù)組中,每個(gè)元素對應(yīng)一個(gè)光敏電阻通道。

【4】確定最強(qiáng)光位置:根據(jù)采集到的光敏電阻數(shù)據(jù),通過比較找到最強(qiáng)光的位置。遍歷lightSensor數(shù)組,記錄最大值的索引,表示最強(qiáng)光所在的方向。

【5】步進(jìn)電機(jī)控制:根據(jù)最強(qiáng)光的位置控制步進(jìn)電機(jī)的旋轉(zhuǎn),使太陽能光板朝向最大光的方向。根據(jù)最大光位置的索引,使用條件語句判斷旋轉(zhuǎn)方向,然后調(diào)用StepperMotor_Rotate函數(shù)控制步進(jìn)電機(jī)旋轉(zhuǎn)。根據(jù)需求,可以設(shè)置旋轉(zhuǎn)步數(shù)和旋轉(zhuǎn)方向,以實(shí)現(xiàn)精確的轉(zhuǎn)動(dòng)控制。

【6】延時(shí)等待:在步進(jìn)電機(jī)旋轉(zhuǎn)完成后,可以添加適當(dāng)?shù)难訒r(shí),以等待太陽能光板調(diào)整到新的位置。可以根據(jù)實(shí)際情況調(diào)整延時(shí)時(shí)間,確保光板穩(wěn)定后進(jìn)行下一次采集和控制。

【7】循環(huán)執(zhí)行:將上述步驟放置在一個(gè)無限循環(huán)中,以實(shí)現(xiàn)持續(xù)的太陽能跟蹤。程序?qū)⒉粩嗖杉饷綦娮钄?shù)據(jù)、確定最強(qiáng)光位置,并通過步進(jìn)電機(jī)控制太陽能光板旋轉(zhuǎn),以獲得最大的太陽能收集效率。

三、項(xiàng)目代碼

3.1 PCF8591采集代碼

以下是利用PCF8591的光敏電阻采集并通過串口打印的實(shí)現(xiàn)代碼。

#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

// 函數(shù)聲明
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) {
        // 讀取光敏電阻數(shù)據(jù)
        ldr1 = pcf8591ReadChannel(LDR_CHANNEL_1);
        ldr2 = pcf8591ReadChannel(LDR_CHANNEL_2);
        ldr3 = pcf8591ReadChannel(LDR_CHANNEL_3);
        ldr4 = pcf8591ReadChannel(LDR_CHANNEL_4);
      
        // 打印光敏電阻數(shù)據(jù)到串口
        sprintf(str, "LDR1: %d, LDR2: %d, LDR3: %d, LDR4: %drn", ldr1, ldr2, ldr3, ldr4);
        uartSendString(str);
      
        delay(1000);  // 延時(shí)一段時(shí)間后再進(jìn)行下一次采集和打印
    }
}

// 延時(shí)函數(shù)
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;  // 設(shè)置定時(shí)器1為模式2
    SCON = 0x50;  // 設(shè)置串口工作方式1,允許接收
    TH1 = 256 - _cror(_cror(FOSC/12, 4), 4) / BAUDRATE;  // 設(shè)置波特率
    TR1 = 1;  // 啟動(dòng)定時(shí)器1
}

// 串口發(fā)送單個(gè)字節(jié)
void uartSendByte(unsigned char dat) {
    SBUF = dat;
    while (!TI);  // 等待發(fā)送完成
    TI = 0;       // 清除發(fā)送完成標(biāo)志位
}

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

// 初始化PCF8591模塊
void pcf8591Init() {
    // 發(fā)送啟動(dòng)轉(zhuǎn)換命令
    I2C_Start();                     
    I2C_Send_Byte(PCF8591_ADDR);     // 發(fā)送設(shè)備地址
    I2C_Wait_Ack();
    I2C_Send_Byte(0x40);             // 發(fā)送轉(zhuǎn)換命令,選擇通道0
    I2C_Wait_Ack();
    I2C_Stop();
}

// 讀取PCF8591模塊的指定通道的數(shù)據(jù)值
unsigned char pcf8591ReadChannel(unsigned char channel) {
    unsigned char value;
  
    I2C_Start();
    I2C_Send_Byte(PCF8591_ADDR);      // 發(fā)送設(shè)備地址
    I2C_Wait_Ack();
    I2C_Send_Byte(channel);           // 發(fā)送通道號
    I2C_Wait_Ack();
    I2C_Start();                      // 重新啟動(dòng)
    I2C_Send_Byte(PCF8591_ADDR + 1);  // 發(fā)送讀取命令
    I2C_Wait_Ack();
    value = I2C_Read_Byte();           // 讀取數(shù)據(jù)
    I2C_Send_NAck();
    I2C_Stop();
  
    return value;
}

3.2 主項(xiàng)目框架代碼

#include <reg52.h>

// 定義PCF8591模塊的引腳連接
#define PCF8591_ADDRESS 0x90  // PCF8591模塊的I2C地址
#define PCF8591_CONTROL 0x00  // PCF8591模塊的控制寄存器地址

// 定義步進(jìn)電機(jī)的引腳連接
sbit IN1 = P1^0;  // 步進(jìn)電機(jī)引腳1
sbit IN2 = P1^1;  // 步進(jìn)電機(jī)引腳2
sbit IN3 = P1^2;  // 步進(jìn)電機(jī)引腳3
sbit IN4 = P1^3;  // 步進(jìn)電機(jī)引腳4

// 定義步進(jìn)電機(jī)旋轉(zhuǎn)方向
#define CW 0  // 順時(shí)針
#define CCW 1  // 逆時(shí)針

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

// 延時(shí)函數(shù)
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--);
}

// I2C總線啟動(dòng)
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發(fā)送一個(gè)字節(jié)的數(shù)據(jù)
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讀取一個(gè)字節(jié)的數(shù)據(jù)
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;
}

// 設(shè)置PCF8591的控制字節(jié)
void PCF8591_SetControl(unsigned char ctrl) {
    I2C_Start();
    I2C_SendByte(PCF8591_ADDRESS);
    I2C_SendByte(PCF8591_CONTROL);
    I2C_SendByte(ctrl);
    I2C_Stop();
}

// 讀取光敏電阻的數(shù)據(jù)
unsigned int ReadLightSensor(unsigned char channel) {
    unsigned int value;
    PCF8591_SetControl(0x40 | channel);  // 選擇光敏電阻通道
    delay(10);  // 延時(shí)等待轉(zhuǎn)換完成
    I2C_Start();
    I2C_SendByte(PCF8591_ADDRESS | 0x01);  // 續(xù)上一段

    value = PCF8591_ReadByte();  // 讀取高字節(jié)
    value = (value << 8) + PCF8591_ReadByte();  // 讀取低字節(jié)
    I2C_Stop();
    return value;
}

// 控制步進(jìn)電機(jī)旋轉(zhuǎn)
void StepperMotor_Rotate(unsigned char direction, unsigned int steps) {
    unsigned int i;
    for (i = 0; i < steps; i++) {
        // 順時(shí)針旋轉(zhuǎn)
        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);
        }
        // 逆時(shí)針旋轉(zhuǎn)
        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);
        }
    }
}

// 主函數(shù)
void main() {
    unsigned int lightSensor[4];
    unsigned char maxIndex;
    
    while (1) {
        // 采集光敏電阻數(shù)據(jù)
        lightSensor[0] = ReadLightSensor(CHANNEL_0);
        lightSensor[1] = ReadLightSensor(CHANNEL_1);
        lightSensor[2] = ReadLightSensor(CHANNEL_2);
        lightSensor[3] = ReadLightSensor(CHANNEL_3);
        
        // 確定最強(qiáng)光位置
        maxIndex = 0;
        if (lightSensor[1] > lightSensor[maxIndex]) maxIndex = 1;
        if (lightSensor[2] > lightSensor[maxIndex]) maxIndex = 2;
        if (lightSensor[3] > lightSensor[maxIndex]) maxIndex = 3;
        
        // 控制步進(jìn)電機(jī)旋轉(zhuǎn)
        if (maxIndex == 0) {
            StepperMotor_Rotate(CW, 100);  // 右轉(zhuǎn)
        } else if (maxIndex == 1) {
            StepperMotor_Rotate(CCW, 100);  // 左轉(zhuǎn)
        } else if (maxIndex == 2) {
            StepperMotor_Rotate(CW, 100);  // 右轉(zhuǎn)
            StepperMotor_Rotate(CW, 100);  // 右轉(zhuǎn)
        } else if (maxIndex == 3) {
            StepperMotor_Rotate(CCW, 100);  // 左轉(zhuǎn)
            StepperMotor_Rotate(CCW, 100);  // 左轉(zhuǎn)
        }
        
        delay(1000);  // 延時(shí)一段時(shí)間
    }
}
  • 更多詳細(xì)資料請聯(lián)系.docx
    下載

相關(guān)推薦