352.ギヤードモータのサーボ化4ch対応(PIC16F873)


2002/02/26 【ソフトウエア編TOPに戻る】

前回、351.ギヤードモータのサーボ化その1で、PIC16F873を利用したサーボコントローラを作りました。前回のバージョンではモータを1個だけしか制御できませんでしたが、今回ご紹介するプログラムはモータを4個まで制御できるようにしたものです。

基本的な制御の考え方は、前回と全く一緒です。つまり、単純な比例制御を、ただ多チャンネル化に対応させているだけです。しかし、プログラミング上の手法や具体的な処理方法に若干の手直しを行なっているため、似て非なるものになっています。今回も細かなプログラム内容の説明は省略致しますが、その概要についてご紹介させて頂きます。細かな動作内容が知りたい方は、ソースプログラムのコメント欄を追いかけて頂ければ分かると思います。ただし、相当根気が要る作業になるかもしれませんが...(^^;


352−1.動作の概略

今回の動作も、前回と同様に20mS周期で送られてくる0.28mS〜1.34mSのパルス幅を持つPWM信号を受け取ることを前提としています。ただし、4CH分のPWM信号を同時に受け取り、4CH分のモータドライブパルスを同時に出力します。全体としては以下のような感じの動作波形となります。

動作概要図

PWM信号を4CH分同時に受けますが、全てのPWMパルスの立ち上がりのタイミングに同期が取れていることが条件となります。これはPIC内部のひとつのタイマーTMR1で全てのPWMのパルス幅を計測するためです。PWM信号が同期されていないでバラバラのタイミングで入力されると、正確なパルス幅の計測が出来なくなりますので要注意です。

同様に、出力されるモータードライブパルスも、ひとつのタイマーTMR1で時間を計測しながらパルス幅を決定しているため、やはり全てのパルス出力が同時にスタートします。これは接続されている全てのモータに同時に電源を供給することを意味しますので、電源回路に負担を掛けることになります。つまりラッシュの多い動作となり、電流容量の少ない電源ではドライブしきれなくなるかも知れないという弱点を持ちます。それぞれのモータドライブパルスの出力タイミングをずらすことで改善できるはずですが、それは今後の課題としておきます。

【先頭に戻る】

 

■以下の図は、PWM信号が入力されてから2mSまでの間に行なっている処理を拡大したものです。

初めの2mS

①TMR1の初期化と起動(実行時間1.8μS)

PWM信号の立ち上がりを検出すると、先ず初めにTMR1の初期化と起動を行ないます。TMR1は2mS後にカウンタ値がFFFFHになるように初期値をセットし、割り込みを許可した上でカウントを開始させます。2mSにセットするのは、入力されるPWMパルス幅が1.34mSをオーバーして2mS経っても立ち下がらない場合に、そのチャンネルのパルス入力を無効にするための上限とするためです。

なお、①の処理をはじめるきっかけとなるパルス入力の立ち上がり検出は、チャンネル1のPWM入力で行なっています。つまり、PWMのチャンネル1に信号が入力されない限り、2〜4チャンネルも動作しないことになりますので、注意が必要です。

 

②〜⑤ポテンショメータのA/D変換(実行時間各約35.6μS)

タイマーTMR1を起動させたら、すぐに各チャンネルのポテンショメータをA/D変換します。A/D変換はチャンネル1から4まで順番に行い、それぞれPDATA1〜4と宣言したメモリ空間に8BITで格納します。4チャンネル分のA/D変換は、0.28mSまでに終了させなければなりません。これは、規定のPWM信号の立下りを検出するための処理に移行しなけらばならないためです。今のところ、計算上では0.14mSまでにここまでの処理を終了しているはずですので、問題ありません。

なお、規定の1.34mSをオーバーして2mS以下で立ち下がるようなパルスが入力された場合のチェック処理は、今回入っていません。入れる必要性は感じていますが、今回は手抜きです。(^^; すみません。

 

⑥パルス立下り検出待機期間

全てのポテンショメータのA/D変換を終了すると、PWM信号のパルスの立下りを検出するためのポーリング処理に入ります。ポーリング処理とは、周期的に入力を監視して、状態の変化を検出したら次の処理を行なうというものです。どれくらいの周期で監視しているかというと最短で2μS周期で、最長で約12μS周期となります。なにも変化が検知されない時に最短周期となり、4チャンネル分全てが同時に変化した場合に最長周期となります。

入力パルスの立下りを検出するための期間はタイマーTMR1が2mSを経過するまでループで続けられます。ループ処理はTMR1がFFFFHに達して割り込みが発生することによって終了します。

 

⑦〜⑩PWMパルス立下り検出(実行時間各2.4μS)

⑥の期間中に入力パルスが立ち下がると、状態の変化を検出して、その時のタイマーTMR1のカウント値を読み込みます。TMR1のカウント値は上位8ビットと下位8ビットがそれぞれTMR1HとTMR1Lのレジスタに記録されていますが、このデータをそれぞれ検出したチャンネルに応じて上位をCDATA1H〜CDATA4Hと下位をCDATA1L〜CDATA4Lに宣言したメモリー空間に格納します。このデータが、モータを停止させるための目標位置のデータとなります。

パルスの立下りが検知されて、データが正常に取り込めたことを示すために、CAPFLGという1バイトのメモリー空間を用意しています。1チャンネル目のパルス立下りが検出されたら0ビット目に1を立てる。という具合に、検出結果に応じて4ビット分に1を立てる処理を行ないます。このビットをフラグ(旗)と呼び、処理の状態を示すための指標としています。この後もCAPFLGの状態を見て、正常にデータが取り込めたチャンネルだけを処理の対象にする、などといったことをしています。

⑦〜⑩の各立下り検出の順番は、1〜4チャンネルの入力パルスの幅が短い順に実行されます。なので、場合によって実行される順番やタイミングが異なります。上図はひとつの事例として捉えて下さい。

複数のチャンネルが同時に立ち下がった場合はどうなるのでしょう。その場合は若番から順に処理されて行きますので、1チャンネル分待たされる度に、2.4μSずつの誤差を生じますが、この誤差は動作に影響を与えるものではありません。

全てのチャンネルの入力パルスで立下りが検出されても、2mSが経過するまではループを続けます。

【先頭に戻る】

 

■下の図は、2mSから4mSの間に行なっている処理の部分を拡大したものです。

⑪TMR1割り込み処理(実行時間5.4μS)

PWM信号の立ち上がりを検出してから2.0mSが経過すると、TMR1のカウント値がFFFFHに達して割り込みが発生します。プログラム処理全体の中では、TMR1による割り込みには2種類あります。ひとつはPWM信号のパルス立下りを検出する期間の終了を示す割り込みで(今回の割り込み)、もうひとつはこの後にご紹介するモータドライブパルスを発生させる期間の終了を示す割り込みです。両方とも同じTMR1の割り込みなので、どちらの割り込みなのかを判断するために、INTFLGというフラグを用意しています。

パルス立下り検出期間ではINTFLGの値を0にしておき、モータドライブパルスの出力期間では1にしておきます。こうすることによって、割り込み処理内部で、場合に応じた処理に分岐させることが出来ます。

今回のパルス立下り検出期間の終了を示す割り込み処理では、割り込みステータスの初期化のほかに、検出したパルス幅データの簡単なチェックを行なっています。ここでのチェックでは、規定の0.28mSに満たないチャンネルデータを、無効にしています。つまり対応するCAPFLGのビットを0にクリアしています。

 

⑫〜⑮取り込んだパルス幅データの8ビット化(実行時間各3.2μS)

ここでは、パルス幅データとして取り込んだ有効10ビットのデータを、A/D変換したポテンショメータからのデータと単純比較が可能なように8ビットのデータに変換しています。プログラム的にはCDATA1H〜4Hの下位2ビット分と、CDATA1L〜4Lの上位6ビット分を合成してひとつの8ビットデータにし、CDATA1L〜4Lに格納しなおしています。

 

⑯〜⑲各チャンネルのモータドライブパラメータの決定処理(実行時間各78μS)

ここでは、A/D変換で得たポテンショメータの位置データPDATA1〜4と、PWMのパルス幅を計測して8ビット化して得た目標位置データCDATA1L〜4Lを元にして、モータの回転方向NRDATA1〜4と、モータに与えるドライブパルスの幅PWITDH1H〜4Hを決定します。ドライブパルスの幅を決定するためのプロセスについては、351.ギヤードモータのサーボ化その1を参照して下さい。なお、現在位置データPDATA1〜4と目標位置データCDATA1L〜4Lの差を計算してSDATA1〜4に格納し、その偏差の量に基づいてパラメータを決定しています。

 

20〜23 各チャンネルのモータドライブパルスを立ち上げる(実行時間各2μS)

ひとつのギヤードモータを制御するために2BITを使います。モータドライバICとしてL6203のインターフェイスに合わせると、0,1または1,0で正転/逆転を切り替え、0,0もしくは1,1でブレーキモードになります。正転/逆転はNRDATA1〜4の値が0(正転)か1(逆転)かで決定します。

 

24 TMR1のカウント開始と、モータドライブパルスの立ち下げ処理

モータドライブパルスを立ち上げたら、すぐにTMR1のカウントを開始します。このカウントは、モータドライブパルスのパルス幅を所定の時間にするための基準タイマーとして用います。

今回、デューティー比の最大を0.75としているため、20mS x 0.75 = 15mS がモータドライブパルスの最長幅となります。カウント開始後から15mS後にTMR1がFFFFHになるための初期値は、以下の計算で求められます。(ただしPICクロック20MHz1/8プリスケーラ設定で動作させた場合)

■15mS期間のカウント数 15mS/1.6μS = 9375 = 249FH

■TMR1の初期値 FFFFH - 249FH = DB60H

つまり、TMR1の初期値をTMR1H = DBH , TMR1L = 60H と設定すれば、カウント開始から15mS後にFFFFHに達して、自動的に割り込み処理に移ることができるようになります。

ただし、今回はコンペアマッチ機能を利用せず、ポーリングでTMR1のカウント値と予め決定したパルス幅データPWIDTH1〜4とを演算で比較して、TMR1 > PWIDTH という関係を条件としてパルス出力を終了させます。このとき、両データを16ビット幅で比較させようとすると処理が面倒なので、上位8ビットだけを比較してパルス終了処理をしています。

なので、TMR1の初期値は繰り上げてTMR1H = DAH , TMR1L = 00H としています。

同様にして、目標位置までの各レベルに応じた基準パルス幅データWIDTH0H〜3Hも、上位8ビットだけの値にし、下位8ビットは00Hにしてしまっています。

TMR1がFFFFHに達すると割り込み処理に移って、強制的に全てのモータドライバパルスを終了させます。そして、プログラムの一番初めの処理にジャンプし、再びPWM入力パルスの立ち上がりを待ちます。

以上の繰り返しを永遠に続けます。

【先頭に戻る】


352−2.4CH対応版プログラム dcservo2.asm

というわけで、ソースプログラムをご紹介します。ただし、長いのでプログラムの掲載と、プログラムの細かな説明は省略させて頂きます。ここをクリックするとダウンロードできますdcservo2.asm

上記の概要説明と、ソースプログラム中のコメントを参考にして追いかけて頂くと、多分わかってもらえるかと思います。ちょっと大変ですが...。というか、だれも追いかけようとはしないと思いますが...。

なお、4チャンネルの制御用PWM信号は、srvtest5.cのプログラムを使ってAKI-H8から出力させています。ここをクリックするとダウンロードできますので、良ければ参考にして下さい。(勝手に首振りするプログラムです。)

【先頭に戻る】


352−3.回路図

実験回路は、PIC実験用ボードに、L6203を実装したテスト基板を接続して用意しています。また、ポテンショメータの接続用に簡易型実験用I/Oボードを使い、PWMパルス発生用にH8小型マザーボードを使っています。回路図は以下の通りになります。なお、実験風景は、ほとんど前回の351.ギヤードモータのサーボ化その1と一緒です。

実験回路図

【先頭に戻る】


回路図ではL6203を4個接続した図面にしてありますが、現在のところL6203用の実験基板は1CH分しか作っていないため、検証は1CHずつ別々に行ないました。なので、正直なところ、同時に4個のモータを動かしていないため、どんな障害が発生するのか?といったところまでは見ていません...。(無責任ですみません)

4CH分がお互いに干渉しないで独立に動作することは、PICのRBポートにLEDを接続して、その点灯状態で検証しています。

ちなみに、1CHだけポテンショメータを接続して2〜4CHに接続しないで動作させると、2〜4CHのモータドライブパルスの出力は、1CHのポテンショメータのデータに友連れして動作するようです。ソースプログラム上は独立を保つはずなのですが、A/D入力に設定しているにもかかわらず、オープン状態で動作させるということ自体に問題があるようです。なので、使用しないCHがある場合には、アナログ入力端子をGNDに落しておく等の対策が必要だと思います。

 

【ソフトウエア編TOPに戻る】


【表紙に戻る】