如上所述,太陽(yáng)能自動(dòng)跟蹤系統(tǒng)的軟件部分包含多個(gè)模塊,各模塊的啟動(dòng)和停止由單片機(jī)控制。在程序設(shè)計(jì)時(shí),將這些模塊的入口都安排在主程序中,主程序循環(huán)檢測(cè)通過(guò)串口接收的命令,通過(guò)對(duì)命令解釋,然后根據(jù)命令轉(zhuǎn)入相應(yīng)的模塊。程序流程圖如圖3.1。
系統(tǒng)軟件的設(shè)計(jì)主要是通過(guò)C語(yǔ)言編程實(shí)現(xiàn)單片機(jī)對(duì)步進(jìn)電機(jī)控制以及系統(tǒng)狀態(tài)的顯示。
系統(tǒng)通電后,首先對(duì)LCD,IO端口初始化,然后開(kāi)中斷,此時(shí)系統(tǒng)開(kāi)始工作,檢測(cè)當(dāng)前太陽(yáng)位置,直到接收板對(duì)準(zhǔn)太陽(yáng),實(shí)現(xiàn)對(duì)太陽(yáng)能全方位跟蹤。系統(tǒng)默認(rèn)時(shí)間是00:00,用戶可以根據(jù)當(dāng)?shù)貢r(shí)間調(diào)整系統(tǒng)時(shí)間。當(dāng)陰天時(shí),太陽(yáng)跟蹤系統(tǒng)檢測(cè)不到太陽(yáng),為了實(shí)現(xiàn)太陽(yáng)一出來(lái)就能自動(dòng)跟蹤太陽(yáng),系統(tǒng)時(shí)間每到12:00或18:00(也是太陽(yáng)落山),系統(tǒng)自動(dòng)控制接收板與大地垂直,這樣不管太陽(yáng)在那個(gè)位置,接收板都能檢測(cè)到太陽(yáng)。
圖中,啟動(dòng)后首先進(jìn)行的初始化包括:對(duì)單片機(jī)本身的中斷和LCD液晶顯示器等的初始化。
系統(tǒng)采用光敏電阻光強(qiáng)比較法,設(shè)計(jì)出一種全新的光電轉(zhuǎn)換裝置,很好的實(shí)現(xiàn)了光電轉(zhuǎn)換。它能夠利用光敏電阻比較法實(shí)現(xiàn)對(duì)太陽(yáng)水平、垂直方向的全方位跟蹤,晚上便自動(dòng)復(fù)位。當(dāng)太陽(yáng)的水平或垂直位置發(fā)生偏移時(shí),D1、D2或D3、D4(另一組控制電路)四個(gè)光電管中必有一個(gè)受陽(yáng)光照射,這樣就可確認(rèn)太陽(yáng)運(yùn)動(dòng)的方向了。控制電路有兩組,電路圖中是其中的一組,另一組電路與此相同。光電管是直接與控制電路連接的,當(dāng)太陽(yáng)能板正對(duì)太陽(yáng)時(shí),D1、D2都是高電阻,A、B兩點(diǎn)電壓相等。運(yùn)放輸出的電壓相同,單片機(jī)收到的信號(hào)差為零,所以單片機(jī)不控制電動(dòng)機(jī)轉(zhuǎn)動(dòng)。若陽(yáng)光發(fā)生傾斜,使Dl被陽(yáng)光射中呈低電阻,則A點(diǎn)電位比B點(diǎn)高,信號(hào)經(jīng)過(guò)放大和轉(zhuǎn)換,則單片機(jī)使得電機(jī)得電轉(zhuǎn)動(dòng)并拖動(dòng)太陽(yáng)能板轉(zhuǎn)動(dòng),使太陽(yáng)能板重新對(duì)準(zhǔn)太陽(yáng)。當(dāng)D1、D2重新轉(zhuǎn)為高電阻時(shí),電機(jī)停轉(zhuǎn)。若陽(yáng)光偏轉(zhuǎn)時(shí)使D2被陽(yáng)光射中則電機(jī)反轉(zhuǎn)。不論哪種情況,電機(jī)運(yùn)動(dòng)的方向和太陽(yáng)運(yùn)動(dòng)的方向總是一致的.從而達(dá)到了跟蹤的目的。當(dāng)光敏電阻對(duì)準(zhǔn)陽(yáng)光時(shí),采用微凋即可使得A、B兩點(diǎn)的電位相等,以提高系統(tǒng)的準(zhǔn)確度。
該程序中參數(shù) vol_value_2 是硅光片上面的光敏電阻經(jīng)過(guò)A/D轉(zhuǎn)換所得的電壓值,參數(shù)vol_value_4是硅光片下面的光敏電阻經(jīng)過(guò)A/D轉(zhuǎn)換所得的電壓值,上段程序是將上下兩個(gè)光敏電阻吸收的陽(yáng)光通過(guò)A/D轉(zhuǎn)換變?yōu)殡妷汉筮M(jìn)行比較,從而控制電機(jī)的正反轉(zhuǎn)。
3.3 太陽(yáng)能板二維角度調(diào)整模塊
3.3.1 電機(jī)水平轉(zhuǎn)動(dòng)控制部分
當(dāng)通過(guò)AD轉(zhuǎn)換后,單片機(jī)得到左右兩邊的輸出電壓,若左右兩邊的輸出電壓不相等時(shí),水平電機(jī)控制部分別開(kāi)始工作,若左邊電壓值比右邊電壓值高且左邊電壓與右邊電壓差的絕對(duì)值超過(guò)一定的范圍時(shí),電機(jī)開(kāi)始向右轉(zhuǎn),反之,若右面電壓比左面電壓大,且左右兩面電壓差的絕對(duì)值超過(guò)一定范圍后,電機(jī)向左轉(zhuǎn),否則,電機(jī)不轉(zhuǎn)動(dòng)。當(dāng)水平控制結(jié)束后,水平轉(zhuǎn)動(dòng)停止,垂直轉(zhuǎn)動(dòng)開(kāi)始。
在這個(gè)模塊中,超過(guò)一定是絕對(duì)值是為了避免因?yàn)楹苄〉恼`差或者一些沒(méi)有必要轉(zhuǎn)動(dòng)的情況下電機(jī)發(fā)生轉(zhuǎn)動(dòng),提高了電機(jī)的利用效率。
3.3.2 程序設(shè)計(jì)思想或說(shuō)明
通過(guò)AD轉(zhuǎn)換得到光敏電阻的電壓值,將左右或上下的電壓值進(jìn)行比較,根據(jù)電壓值的不同進(jìn)行電機(jī)的調(diào)整。以電機(jī)的水平調(diào)整為例,若左面電壓值大于右面電壓值,則表示左面接收的太陽(yáng)光必右面的多,則電機(jī)通過(guò)步進(jìn)電機(jī)向右轉(zhuǎn),在轉(zhuǎn)動(dòng)的同時(shí),左右兩面的電壓也一直還在比較,直到左右兩邊電壓相等或兩面電壓的絕對(duì)值在一定的范圍內(nèi),電機(jī)水平轉(zhuǎn)動(dòng)停止。
Main.c #include "msp430x14x.h" #include "adc12.h" #include "move.h" #include "cry1602.h"
unsigned char tishi_horizontal[] = {"HZ:"}; unsigned char tishi_vertical[] = {"VT:"}; unsigned char flag_horizontal_stop = 0; unsigned char flag_vertical_stop = 1; #define jingdu_horizontal 200 //水平精度控制 #define jingdu_vertical 200 //垂直精度控制 void motor_deal_horizontal(); //水平電機(jī)控制 void motor_deal_vertical(); //垂直電機(jī)控制 void main(void) { WDTCTL = WDTPW + WDTHOLD; P6DIR |= BIT2;P6OUT |= BIT2; //關(guān)閉電平轉(zhuǎn)換 P2DIR = 0xff; P2OUT = 0xf0; P1DIR = 0xff; P1OUT = 0xf0; LcdReset(); //復(fù)位1602液晶 DispNChar(0,0,3,tishi_horizontal); //顯示提示信息 DispNChar(0,1,3,tishi_vertical); //顯示提示信息 AD_Start(); while(1) { if((flag_vertical_stop == 1) && (flag_horizontal_stop ==0)) { motor_deal_horizontal(); //flag_vertical_stop = 0; } else if((flag_horizontal_stop == 1) && (flag_vertical_stop == 0)) { motor_deal_vertical(); //flag_horizontal_stop = 0; } else {;} } } void motor_deal_horizontal() //水平電機(jī)控制 { extern unsigned int vol_value_1; extern unsigned int vol_value_3; if ((vol_value_1 > vol_value_3 ) && ((vol_value_1 - vol_value_3) >= jingdu_horizontal)) { right_zhuan(1500); AD_Start(); } else if ((vol_value_1 < vol_value_3 ) && ((vol_value_3 - vol_value_1) >= jingdu_horizontal)) { fan_zhuan(1500); AD_Start(); } else { stop(); AD_Start(); flag_horizontal_stop = 1; flag_vertical_stop = 0; } } void motor_deal_vertical() //垂直電機(jī)控制 { extern unsigned int vol_value_2; extern unsigned int vol_value_4; if ((vol_value_2 > vol_value_4 ) && ((vol_value_2 - vol_value_4) >= jingdu_vertical)) { fan_zhuan_y(3000); AD_Start(); } else if ((vol_value_2 < vol_value_4 ) && ((vol_value_4 - vol_value_2) >= jingdu_vertical)) { right_zhuan_y(3000); AD_Start(); } else { stop_y(); AD_Start(); flag_vertical_stop = 1; flag_horizontal_stop = 0; } } Move.c #include <msp430x14x.h> typedef unsigned char uchar; typedef unsigned int uint; uchar F_Rotation[4]={0x10,0x20,0x40,0x80};//電機(jī)正轉(zhuǎn)表; uchar B_Rotation[4]={0x80,0x40,0x20,0x10};//電機(jī)反轉(zhuǎn)表 //電機(jī)控制模擬端口放在P2口,根據(jù)前一次的檢測(cè)光強(qiáng)x_before,以及 //當(dāng)前采集的系統(tǒng)光強(qiáng)x_now,確定電機(jī)的轉(zhuǎn)動(dòng)方向 void Delay(uint w)//延時(shí)程序 { while(--w); } //*************垂直電機(jī)控制部分程序****************** void right_zhuan_y(uint sudu) //電機(jī)正轉(zhuǎn)速度為sudu { uint w; for(w=0;w<4;w++) //4相 { P1OUT=~F_Rotation[w]; //正轉(zhuǎn)時(shí)序 Delay(sudu); //速度為sudu } } void fan_zhuan_y(uint sudu) //電機(jī)反轉(zhuǎn)速度為sudu { uint w; for(w=0;w<4;w++) //4相 { P1OUT=~B_Rotation[w]; //正轉(zhuǎn)時(shí)序 Delay(sudu); //速度為sudu } } void stop_y() { P1OUT=0XFF; Delay(10000); P1OUT=0XFF; Delay(10000); }
//*******水平電機(jī)控制部分開(kāi)始************************************ void right_zhuan(uint sudu) //電機(jī)正轉(zhuǎn)速度為sudu { uint w; for(w=0;w<4;w++) //4相 { P2OUT=~F_Rotation[w]; //正轉(zhuǎn)時(shí)序 Delay(sudu); //速度為sudu } } void fan_zhuan(uint sudu) //電機(jī)反轉(zhuǎn)速度為sudu { uint w; for(w=0;w<4;w++) //4相 { P2OUT=~B_Rotation[w]; //正轉(zhuǎn)時(shí)序 Delay(sudu); //速度為sudu } } void stop() { P2OUT=0XFF; Delay(10000); P2OUT=0XFF; Delay(10000); } cry1602.c #include <msp430x14x.h> #include "cry1602.h" typedef unsigned char uchar; typedef unsigned int uint; /**************宏定義***************/ #define DataDir P4DIR |