如上所述,太阳能自动跟踪系统的软件部分包含多个模块,各模块的启动和停止由单片机控制。在程序设计时,将这些模块的入口都安排在主程序中,主程序循环检测通过串口接收的命令,通过对命令解释,然后根据命令转入相应的模块。程序流程图如图3.1。
系统软件的设计主要是通过C语言编程实现单片机对步进电机控制以及系统状态的显示。
系统通电后,首先对LCD,IO端口初始化,然后开中断,此时系统开始工作,检测当前太阳位置,直到接收板对准太阳,实现对太阳能全方位跟踪。系统默认时间是00:00,用户可以根据当地时间调整系统时间。当阴天时,太阳跟踪系统检测不到太阳,为了实现太阳一出来就能自动跟踪太阳,系统时间每到12:00或18:00(也是太阳落山),系统自动控制接收板与大地垂直,这样不管太阳在那个位置,接收板都能检测到太阳。
图中,启动后首先进行的初始化包括:对单片机本身的中断和LCD液晶显示器等的初始化。
系统采用光敏电阻光强比较法,设计出一种全新的光电转换装置,很好的实现了光电转换。它能够利用光敏电阻比较法实现对太阳水平、垂直方向的全方位跟踪,晚上便自动复位。当太阳的水平或垂直位置发生偏移时,D1、D2或D3、D4(另一组控制电路)四个光电管中必有一个受阳光照射,这样就可确认太阳运动的方向了。控制电路有两组,电路图中是其中的一组,另一组电路与此相同。光电管是直接与控制电路连接的,当太阳能板正对太阳时,D1、D2都是高电阻,A、B两点电压相等。运放输出的电压相同,单片机收到的信号差为零,所以单片机不控制电动机转动。若阳光发生倾斜,使Dl被阳光射中呈低电阻,则A点电位比B点高,信号经过放大和转换,则单片机使得电机得电转动并拖动太阳能板转动,使太阳能板重新对准太阳。当D1、D2重新转为高电阻时,电机停转。若阳光偏转时使D2被阳光射中则电机反转。不论哪种情况,电机运动的方向和太阳运动的方向总是一致的.从而达到了跟踪的目的。当光敏电阻对准阳光时,采用微凋即可使得A、B两点的电位相等,以提高系统的准确度。
该程序中参数 vol_value_2 是硅光片上面的光敏电阻经过A/D转换所得的电压值,参数vol_value_4是硅光片下面的光敏电阻经过A/D转换所得的电压值,上段程序是将上下两个光敏电阻吸收的阳光通过A/D转换变为电压后进行比较,从而控制电机的正反转。
3.3 太阳能板二维角度调整模块
3.3.1 电机水平转动控制部分
当通过AD转换后,单片机得到左右两边的输出电压,若左右两边的输出电压不相等时,水平电机控制部分别开始工作,若左边电压值比右边电压值高且左边电压与右边电压差的绝对值超过一定的范围时,电机开始向右转,反之,若右面电压比左面电压大,且左右两面电压差的绝对值超过一定范围后,电机向左转,否则,电机不转动。当水平控制结束后,水平转动停止,垂直转动开始。
在这个模块中,超过一定是绝对值是为了避免因为很小的误差或者一些没有必要转动的情况下电机发生转动,提高了电机的利用效率。
3.3.2 程序设计思想或说明
通过AD转换得到光敏电阻的电压值,将左右或上下的电压值进行比较,根据电压值的不同进行电机的调整。以电机的水平调整为例,若左面电压值大于右面电压值,则表示左面接收的太阳光必右面的多,则电机通过步进电机向右转,在转动的同时,左右两面的电压也一直还在比较,直到左右两边电压相等或两面电压的绝对值在一定的范围内,电机水平转动停止。
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(); //水平电机控制 void motor_deal_vertical(); //垂直电机控制 void main(void) { WDTCTL = WDTPW + WDTHOLD; P6DIR |= BIT2;P6OUT |= BIT2; //关闭电平转换 P2DIR = 0xff; P2OUT = 0xf0; P1DIR = 0xff; P1OUT = 0xf0; LcdReset(); //复位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() //水平电机控制 { 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() //垂直电机控制 { 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};//电机正转表; uchar B_Rotation[4]={0x80,0x40,0x20,0x10};//电机反转表 //电机控制模拟端口放在P2口,根据前一次的检测光强x_before,以及 //当前采集的系统光强x_now,确定电机的转动方向 void Delay(uint w)//延时程序 { while(--w); } //*************垂直电机控制部分程序****************** void right_zhuan_y(uint sudu) //电机正转速度为sudu { uint w; for(w=0;w<4;w++) //4相 { P1OUT=~F_Rotation[w]; //正转时序 Delay(sudu); //速度为sudu } } void fan_zhuan_y(uint sudu) //电机反转速度为sudu { uint w; for(w=0;w<4;w++) //4相 { P1OUT=~B_Rotation[w]; //正转时序 Delay(sudu); //速度为sudu } } void stop_y() { P1OUT=0XFF; Delay(10000); P1OUT=0XFF; Delay(10000); }
//*******水平电机控制部分开始************************************ void right_zhuan(uint sudu) //电机正转速度为sudu { uint w; for(w=0;w<4;w++) //4相 { P2OUT=~F_Rotation[w]; //正转时序 Delay(sudu); //速度为sudu } } void fan_zhuan(uint sudu) //电机反转速度为sudu { uint w; for(w=0;w<4;w++) //4相 { P2OUT=~B_Rotation[w]; //正转时序 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 |