太陽の追尾装置の製作

サーボモータと光センサーで太陽の追尾装置を作ってみた。 太陽追尾というか、よーするに明るいところを追いかける装置です。 
f:id:manpukukoji:20171004121609j:plain
マイコンは、16F1827、センサーは、Cdsセルで、上下左右、4つのセンサーで、上下でより明るい方、左右でより明るい方を向くようにサーボモータをコントロール。 上下で120度、左右180度の可動範囲になっています。
センサーの隔壁は、最初、筒型のパトリオットミサイルのランチャーみたいなのを試してみたのですが、いまいち、うまく作動しなかったので、シンプルな、田の字型の隔壁スタイルにしたら、わりと良さげだったので、これを採用。
f:id:manpukukoji:20171004121640j:plain
一応、基盤は汎用性をもたせて、サーボのコントロール部分をメイン基盤とし、センサー部分は、ドーターボードのようにして別基盤にしています。
ライトでグリグリやると、なんか面白いです。

サーボモータで光を追跡

回路図は、以下
f:id:manpukukoji:20171004112237p:plain

ほんでもって、PICのプログラムは、以下です。

/*	Project Twin servo control
	PIC16F1827 with two servo moter and 4 Cds cell sensor
	trace the britest spot (Sun tracker)
*/

/*PIN of 16F1827 asign
	RA0 : Cds1 (Upper)		RB0 : Servo PWM Vertical
	RA1 : Cds2 (Lower)		RB1 : Servo PWM Holizontal
	RA2 : Cds3 (Right)		RB2 : Rx
	RA3 : Cds4 (Left)		RB3 : 
	RA4 :  				RB4 : 
	RA5 : MCLR			RB5 : Tx
	RA6 : 				RB6 : 
	RA7 : 				RB7 : 
*/
#include <pic.h>

#define _XTAL_FREQ  8000000    // delay用(クロック8MHzで動作時)
#define INT_START 25536		//20msの割り込みの初期値(65536-25536=40000)

__CONFIG( WRT_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTOSC & CP_OFF & CPD_OFF) ;
__CONFIG(PLLEN_OFF & STVREN_ON & BORV_25 & LVP_OFF);

unsigned short next1,next2;	//next1 for UpDown, next2 for RightLeft


void delay(unsigned char d){
	int i;
	for(i=0;i<d;i++) __delay_ms(10);
}

void interrupt pwm( void )
{
    // タイマ1割り込み処理
    if( TMR1IF )
    {
        RB0 = 1;
        RB1 = 1;

        CCPR1H = (next1>>8);	//next1 for UpDown, next2 for RightLeft
		CCPR1L = (0x00ff & next1);
        CCPR2H = (next2>>8);
		CCPR2L = (0x00ff & next2);
        TMR1 = INT_START;   // 20msec毎に割り込み
        TMR1IF = 0; // タイマ割り込みフラグをクリア
    }

    // CCP1割り込み処理
    if( CCP1IF )
    {
        RB0 = 0;
        CCP1IF = 0; // コンペアマッチ割り込みフラグをクリア
    }

    // CCP2割り込み処理
    if( CCP2IF )
    {
        RB1 = 0;
        CCP2IF = 0; // コンペアマッチ割り込みフラグをクリア
    }
}



void main(void){

     int m1,m2,vdata;		//m1 for UpDown, m2 for RightLeft
	 int v1,v2,h1,h2;	//ADC value
	 
     m1=3000;		//1.5mSec
     m2=3000;

	vdata=0;
	
     OSCCON     = 0b01110010;    // 内部クロックは8MHzとする
     OPTION_REG = 0b00000000;
//割り込み設定
	 CCP1CON=0b00001010;	//compair mode
	 CCP2CON=0b00001010;
     T1CON=0b00000100;		//1:1 PreScaler
//     CCP1M=0b1010;		//CCP1 Compair Interrupt
//     CCP2M=0b1010;		//CCP2 Compair Interrupt

//pin設定
     TRISA  = 0b00101111;    // 1で入力 0で出力 RA0-RA3:Input RA6-RA7:Outputに設定(RA5は入力専用)
     TRISB  = 0b00000000;    // RB1-RB7全てを出力に設定 RB0,RB1をサーボ制御に使用
     ANSELA = 0b00001111;    //RA0-RA3 をADCにセット
     ANSELB = 0b00000000;    //汎用ポート RB3(AN9)をADCにセット
     PORTA  = 0b00000000 ;   // RA出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ;   // RB出力ピンの初期化(全てLOWにする)

//ADC設定
	 ADCON0 = 0b00100100;
	 ADCON1 = 0b11000000;	//右寄せ, Fosc/8

//割り込み初期値
    TMR1IE = 1; // タイマ1割り込み有効
    CCP1IE = 1; // コンペアマッチ割り込み有効
    CCP2IE = 1; // コンペアマッチ割り込み有効

    TMR1 = INT_START;
    next1 = INT_START + 3000;  // 1.5msec
    next2 = INT_START + 3000;  // 1.5msec

    TMR1ON = 1; // タイマ1 開始

    TMR1IF = 0;
    CCP1IF = 0;
    CCP2IF = 0;
    PEIE = 1;
    GIE  = 1;    // 全割り込み有効


while(1) {

//ADC 

//ADC0
	ADCON0=0b00000011;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	v1=vdata;
	
//ADC1
	ADCON0=0b00000111;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	v2=vdata;


//ADC2
	ADCON0=0b00001011;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	h1=vdata;

//ADC3
	ADCON0=0b00001111;
	__delay_us(50);
	GO_nDONE=1;
	while(GO_nDONE);
	vdata=ADRESH;
	vdata<<=8;
	vdata|=ADRESL;
	h2=vdata;

//Compair brightness
//Vertical direction
	if(v1>v2){
		if((v1-v2)>3){
			m1=m1+(v1-v2);
			if(m1>=4000){m1=4000;}
		}
	}
	else if(v1<v2){
		if((v2-v1)>3){
			m1=m1-(v2-v1);
			if(m1<=1900){m1=1900;}
		}
	}

	next1=INT_START+m1;
	
//Holizontal direction
	if(h1>h2){
		if((h1-h2)>3){
			m2=m2+(h1-h2);
			if(m2>=4800){m2=4800;}
		}
	}
	else if(h1<h2){
		if((h2-h1)>3){
			m2=m2-(h2-h1);
			if(m2<=1000){m2=1000;}
		}
	}
	
	next2=INT_START+m2;
	

	delay(10);

}	//End of While
}	//End of main