■ホビーロボット部品の製造・販売 
  モータコントローラ、センサ、音声、画像、無線モジュールなど、
■ホビーロボット制作記事のページ (各種マイコン、PCとの接続事例)
■特殊メイク、特殊材料の販売 ※特殊メイクのコーナーはこちらに移りました。
Top(お知らせ) 製品紹介 使い方とサンプルプログラム 通信販売 リンク ロボット掲示板 会社案内
 Easy Robotics for all enthusiastic people!!!  ---HOBBY ROBOT PARTS SHOP ASAKUSAGIKEN---   Since 2003...


入門用マイコンボードPIColo
 タイマ割り込みによるRCサーボの駆動

はじめに

 このページでは、ビギナー向けに、マイコンボードPIColoの開発方法を説明します。開発環境の用意や無償のCコンパイラのインストールについてはこちら、プロジェクト/プログラム作成についてはこちらを参照願います。タイマについてはこちらを参照願います。
 
 ※以下の情報は2010年7月現在のものです。ご注意ください。

 PIColoについてはこちらを参照願います。




パーツリスト

パーツ 型名 購入先
RCサーボ Ru−12 浅草ギ研及び販売店

※今回はできればオシロスコープがあった方がよい。



RCサーボについて

 
ホビーロボットによく使われるパーツにRCサーボがあります。これは、一定周期である幅のパルスを加え続けると、パルス幅によって回転角度を変える、というものです。ほとんどのRCサーボは1.5mSのパルス幅で中心位置をさします。パルス周期は10〜20mSのものが多いようです。

 


 浅草ギ研のサーボRu−12もRCサーボと同じパルスで動かす。コネクタはPIColoに直結可能なタイプ。

  Ru−12


割り込みについて


 
マイコンの機能の中でよく使われるものに「割り込み」というものがあります。英語でInterrupt(インタラプト)。これは、メインのプログラム動作中に「あるきっかけ」により強制的に動く機能又はプログラムをいいます。

 PIC16F1936にはいろいろな割り込み機能がありますが、タイマー割り込みを使うと、メインの動作とは関係なく、正確なタイミングを作ることができます。

 たとえば、RCサーボのパルスを作る場合、メインのプログラムでパルスを生成すると、動作状態によっては正確なパルスを生成できなくなります。また、メインのプログラムでパルスを生成するとそれだけで他にはなにもできなくなってしまいます。

 


 そこで、割り込みを使うと、メインでどのような作業をやっていたかには関係なく、正確なタイミングでパルスを作ることができます。

 




タイマー割り込み


 
前回、クロックをタイマーでカウントすることにより正確なタイミングを作りました。タイマーはある条件で割り込みを発生させることもできます。PIC16F1936の場合、割り込みが使えるタイマーとしてTimer1とTimer2,4,6があります。


【Timer1の割り込み】

 Timer1の割り込みはデータシートの16.7に書いてあります。

 

 Timer1はカウントするレジスタがTMR1HとTMR1Lの2つにわかれています。それぞれ8ビットなので両方あわせて16ビットのカウンタを構成しています。TMR1LがFFhになると、次のカウントではTMR1Hが1カウントアップしてTMR1Lは00hになります。割り込みが有効になっていると、TMR1HとTMR1Lの両方あわせてFFFFhになり、その後、もう一度カウントすると0000hになります。このとき割り込みが発生します。


【Timer2,4,6の割り込み 】

 Timer2,4,6の割り込みについてはデータシートの17.2に書いてあります。

 

 

 たとえばTimer4を使うとします。TMR4を0にして、割り込みを発生させたいカウント値をPR4にセットし、タイマを起動すると、TMR4とPR4の値が一致したときに割り込みが発生する、というものです。


 Timer1はプリスケーラが1/8までで16ビット、Timer2,4,6はプリスケーラが1/64で8ビットなので、その範囲でクロックを調整してタイミングを生成します。


パルス周期の設定(20mSの生成)

 前回は、32MHzクロックをTimer2を使って1:64に分周し、1mSを生成しました。このときはカウント値が125でした。

 FOSC(32MHz)/4/64=125,000カウント/秒 よって 125カウント/m秒

サーボパルスの周期は20mSなので同じようなクロックだと8ビットの最大値を軽く超えてしまいます。よって、16ビットタイマのTiemr1を周期用タイマとして使うことにします。クロックですが、パルス幅の方の問題(後で説明します)で、最大速度の32MHzではなく、16MHzにしました。

 Timer1を1:8に分周したとすると

 FOSC(16MHz)/4 /8=500,000カウント/秒 よって10,000/20mS

 となり、10,000カウントで20mSになります。

 Timer1の割り込みはロールオーバー割り込みなので、10,000カウントでロールオーバーする値をセットすることになります。16ビットの最大値は65,535なので、55,535をセットすると20mS後にロールオーバー割り込みが発生することになります。

 


パルス幅の設定(0.5〜2.5mSの生成)

 Timer1以外のタイマは8ビットタイマなので0〜255までしかカウントできません。この範囲で0.5〜2.5mSを生成する必要があります。

 32MHzの場合、Timer2,4,6に入るのはFOSC/4なので8MHz、1:64で125kHz、よって1mSで125カウントになります。これで2.5mSを表そうとすると、125x2.5=312.5となり、8ビットの最大値である255を超えてしまいます。感覚的にこの値の1/2だったら2.5mSもカウントできます。PIC16F1936の場合はプログラムでクロックを変えられますので、クロックの速度を半分にすれば、倍の長さをカウントできることになります。ということで今回はクロックを16MHzで使ってみます。

 前回、1mSを作るのに wait_ms( ) という関数を作りましたがこれにはTimer2を使いました。ということでここでは空いているTimer4を使うことにします。

 Timer2,4,6はPRxレジスタとの比較で割り込みを発生しましので、PR4にパルス幅相当の値を入れておけば、そのパルス幅を生成することができます。

 




割り込みプログラム

 Timer1の割り込みを使うにはTMR1IEを1にします。Timer4の割り込みを使うにはTMR4IEを1にします。さらに周辺機器割り込みを有効にする必要があるので、PEIEを1にします。さらに、割り込み全体を許可するのにGIEを1にします。

 割り込みが有効になっていると、

 static void interrupt isr(void)

 の関数が自動的に実行されます。この構文は(HITEC-Cで)決まっています。どの割り込みが発生してもこの関数が実行されるので、どの割り込みかをフラグで判断します。

 Timer1の割り込みが発生するとTMR1IFが1になります。Timer4の割り込みが発生するとTMR4IFが1になります。それぞれのフラグは自動的には0にもどらないので、割り込みプログラム内で0にクリアする必要があります。

 Timer1割り込みが発生したらパルスを立ち上げ、そのときにTimer4の割り込みをセットします。次にパルス幅のタイミングでTimer4割り込みが発生するのでパルスを0に戻せば、サーボパルスが生成できます。



プログラム

 ということで作ったプログラムが次のようになります。

 行6まではいままでのプログラムと同じです。又、行12〜22もいままでと同じウェイト関数です。

 行8のように、今回はRA0端子をサーボのパルス出力端子としました。

 行24〜37が割り込みプログラム。それ以降がメインとなります。

 Timer1は8ビットx2の16ビットタイマーになっていますので値のセットがやや面倒です。先の計算通り、55535の値をセットすると20mSになります。それが行28〜29の部分です。55535/256=216.93となるので上位バイトであるTMR1Hに216をセットしています。下位は55535−(216x256)=239となるのでTMR1Lを239にセットしています。

 

 とりあえず、テキスト版も用意しました。プロジェクトの作り方などは前回までを参照して下さい。

 servo.txt (右クリックで対象を保存)

 main関数では、グローバル変数であるsvoPosに数値を入れているだけで、パルス生成に関しては割り込みプログラムで処理しています。割り込みプログラム内でsvoPosをPR4に代入しているので、その値がサーボの位置になります。

 浅草ギ研のサーボ、Ru-12の場合は値94で大体センター位置、31で左90度、156で右90度に曲がります。接続は次のようになります。

 


 という感じで、わりと簡単にサーボを制御することができ、さらにメインでは別な作業も行うことができます。実験の結果、問題なくサーボが動作しました。このときの波形を観測すると次のようになっていました。横1マスが4mSなので20mS周期なのがわかります。

 


多サーボの駆動

 Timer1で20mSを生成しましたが、パルス幅の最大は2.5mSなので、17.5mS間はTimer1が遊んでいることになります。1つのサーボのパルスは最大2.5mSなので、2.5mS周期で次々に駆動するサーボを変えれば、同じようなタイマー構成で8個まで(20/8=2.5mS)駆動できそうです。

 


 ということで作ったプログラムが次のようになります。周期ですが、2.5mSだとギリギリになってしまうので、ちょっと余裕をもたせて3mS周期にしました。行38〜39の部分です。コメントでは2.5mSとなっていますがこの数値で3mSです。先ほどと同じプログラムなので、Timer1は20mSで10,000カウントになります。3mSだと10,000/20x3=1500となります。よってセットする値は65,535−1500=64,035になります。
  64035/256=250.13なのでTMR1Hは250にセット、64035−(250x256)=35なのでTMR1Lは35にセットとなります。

 行73ですが、3mS周期の終わりではHighになっている端子はありえないので、端子の判定をおこなわずに、PORTA全部をLowにしています。

 

 とりあえず、テキスト版も用意しました。プロジェクトの作り方などは前回までを参照して下さい。

 servo2.txt (右クリックで対象を保存)


 実行の結果、指定したサーボが指定した位置に動きました。波形を観測した結果は次のようになりました。これはサーボ1とサーボ2の波形を観測したところ。

 


さいごに

 RCサーボが駆動できると、ロボットの作成などができるようになります。ロボットを作るとなにかしらの入力装置が欲しくなります。次はセンサー入力について。


2010年7月20日

 
(C)Copylight 2003. 有限会社浅草ギ研 | 通信販売の法規(訪問販売法第8条)に基づく通信販売業者の表示