マイコンでプログラムをつくって動かしてみる場合の操作は
最後のマイコンにプログラムを仕込む段階は、対象によって様々ですが、今回使用するH8/3052はプログラム書き込みモードにして電源を投入すると、シリアルポート(SCI)からプログラムをダウンロードできるようになっています。
そのため、一度製品に組み込んでしまっても、ソフトウエアのアップデートなどは容易です。
実際に、ロボットの開発などではプログラムを修正しては書き込む、という作業を何度も行います。
(より簡単にするには、RAMを外付けして、そこにプログラムを転送して試す、という手もありますが、ワンチップマイコンらしからぬ状態になります)。
一応、書き込み寿命は100回以上などと記載されていますが、経験上派手に使っても書き込めなくなるまで使った例はほとんどありません。
(その前に電気的にどこかが壊れるため...というのも芳しくありませんが)
実習では
h8progにはコンパイルに必要なツールと、サンプルソースがあります。
なお、不要になった場合はフォルダごと廃棄してください。
とはいえ、まっさらの状態から作ることは大変ですので、まずは以下のサンプルプログラムの中身をのぞいてみたり、それを改造するところから始めます。
まず、コマンドプロンプトを開いてください。
(メニュー:プログラム→アクセサリより、もしくはファイル名を指定して実行で "cmd")
そこで、先ほど用意した h8progにカレントディレクトリを移動します。
たとえば、"D:\h8prog"にいれた場合は"d:" "cd \h8prog" とします。
フォルダ名が長い場合は、フォルダを開いた状態で上部に表示されているパスをコマンドプロンプトにドラッグ&ドロップすれば手間が省けます。
そこで、プログラム("source.c"とします)をコンパイルします。
このとき、メッセージが大量に表示されますが、"error"っぽいものが混じっていなければコンパイルはできています。 念のため、compileの最終生成物である、"source.mot"があるか、その日付が最新になっているか確認してください。D:\h8prog> compile source compile以降を入力+enter
あとは、書込スイッチを外側に倒して電源をいればおせば、書き込んだプログラムがスタートします。
このプログラムの上半分はパソコンにSCI→シリアルポートでデータを送信するための関数群です。
これのプログラムを早速動作させてみます。
電源をいれれば動くのですが、それでは結果を見ることができません。
適当な通信ターミナルソフト(TeraTermなど)があれば、それを利用して、なければ、h8prog内にある "sermon.exe"をつかって(設定は別途説明)出力をみてみましょう。
その上で、アナログ入力端子に可変抵抗器や、センサ類をつないでみて、値が変化していく様子を確認してください。
なお、本来のC言語にはP1とかAD.DRAといった単語はありません。一番最初で"include(含む)"されている3048f.h内で、3052の機能を使いやすくみせているものです(3048は3052の古い版でこの辺りは互換性あり)。
C言語の詳細には触れませんが、最低限の説明をします(なんとなく、プログラムの意味は伝わると思います)。
C言語のプログラムは「関数」の集合体で構成されます。
関数名(引数)
{
....
}
という部分です。下の方にある main() という関数が、電源投入の直後に実行されます。
ここから、他の関数を呼び出す形で処理が進みます。
ちなみに、プログラム内に使われない関数があってもかまいません。
main()関数の中では、まず、各種初期化を行います。
InitializeSCIを呼んで通信を初期化し、ADは前にやったように0〜3チャネルで連続変換に設定し、DAを有効化しています。
そのあとが処理の本体です。"while(1) { .. }"はずっとこの間の処理を繰り返す、という意味です。
ここでは、一周ごとに1ずつ増える変数c、ポート1の読み取り値を10進および16進数で、AD変換の値4つを10進数で、表示するようになっています。
(通信部分は同じなので略)
main()関数の中で、変更された部分は、ITU3,4の初期化が追加されたことと、while(1)の中身がITU3,4のGRA,GRBを参照するように書き換えられたことです。
これもコンパイルして書き込んで、加速度計をつないで実行してみると、角度に応じて値が変化することが確認できます。
main()関数では、ポート2の下4ビットをモータへの指令のために出力に切り替えて、while(1)のなかでパターン出力を行います。
最後の /*時間潰し*/、と記載された部分は0から99まで無駄に数えることで時間潰しをしています。
これがないと、一番遅くしても早すぎるので、適当に遅くなるように調整しました。
このプログラムは通信を行わないので、パソコン側ではなにもいりません。
プルダウン型の端子基板を取りつけれあれば、電源を入れてプログラムが動作しても動きません(speed=0になるため)。
あるところまでスピードを上げると、「ぶー」と音はするものの、回り方が変になります。
これはステッピングモータの脱調と呼ばれる現象で、パルスを切り替える間に次の位置まで回転が進まなくなっておいて行かれる現象です。
こうなると、ステッピングモータの利点である、パルスを送るだけで正確に回転するという利点が無くなるため(それどころか止まったことも検出できない)、こうならない範囲で使用する必要があります。
このプログラムを改造してみましょう。
まず、GetStep(方向)関数は、方向が正の場合はステップを1つ進めるのに必要な励磁パターンを、負の場合は逆に一ステップ進めるためのパターンを返します。0を渡された場合は、現状維持です。
この関数では、その上で用意した StepPatternを順番に読むことで動作します。
StepPatternを読む位置はstepseq変数で、これが増減します。
この例では4パターンを順に使用するため、stepseqが3から4になったときには0に、0から−1になったときは3に強制的に変更しています(STEPCは4と等しいと定義してあります)。これによって、0-1-2-3-0-1-2-3、もしくは 3-2-1-0-3-2-1-0のような順にStepPatternを読み取ります。
(C言語ではデータのならびは0から順に数える)
さて、このプログラムでは、countとspeedという二つの変数が重要な役割を持ちます。
speedは文字通りスピードです。count変数は、while(1)が一回回る度に、speedだけ増えます。
たとえばspeed=10の場合、10ずつ増えていき、1000周に一回は、count+speed>10000の条件に反応し、GetStepに1が渡され、ステッピングモータのステップが一つ進みます。
このとき、10000を越えたぶんは、10000を引くことで、値が戻って、次の1000回で徐
々にまた増えてきます。そのあいだはGetStep(0)でパターンは進みません。
ここで、speedが20になると、500回で10000まで増えます。while(1)の中は毎回ほぼ同じ時間で処理されるので、speed=10の時に比べて、半時間でステップが進むようになります。
つまり、回転速度が倍になります。
speed=30になったら、割りきれませんが、おおむね3倍の速度になります。
このようなプログラムを組むことで、指令した速度で回せるようになります。
GetStepで得たパターンは、毎回P2.DRを通じて出力します。
(.BYTEという表記は、P2はビット単位でも操作できるため、バイト単位であることを明記)
そこで、+5V端子と、ビット0〜7の端子を適宜つないでみます(+5Vにつないだ線で端子に触ってみる、程度)。
ビット0に比較してビット1、2となるにつれ、2倍、4倍と速度があがります(いいですよね?)。
プログラムの修正を試すとき、コピーを作って名前を変えておいた方がいいでしょう。
※
その上で可変抵抗器をつないで、つまみで速度が変わることを確認する。
このとき、パターンの数が変わらないならそのままStepPatternを書き換えれば良く、8データのパターンにするならば、その上の#define STEPC 4を8に書き換える。
今回は、targetとcurrentという変数がでてきます。 currentはモータの現在の回転角を保持していて、targetは目標角度です。 プログラム開始時を角度0としています。 targetは先ほどのspeed同様、なんらかの入力をつかいます。
ステッピングモータは前述のように、ある程度の速度以下で回す必要があります。 そのことを念頭に、ここでは、目標と現在値を比較して、それに応じてGetStep()を呼び出しています。それと同時に、現在値を更新しています。 こうすることで、1ステップずつ目標に近づけることができます。 モータの回転速度よりも早く目標が変化した場合は、一定の速度で追いかけることになります。
試し方は先ほどと同じで、端子に適当に5Vを与えてください。
これも改造してみましょう。
によって、指令が0〜1023で与えられます。target=(AD.DRA>>6);
30000はセンサを水平にしたときだいたいそのくらいなので、適当に引きました。30で割るのも分かりやすくするためです。target=((int)ITU3.GRB-30000)/30;
後者はそのまま加速度計をポートBにつないで、前者は温度センサや距離センサをつないでみましょう。小刻みなふれがどうしても出てしまいますが、それぞれ、ディジタルだけどアナログに針表示の傾斜計、温度計、距離計になります。
さらに、ステッピングモータでは不適かもしれませんが、同様のシステムを作り、回転部分に加速時計や距離センサをとりつけると、フィードバック的な動作をするようになります。
などなど、本当に使い切ることは容易ではありません。 しかし、こんな感じで動作するんだ、という感覚さえつかめれば、この先を試してみるきっかけにはなるのではないかと思います。