基礎実験4.8までで、簡単なリアルタイムスケジューラを導入して効率よくラジコンサーボを制御できるようになりました。これからは、シリアル通信を使ってPICに対して連続的にサーボを制御するための命令を送るための実験に入ります。 いきなり全部やるのは難しいので、以下の順番で通信と制御の実験をしていきます。
先にお断りしておきますが、私はPICを扱うのも、VBでプログラムを書くのも初めてです。特にVBについては、質問されても答えられないと思いますので、ご容赦ください。
今回の基礎実験では、PC側のプログラムからラジコンサーボを制御することを考えています。ですから、まずはラジコンサーボの出力角度である-60から+60までの数字をPCからPICに送れるようにする必要があります。 そこで、先にVBでMSCommを使って通信するプログラムを作り、データとして-60から+60 までの数字をPICに送信するプログラムを作成します。 VBプログラムができたら、PIC側では受信データを解析してVBに送り返すプログラムを作成します。
パケット(packet)とは、小包とか束という意味で、通信の世界では、やり取りするデータの1セットをパケットといいます。通信データのフォーマットと言い換えてもいいでしょう。通信するデータがパケット形式になっていると、通信データがずれたりした場合に、正常なデータがどこから始まってどこで終わるのかを見つけやすくなります。今回の実験では、人間の目でどんなデータがやり取りされているのかを確認しやすくするために、データをASCIIデータでやり取りすることにしました。 サンプルプログラムで使用しているパケットのフォーマットは下表のとおりです。
| 意味 | ASCII文字 | ASCIIコード |
| 先頭コード | @ | 0x40 |
| 符号 | +、- | 0x2b、0x2d |
| 十の位 | 0〜9 | 0x30〜0x39 |
| 一の位 | 0〜9 | 0x30〜0x39 |
| 終了コード | [LF] | 0x0a |
本来ならば、先頭コードには[STX]、終了コードには[ETX]が入るべきなのかもしれませんが、プログラムのデバッグをするのに出力結果をhyper terminal 等で確認する際に、人間がぱっと見て判るものの方が良いだろうと思い、先頭コードを@にしてみました。(終了コードは、ただなんとなく、気分で決めました。)
VBとPICで通信できることが確認できたら、次はVBプログラムの操作でラジコンサーボを動かしてみましょう。VBのプログラムは、先ほどラジコンサーボの制御角度を送信するように作成したので、そのままで良いでしょう。 PIC側は、受信したデータの角度に応じてラジコンサーボを制御するプログラムを用意します。といっても、これまでの実験で作成したプログラムをコピー&ペーストして足し合わせるだけのことです。
基本的な構造は、基礎実験4.8 の sched2.c と先ほどの vbtopic.c を足し合わせたものです。ちょっとだけ変わったところといえば、vbtopic.c ではパケット解析がmain関数の中にありましたが、これを独立した関数として外に出しました。また、サーボの出力角度をVB側のテキストボックスに出力させるために、PrintTask を新しく作りました。 PrintTaskを作った理由は、一般に printf という関数は処理が重いので、割り込み処理の中で printf が実行されるようなことを避けたかったことにあります。
予断ですが、本当にコピペで作ったこのプログラムがあまりにも簡単に動いてしまったので、思わず笑ってしまいました(^-^;)
VB側のプログラムを実行すると、このようなウィンドウが出てきます。通信開始ボタンを押すと左下のテキストボックスにPICが出力しているラジコンサーボの角度が表示されます。ウィンドウ左上のスクロールバーを動かすと、ラジコンサーボの角度が変化します。ウィンドウ右上のリセットボタンを押すと、ラジコンサーボの出力角度が0にリセットされます。

いよいよ今回の基礎実験の山場に入っていきます。テキストファイルにデータ列を作っておき、これを読み込んでラジコンサーボをデータどおりに制御することに挑戦します。 基本的なプログラムの作りはこれまで通りで良いとして、VB側でテキストファイルを読み込む部分を新たに作る必要があります。 このテキストファイルの連続読み込みは、Common Dialog Control と Timer を使って実現することにします。
vb_4-9-3.exe を展開してできるフォルダに testdata.txt というファイルが入っています。このプログラムを使ってPICにデータを送る場合は、このファイルのように1列のテキストファイルにしてください。(ご自身で手を加える分には、どのようにしても結構です。) データファイルを手で作るのは大変なので、私は Exel で作ったデータをテキストファイルとして保存することで、このデータファイルを作成しました。

ウィンドウの下半分は以前のものそのままで、上半分が追加分です。ファイル読み込みボタンを押すと、「ファイルを開く」という見慣れたダイアログボックスがでてきますので、そこから送信したいデータのファイルを選択して開きます。それから出力間隔を選択して実行ボタンを押せば、データファイル通りに出力されます。数字だけではどれくらい動いているのか実感がわかないので、出力にあわせてスクロールバーが動くようにしてみました。
説明したいのは山々なのですが、うまく説明できるほど書いた本人も理解していないというのが現状です(汗) ポイントを絞り込んで説明するとすれば、「ファイルから読み込んだデータは動的配列に格納している。」という1点に尽きるかと思います。 データの長さがどれくらいになるか予想できないため、ファイルからデータを読み込みながらデータの数を数えて、配列長を増やすことにしました。 動的配列そのものについては、VBのヘルプを参照してください。
基本的なつくりはこれまでどおりです。 主な変更点は以下のとおりです。
試行錯誤したところがあるので、それ以外にも細かい変更が入っているかもしれませんが、構造は変わっていません。
ここまでの実験で、テキストデータを作ってラジコンサーボをデータどおりに制御することが(一応)できるようになりました。後は、ラジコンサーボの数を増やしていけば何とかなりそうな気がしますよね?
しかし、実はこれまでのPIC側プログラムでは、私が気づいていながらあえて目をつぶってきたことがあります。それは、特定の出力角度近辺ではラジコンサーボが振動してしまうという問題点です。最初はラジコンサーボの特性なのかと思っていたのですが、オシロスコープで信号を見てみたところ、制御信号の周期が微小幅で変動していることがわかりました。 原因は今のところ(2003/04/22現在)特定できていません。
制御信号が微小幅で変動する問題点(一般に「ジッタ」といいます)の原因は、割り込み処理タイミングの遅れによるものであることがわかりました。具体的に言うと、通信割り込みの処理中にサーボ制御信号をLowにするためのTimer1割り込みが発生すべき時間になっても、CSS-PCMでは多重割り込みを禁止していますからTimer1割り込みの処理は通信割り込みの処理が終わるまで実行されず、これがサーボ制御信号をLowにするタイミングを狂わせていたわけです。
さて、対策です。割り込み処理の基本は、「割り込みではフラグを立てるだけ」 だそうですから、現在割り込み処理の中に入っているものを徹底的に割り込み処理の外に追い出すようにすればいいでしょう。 実際にどうすればよいかは、次の実験のソースコードから読み取ってください。
△目次 / 4.10 基礎実験:複数個のラジコンサーボ制御 >>