RCサーボは外部からの信号に応じて、一定の角度まで回転する小型モータです。大型のものはロボットの関節に、小型のものはラジコン飛行機の翼の角度制御などに利用されています。RCはラジコン、サーボは主人の命令に従う召使の意味のようです。
サーボモータの端子は3本で、内2本(赤、黒)は電源です。ここでは、5Vの電源をそのまま利用します。他の1本が制御信号で、一定間隔のパルス信号です。このパルス幅がサーボモータの角度を設定します。パルス幅1.0〜2.0mSがモータの角度-70〜70に対応します。この値は、サーモモータにより若干変化します。
角度に対応する幅のパルスを 20mS 周期で送ります。
寸法: 22.5x11.5x27 (mm3) トルク:1.6 kg*cm(4.8V) 速度: 0.12s/60度(4.8V) ギア:プラスチック 重量: 9g
電源電圧:4.8V 動作可能範囲:±70°程度 制御パルスHigh電圧:3-5V(矩形波) パルス幅:0.8-2.4ms 程度 信号周期:15〜20ms 端子列機能:黒・赤・白=接地
参考のため、標準型のサイズのRCサーボの例を紹介します。少し遅くなりますが、トルクは4倍以上です。
トルク 4.8V時:7.2kg-cm
スピード 4.8V時:0.33sec/60°
ギア プラスチック
方式 アナログ
サイズ 39.5×20.0×39.6mm
重量 46g
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128)タイマー1の場合も同様ですが、定数の名前が異なります。T1のプリスケーラは3ビットなので、T1_DIV_BY_4、T1_DIV_BY_2、T1_DIV_BY_1、のみになります。
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8)タイマーの値は、次の値で設定できます。
SET_TIMER0(1バイト値)この値以後、計数信号からのパルスで値が増加します。現在のタイマーの値は、
SET_TIMER1(2バイト値)
val = get_timer0();で取得できます。タイマー0は1バイト、タイマー1は2バイトの値になります。タイマーの値は計数信号により読み取るごとに値が増加します。
val = get_timer1();
enable_interrupts(INT_TIMER1); //タイマ1割込み許可以下のように定義された割り込み関数を実行します。
enable_interrupts(GLOBAL);//グローバル割込み許可
#INT_TIMER1 //タイマー割り込み関数の宣言割り込みについては、こちらを参照してください。ここでは、タイマー1を20mS間隔でオーバーフローさせて割り込みを発生させ、割り込み処理で、RCサーボの回転角に対応した幅のパルスを生成します。 この割り込み処理により、プログラムで20mSを計数する必要がなくなります。
timer1_isr(){
割り込み処理
}
可変抵抗は、上側の黄色の丸い部分を回転すると、抵抗値が変化する部品です。端子(下)側から見たとき、左右の両端子が固定抵抗、上側の端子と片側の端子の抵抗が回転とともに変化します。写真の端子は側面から見ています。左の上下の端子が固定で、右の端子が可変です。テスタで抵抗値を測定し動作を確認してください。
押ボタンスイッチは、上のボタンを押すと側面から出ている二つの端子が短絡します。端子は両側から出ていますが、2回路ではなく、同時にオン/オフします。
ここでは、可変抵抗器を利用し、この抵抗値をAD変換して読み取り、この値でRCサーボを回転させます。RCサーボへの制御信号は、ポートAのA2を利用します。RCサーボのコネクタは白が制御線で赤が電源、黒がグランドです。コネクタはピンへダでパッチボードに接続します。ピンへダの長いほうをコネクタに差込、短いほうにパッチボードの線を半田付けします。
シリアル通信を マイクロローダとハイパーターミナルで共有するため、CLR端子への接続に押しボタンスイッチを付加します。マイクロローダでプログラムを送るとき、このスイッチをオンにする必要があります。
回路にはありませんが、B1にLEDを接続するとランプが点滅します。動作確認に利用してください。
AD変換をした値を表示するため #use RS232() でRS232C の利用を宣言します。BAUD= は通信速度 xmit=
は送信信号の端子、rcv= は受信信号の端子です。#INT_TIMER1 はタイマー1割り込み処理の宣言です。タイマー1がオーバーフローすると、続く関数が実行されます。ここで、可変抵抗器の値を1/3した値の時間だけ、RCサーボ(PIN_A2)にパルスを送ります。
main()では、AD変換と、タイマー0、1、の設定、ターマー1の割り込み許可、を行います。繰り返しの中で、AD変換と、変換値の表示を行います。printf()
のLu は2バイト符号なし整数データの表示を指定します。
//Servo Test //パルス周期 15-20mS //パルス幅 0.8-2.4mS #include <16F873A.h> #fuses HS,NOWDT,NOLVP,NOPROTECT #use delay(clock = 20000000) #use RS232(BAUD=9600,xmit=PIN_C6,rcv=PIN_C7) long vd,loop; #INT_TIMER1 //タイマ1割込みの指定 timer1_isr(){ //タイマ1割込み処理関数 set_timer1(53000); set_timer0(0); output_high(PIN_A2); while (get_timer0() < vd/3) {}; output_low(PIN_A2); } void main() { setup_adc_ports(AN0); setup_adc(ADC_clock_div_32); set_adc_channel(0); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);//タイマ0のモード設定 setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);//タイマ1のモード設定 set_timer1(2500); set_timer0(100); enable_interrupts(INT_TIMER1); //タイマ1割込み許可 enable_interrupts(GLOBAL);//グローバル割込み許可 loop=0; while(1){//割込み待ち output_low(PIN_B1); vd=read_adc(); delay_ms(20); output_high(PIN_B1); delay_ms(30); loop++; if (loop>20){ printf("%3Lu\r\n",vd); loop=0; } } }
PC側のRS232Cをマイクロローダとハイパーターミナルで共有するため、注意が必要です。マイクロローダでプログラムを送るとき、PICのリセット(CLR)回路にあるスイッチをオンにします。
printf() の値を表示するには、ハイパーターミナルで接続しますが、再度マイクロローダを利用する場合、ハイパーターミナルの接続を一時的に切断する必要があります。
サーボモータを無理に回すとプラスチックのギア(歯車)が破損します。やさしく扱ってください。
//Servo Test //パルス周期 15-20mS //パルス幅 0.8-2.4mS #include <16F873A.h> #fuses HS,NOWDT,NOLVP,NOPROTECT #use delay(clock = 20000000) long vd; #INT_TIMER1 //タイマ1割込みの指定 timer1_isr(){ //タイマ1割込み処理関数 set_timer1(53036); set_timer0(0); output_high(PIN_A2); while (get_timer0() < vd) {}; output_low(PIN_A2); } void main() { setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);//タイマ0のモード設定 setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);//タイマ1のモード設定 set_timer1(53000); enable_interrupts(INT_TIMER1); //タイマ1割込み許可 enable_interrupts(GLOBAL);//グローバル割込み許可 while(1){ for(vd=30;vd<=80;vd +=5){//正回転 output_high(PIN_B2); //動作確認用 delay_ms(50); output_low(PIN_B2); delay_ms(100); } for(vd=80;vd>=30;vd-=5){//逆回転 output_high(PIN_B2); //動作確認用 delay_ms(100); output_low(PIN_B2); delay_ms(200); } delay_ms(500);//休止 } }