PIC16F1827を使ってサーボモーター2個をコントロールしてみた。
16F1827は、タイマー1の割り込みでコンペアモードが4つ使えるみたいなので、4つのサーボモーターがコントロールできそう・・・。
とりあえず、ADコンバータ使って、半固定抵抗で電圧をぐりぐりやって2軸を動かしてみた。
使ったサーボモータは、GWSのMINI STD というのと、TowerProのSG-5010 ですが、使うサーボによって、プログラムの値を変更しないと、ならないと思います。
このまま使って、高価なサーボモータ壊しちゃったりしないようにご注意ください。
あくまでも、自己責任で・・・。よろしく!
ちなみに、僕は、いまだに古いMPLAB IDE(v8.6)でHiTech-C使っているので、最新のIDEとは、ちょっと違うと思うけど、include のヘッダとか、Configrationの表記以外は、だいたい、似たようなものではないかと思います。
プログラムは、以下
/* Project Twin servo control PIC16F1827 with two servo moter and 2VR AD control */ /*PIN of 16F1827 asign RA0 : VR1 RB0 : Servo1 Control RA1 : VR2 RB1 : Servo2 Control RA2 : RB2 : RA3 : RB3 : RA4 : RB4 : RA5 : MCLR RB5 : 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){ unsigned long m1,m2,vdata; //m1 for UpDown, m2 for RightLeft unsigned int f1,f2; //flag for PWM increase or decrease 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 //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; // 全割り込み有効 f1=1; f2=1; while(1) { //ADC //ADC1 ADCON0=0b00000011; __delay_ms(1); GO_nDONE=1; while(GO_nDONE); vdata=ADRESH; vdata<<=8; vdata|=ADRESL; m1=(vdata*2400)/1024+1800; if(m1>=4200){m1=4200;} if(m1<=1800){m1=1800;} //ADC2 ADCON0=0b00000111; __delay_ms(1); GO_nDONE=1; while(GO_nDONE); vdata=ADRESH; vdata<<=8; vdata|=ADRESL; m2=(vdata*3800)/1024+1000; if(m2>=4800){m2=4800;} if(m2<=1000){m2=1000;} next1=INT_START+m1; next2=INT_START+m2; delay(3); } //End of While } //End of main