太陽の追尾装置の製作
サーボモータと光センサーで太陽の追尾装置を作ってみた。 太陽追尾というか、よーするに明るいところを追いかける装置です。

マイコンは、16F1827、センサーは、Cdsセルで、上下左右、4つのセンサーで、上下でより明るい方、左右でより明るい方を向くようにサーボモータをコントロール。 上下で120度、左右180度の可動範囲になっています。
センサーの隔壁は、最初、筒型のパトリオットミサイルのランチャーみたいなのを試してみたのですが、いまいち、うまく作動しなかったので、シンプルな、田の字型の隔壁スタイルにしたら、わりと良さげだったので、これを採用。

一応、基盤は汎用性をもたせて、サーボのコントロール部分をメイン基盤とし、センサー部分は、ドーターボードのようにして別基盤にしています。
ライトでグリグリやると、なんか面白いです。
サーボモータで光を追跡
回路図は、以下

ほんでもって、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