■槻ノ木隆のPC実験室■FreescaleのDEMO9S08QG8ボードで遊んでみる昨年からFreescaleの動向がちょっと面白い。FreescaleというのはMotorolaの半導体部門が独立した会社で、日本では東京の目黒に本社、仙台に研究開発センター、名古屋に営業所と品質・テストセンター、大坂に営業所をそれぞれ開設している。G4に代表されるPowerPC系CPUや、このPowerPCを組み込んだ、ブロードバンドルータに良く使われるPowerQUICCとかその前身のQUICCといったSoC、あるいはPalmに使われているDragonBallシリーズなど、民生機器に向けて幅広く製品を展開している。CPUのみならず、フラッシュメモリとかアナログ部品なども盛んで、最近では世界で初めてMRAMの製品化に成功したあたりもちょっとしたトピックである。ここまで書けばおわかりな通り、Freescaleは直接的には機器メーカーが商売の相手であり、直接コンシューマに対して製品を売るということはない。G4を入手したところでMacが作れるわけではないし、Apple自体PowerPCを捨ててしまっているから、IntelなりAMDからCPUを購入して自作するといったPCの世界ではあたりまえの動機は、ここでは発生しない。Freescaleのパーツを使った最終製品(ルータとか民生機器各種、あるいは基地局のシステムなど)をユーザーがどうこうする事はありえないから、コンシューマには無縁の会社といって良かった。過去形なのは、「やっぱこのまんまではいけない」とどうもFreescaleが考えている模様だからだ。今年に入ってからは電子工作キット制作コンテストを開催したり、九十九電機のロボット王国でも取り扱いを始めたり、と積極的なコンシューマ向けの展開を行なっている。ここで主眼となるのは、やはり「モノ作り」。「電子工作」に目を向けてもらうことで、ここでFreescaleの名前を知ってもらおうという話である。した事もあってか、筆者の手元にFreescaleが本来は開発者向けキットとして提供しているDEMO9S08QG8のキットがやってきた。ちなみにこのキット、上述のロボット王国の他にマルツパーツ館などでも入手可能である。アメリカ国内でのFreescale直販価格は50.00ドル(*1)、国内では6,000~7,000円の値段付けとなっている。編集長からは「これ使って夏休みの工作ネタを1つ」というオーダーを頂いたのだが、記事の掲載時期を見ればお分かりのとおり見事に失敗である。どのように失敗したか、という話は後でもう少し詳しく説明したい。試しに日本までの通販を掛けてみたら、送料込みで75.83ドルとなった。考えても国内で購入するほうが安い。●環境の用意さて、パッケージ自体はA4よりもちょっと大きめの箱1つである(写真01)。中をあけると、本体とUSBケーブル、CD-ROMのパッケージと簡単なマニュアルが入っている(写真02)。Pack、それにAXIOMの製品CD-ROMの4枚が付属している。manufactureingが製造するAXM-0363という製品である(同社トップページからリンクなし)。そんな事もあって、製品マニュアルやサンプルプログラム、ユーティリティなどはエンベロープに入ったCD-ROMに入っている。マニュアルなどはAXM-0363のサポートページからも入手可能だ。ボードそのものは75×63mmという非常に小さなもので、ここにUSBポートとシリアルポート、ACアダプタのほか、汎用のI/Oインターフェイスが用意されている(写真04)。汎用I/Oインターフェイスは基盤裏側にソケットが用意されており、簡単にデバイスの接続が可能だ(写真05)。USBはBコネクタ、シリアルポートはD-Subの9ピンが(写真06)、反対側にはACアダプタとボリュームが用意される(写真07)。【写真02】AXM-0363のFAQを見ると、「真っ白な」USBケーブルが付属している製品の中には故障していて交換が必要なものがあるそうだ。MCUのMC9S08QG8。【写真05】ジャンパピンなどをこのソケットに差し込む形で接続できる。拡張基盤に適当にポストを立てるだけで済むので便利だ。【写真06】シリアルでPCと接続する場合、9ピンのオス⇔メスケーブルが必要。【写真07】右のボリュームも、プログラムから自由に使える。2Aのものを繋いでも正常に動作したさて、まずは環境の作成だ。5.0のインストールである(写真08)。CodeWarriorとは元々MetroWorksという会社がMac上の開発ツールとして発売したIDE(統合開発環境)だが、その後MotorolaがMetroWorks自体を買収し、自社のMCU向けに各種のCodeWarriorを提供している。MCU専用で、多少の機能制限(プログラムサイズが16KB以内など)が付くものの、実用上はほとんど支障がないバージョンである。Editionのお得さが身にしみる。インストールの最後で、ネットワークに繋いでいるとにアップデートチェックが実行される(写真09)。アップデートも、全オプションを選択しておくのが便利だ(写真10)。インストールが完了すると、MC9S08QG8用のUSBドライバも同時にインストールされる。2.0というデバイスとしてPCから認識される(写真12)。2.0がUSBコントローラ配下にない、というのがミソ。DEMO9S08QG8ボードをUSBデバイスとして扱うのは不可能である。●サンプルプログラムのロードさて、環境の準備が出来たらちょっと実際に動作を確認してみたい。EMO9S08QG8ボードからUSBケーブルを外し(何しろUSBデバイスではないので、「デバイスの取り外し」は不要だ)、ジャンパを確認する。Close(これは必須ではない)になっていることを確認する。PWR”、それに“VDD”というLEDが点灯するはずだ。Mode)用のMC9S12UF32PUの両方に、USBバスパワーで電力を供給している。電源が供給されると、MC9S08QG8は内蔵しているフラッシュメモリに書き込まれたプログラムを読み出し、自動的に実行を開始する。最初に書き込まれているプログラムは「LED1は、SW1を押すたびにON/OFFを切り替える。LED2は点滅を繰り返す」というシンプルなもの。実際電源を入れると、これがあっさり立ち上がる(動画01)。いつまでもLEDを点滅させていても仕方がないので、もう少し他のこともしてみよう。CD-ROMの中の\Examples\DEMO9S08QG8\CodeWarriorというディレクトリの中に、Demo_S08QG8_Test.zipとDEMO9S08QG8_APP.zipという2つのzipファイルがある。Demo_S08QG8_Test.zipの方は、工場出荷時に書き込まれているLED点滅プログラムそのものなので、もう1つのDEMO9S08QG8_APP.zipの方を任意のフォルダに展開する(写真14)。ここで“DEMO9S08QG8_APP.mcp”というファイルをダブルクリックすると、CodeWarriorが立ち上がる(写真15)。このCodeWarriorの画面で“Make”(ソースプログラムを実行可能形式に変換)、ついで“Debug”(デバッガを起動し、MC9S08QG8にプログラムをロードする)を行なう(写真16)。Debbuger”と呼ばれるツールが立ち上がるが、それに先んじてこんなダイアログ(写真17)が表示される。ここまでの手順に間違いがなければ、USBポート経由でのプログラムロードが選択されており、またCPUにはHCS08が選ばれているはずなので、これを確認して“Connect”ボタンを押す。Memoryに書き込むかどうかのダイアログが表示される(写真18)ので、Yesを選択するとUSB経由で今Makeしたプログラムが書き込まれるはずだ。完了すると、デバッガの画面が表示される(写真19)。ここでデバッガから実行を選択すればプログラムは走り出すのだが、その前にちょっとやっておくべき事がある。RS-232CケーブルでDEMO9S08QG8ボードとPCを繋ぎ、PC側で適当なターミナルソフトを立ち上げておくことだ。MC9S08QG8はシリアルポートの制御も可能であり、これを利用してDEMO9S08QG8_APPにはシリアルポート経由で対話式に処理を行なえる一種のインタープリタが実装されている。そのために、PC側にその相手となるターミナルソフトが必要になる。今回は定番TeraTermのUTF-8/TTSSH2対応版を入手して使ったが、別に普通のTeraTermでもいいし、その他のターミナルソフトでも問題はない。1に設定しておく(写真20)。ここまでの手順に問題がなければ、デバッガ画面で“Run”を選択するとターミナル画面にメニューが出現するはずだ(写真21)。【写真18】MC9S08QG8は1度に1つしかプログラムをロードできず、またプログラムは必ず内蔵のフラッシュメモリに格納されていないといけない。【写真19】デバッガ画面。2画面が欲しいところ。【写真21】メニュー形式で色々動作をテストできる。このプログラム、単体ではあまり意味がないというか、各機能の動作テスト用という趣が強いので、ボードの構成を理解しないと使いにくい。逆に自分でハードウェアを作っていろいろ繋げる際のテストとか、シリアルポートの使い方を理解するのには最適である●自分でプログラミングしてみるさて、ここからはC言語の知識が必要になる。C言語の解説までやってると原稿量が爆発するのでご容赦いただきたい。簡単なところで・LED1が高速(数回/秒)で点滅する・LED2が低速(1回/2秒)で点滅するといったプログラムを組んでみることにしたい。CodeWarriorを単独で起動する(写真22)。Project”を選ぶ。基本設定(写真24)ではC言語を選び、プロジェクト名とディレクトリを入力する。Pro”を選択する(写真25)。次は追加ファイルの設定(写真26)だが、新規に作るのだからここは何もなしである(写真26)。Expert”を選ぶ必要がある(写真27)。次は言語環境だが、概ねデフォルトのままで良いだろう(写真28)。最後にLintを掛けるかどうかの質問が出てくるが(写真29)、とりあえず作るレベルだからNoのままでよいだろう。Expertが起動する。最初にCPUの選択が出てくるので、ここでは“MC9S08QG8_16”のみをチェックしておく。ついでProjectのビルドをどうするかの選択が出てくる。最終製品であればReleaseビルドのみなのだろうが、今はDebugビルドのみでよい。以上の設定が終ると、やっとCodeWarriorが立ち上がる(写真33)。【写真24】ディレクトリはLocation+Project名という構造。modelは必要ない。Routineのテンプレートを作成してくれるツール。【写真32】Windowsの世界では、Debugビルドだと最適化を甘くしてソースとマシンコードの連携を取り易くするといった話が出てくるが、試した限りではそういうことはないようで、単にDebug用のスタブやシンボルテーブルを生成するか否かといった違いに見える。16本のピンがどう使われているかがわかりやすく示されるさて、まずはLEDの制御である。6番ピン(ポート名PTB6)をHighにすればLED1が点灯、Lowにすれば消灯という仕組みだ。これはLED2も同じである。I/O”を選び、ここの“BitI/O”をダブルクリックすると、プロジェクトにそのBeanが追加されると共に、Inspectorに詳細設定が出てくる(写真34)。I/O”に“PTB6_SDA_XTAL”を(写真35)、“Direction”には“Output”を選択しておく(写真36)。同様にBit2も追加し、こちらは“PTB7_SCL_EXTAL”を割り当てる。こちらもやはり“Output”だ。これとは別に、一定期間で点滅させるためには、一定期間を通知するための方法が必要である。LED2の方を考えよう。数秒に1回という目的だと、例えば1秒に1回ずつ割り込みを掛け、割り込みルーチンの中でON/OFFを切り替えれば良い。した場合にはTimerInterrupt(TimerInt)が有用である。Selectorで“Timer”→“TimerInt”をダブルクリックし、これをプロジェクトに追加する(写真37)。Routine)が呼ばれる。Inspectorの中で指定を行なう(写真38)。残念ながらTimerIntは1つしか使えないので、LED1では同じ方法は使えない。あるアプローチは、そもそもTimerIntの解像度を思いっきり細かく(例えば1ms)とかにしておき、ISRの中でLED1とLED2の両方を制御する(例えばISRが50回呼ばれるたびにLED1のON/OFFを、1,000回呼ばれるたびにLED2のON/OFFを行なう)なんて方法で、別にこれが悪いわけではないが、折角のサンプルなのでもうひとひねりした。プロジェクトでCPUを展開すると、“Delay100US”という項目がある。デフォルトはDisableだが、これをEnableにすると呼び出せるようになる。これは“100μsの整数倍だけ待機する”という命令で、何倍待機するかはパラメータで渡せる。このDelay100USをLED1のタイマー代わりに使うことにした。Expert周りの作業は完了である。この時点で一度Makeを掛けると、必要な初期化コードとコールバックのテンプレートを作成してくれる。生成されたコードがList1(Test.c)とList2(Event.c)である。###################################################################*/見ればわかるとおり、プログラムはTest.cの先頭から走り始め、そのままぐるぐる回っている。***/となっていることからわかる通り、要するに無限ループでぐるぐる回りっぱなしという代物だ。この部分はCodeWarrior(というか、ProcessorExpert)が勝手に生成するので、書き換えは不可能である。Event.cは、こちらも見ればわかるとおり、先のTimerIntの割り込みが入る度にTI1_OnInterrupt()が呼び出されるという訳だ。これをどう書き換えたかであるが、List3がTest.c、List4がEvent.cである。List3の方は、常識的なプログラマからすると激怒ものなのだろうが、どっちみち最後は無限ループで回ってるだけなので、手前にもう1個無限ループを入れたところで支障はない。中ではCpu_Delay100US()を使って200ms待機させてからLEDの状態を反転している。Bit1_GetVal()はLEDが点灯してればTRUE、消灯してればFALSEを返すので、これを反転してBit1_SetVal()するというだけだ。いいじゃないか」とか突っ込みが入りそうだが、Bit1_GetVal()がマクロで実装されてる関係で、これがあまり上手く動かないのでこんなコードとなった。Event.cの方も同様である。こちらはタイマーが勝手にタイミングを決めてくれるので、単にLED2のON/OFFをするだけだ。*/}このコーディングが終わったら、再びMakeを行ない、エラーがなければDebugを開始する。この手順は先ほどと同じであり、問題なければ点滅する(動画02)。【写真34】左のプロジェクトツリーに“Beans”と“Bit1:BitIO”が追加されているのがわかる。【写真36】LEDは光るだけなのでOutputに設定する【写真37】まだ割り込み周期を設定していないので、プロジェクトウィンドウでは“!”マークがついているのがわかる。【写真38】何も1,000msにしなくても1secでいいのでは?とか言われそうだが、まぁ気分の問題。●工作の課題に向けてそんなわけで、ここまでは順調であった訳だが、ここからがいけなかった。作れる目処は立ったが、DEMO9S08QG8ボード単体で出来ることには限界がある。夏休みの工作というからにはやはりもうひとひねりしないと、このまま出したら失格を食らうのは目に見えている。そこで「何かデバイスをつけないと」という事になる。最初は温度センサーとモーターコントローラでも入れて、PCのファンコントロールをUSB経由でプログラムから出来ないかとか思っていたが、MC9S08QG8がUSBで接続できないのでこの案は放棄。いうわけで、上述のパーツ王国まで足を伸ばして色々見ていて見つけたのがこの超音波測距センサー(写真40)。浅草ギ研が同社のH8マイコンに接続するためのキットとして販売しているものだが、ぱっと見た限りDEMO9S08QG8ボードでも使えそうである。いうわけで、早速購入。これだけだと接続がちょいと面倒なので、ユニバーサル基盤とピンヘッド(写真41)を千石電商で購入した。動作するかどうかの確認である。超音波測距センサーのページにも説明があるが、センサー自体は5V電源とGND、それにトリガー/信号ピン(以前はこれが別だったが今は一緒になっている)の3本の端子だけで構成されている。トリガー/信号ピンはTTLレベルだから、DEMO9S08QG8のI/O端子に直結しても問題はなさそうだ。Connectorは写真41のようになっている。1番のVDDから+5V、3番からGNDを取り、あとは適当なピンにトリガー/信号をつなげれば良い、という目論見だったが、試しに測定してみるとVDDに出ているのは+3.3V。USBバスパワー/ACアダプタのどちらの場合でも、電源ラインはすぐにレギュレータ経由で3.3Vに降圧されるようだ。3.3Vではやはり超音波センサーが動かない。・動作は5VのACアダプタを接続した状態で行なう。最終的にはACアダプタの代わりにマンガン電池3本(4.5V)なりニカド電池4本(4.8V)を供給する。・ACアダプタの端子から直接電源を取る(写真43)。おかげでいきなり超音波測距センサーが物理的にDEMO9S08QG8ボードと一体化する羽目になった。その超音波測距センサーは写真44のようなな形状である。そこで、ユニバーサル基盤に直立するように脚をまげて取り付け(写真45)、写真43にもちらっと見えているように配線すればOKである。ユニバーサル基盤には写真41に映っているピンヘッドをやはりハンダ付けで取り付けた(写真46)。これを組み合わせると、写真47のような構造になる。【写真40】値段は5,250円であった。【写真41】ユニバーサル基盤は105円、ピンヘッドは80円。ド太いケーブルは、ジャンク箱の中に落ちてた電源配線用のものだが、もうすこし細いケーブル買ってくれば良かったと後悔。Manualからの抜粋。【写真43】配線が余りに太すぎ。赤が+5V、黒がGND、黄色がトリガー/信号である。【写真44】片方が発信、片方が受信である。音波が行き戻りする時間から距離を測定するというわかりやすい仕組み。【写真45】この状態でハンダ付けすれば固定される。【写真46】必要なのは1本だけなのだが、それだとあまりに機械的強度が乏しいので、全部で10本のピンヘッドを取り付ける。このうち1本(10番ピン:PTB6に接続)が超音波距離センサーのトリガー/信号に接続されている。【写真47】USBはデバッグ専用で、単体動作時はACアダプタだけで動く。これを電池に切り替えて、適当なガワを作れば、一応工作らしい体裁は整うと目論んだ訳だ。ここまでは順調(とかいいながら配線間違えたりしたので、実質1時間強掛かっている)だったが、問題はここからである。作るものとしては、連続的に(例えば毎秒10回とか)距離を測定し、ある閾値(例えば1m)以内だったらLEDを点灯するといったものを想定していた。最終的にはLEDの代わりに圧電ブザーなんかをつなげれば完璧というわけだ。測定時間から距離を算出して、LEDを点灯するといった具合になる。このうち・毎秒10回の部分は、TimerIntを使えば簡単に実現できる。・LEDの点灯も既に実験済み。立ち上がっている時間を測定するの2つがネックになる。実はこれに必要な部品(CodeWarriorで言うところのBean)は既にある。写真37に戻ると、FreeCnt8/16/32というBeanがあるのがわかるはずだ。これは8bit/16bit/32bitのカウンタで、解像度は最小1μsである。break;}Bit1_SetVal(FALSE);といった具合に記述できる。FC161は16bitのカウンタで、FC161_Reset()はカウンタの初期化、FC161_GetTimeUS()は時刻をμsecで返す関数である。トリガだけなら5μsだから8bitカウンタでも十分だが、距離の測定は最大18.5msec(18500μsec)まで測定できないとまずいので、8bitだとオーバーフローする関係で16bitカウンタとしている。実は当初このコードで問題なく動いていたのだが、デバッグの途中でいきなりカウンタを読み出すとCPUがハングアップする現象に陥った。ためしに超音波測距センサーを外しても現象は変わらず、どうもMC9S08QG8内部のカウンタ部が壊れた(というか、筆者が壊した)模様だ。前節「自分でプログラミングしてみる」でも、最初はこの16bitカウンタを使ってサンプルを作っていたのだが、途中から動かなくなり、やむを得ずCpu_Delay100US()なんぞを使ってサンプルとしたのが正直なところだ。この状態でも、例えば時間測定はTimerIntを使ってISRの中で自分で管理し、距離測定ロジックはmain()の中で廻すという技は使えなくもないが、FreeCntが使えれば不要な作業なだけに、全然参考にならないということであきらめた。そんなわけで、夏休みの課題は失格である。●というわけでいきなり失敗しましたというレポートも変な感じではあるが、割と手軽に電子工作が出来るというイメージは理解いただけたかと思う。個人的に気に入ったのは、プログラミングの手軽さだ。汎用I/Oピンを直接叩けるし、設定も自由自在だ。OSとかが介在しないから余計な事を考える必要もない。あとデバッガもかなり強力である。ソースラインデバッグが可能だし、変数の値も直に読んだり変更したりできる。必要ならポートの操作まで可能であり、かつてクロスプラットフォーム環境で必死こいてデバッグしていたのが嘘のような快適さがある。今回は超音波センサーを使ってみたが、他にも3軸加速度センサーやモーター制御なども可能だし、組み合わせれば自由度は広がるだろう。日本語のマニュアルは無いし、C/C++/アセンブラ以外の開発環境はないから、これらに慣れていない人にはちょっと敷居が高いかもしれない。逆にこのあたりが問題にならない人には、とてもよいオモチャになることを保証する。久々に楽しい日々であった。