PIC16F1827でサーボモータ2軸を制御

PIC16F1827を使ってサーボモーター2個をコントロールしてみた。
f:id:manpukukoji:20170924104300j:plain
16F1827は、タイマー1の割り込みでコンペアモードが4つ使えるみたいなので、4つのサーボモーターがコントロールできそう・・・。
とりあえず、ADコンバータ使って、半固定抵抗で電圧をぐりぐりやって2軸を動かしてみた。
f:id:manpukukoji:20170927085603p:plain
使ったサーボモータは、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