槻ノ木隆のPC実験室

FreescaleのDEMO9S08QG8ボードで遊んでみる




 昨年からFreescaleの動向がちょっと面白い。FreescaleというのはMotorolaの半導体部門が独立した会社で、日本では東京の目黒に本社、仙台に研究開発センター、名古屋に営業所と品質・テストセンター、大坂に営業所をそれぞれ開設している。同社はPowerPC G4に代表されるPowerPC系CPUや、このPowerPCを組み込んだ、ブロードバンドルータに良く使われるPowerQUICCとかその前身のQUICCといったSoC、あるいはPalmに使われているDragonBallシリーズなど、民生機器に向けて幅広く製品を展開している。単にCPUのみならず、フラッシュメモリとかアナログ部品なども盛んで、最近では世界で初めてMRAMの製品化に成功したあたりもちょっとしたトピックである。

 ただここまで書けばおわかりな通り、Freescaleは直接的には機器メーカーが商売の相手であり、直接コンシューマに対して製品を売るということはない。まぁいまさらPowerPC G4を入手したところでMacが作れるわけではないし、Apple自体PowerPCを捨ててしまっているから、IntelなりAMDからCPUを購入して自作するといったPCの世界ではあたりまえの動機は、ここでは発生しない。ましてやFreescaleのパーツを使った最終製品(ルータとか民生機器各種、あるいは基地局のシステムなど)をユーザーがどうこうする事はありえないから、コンシューマには無縁の会社といって良かった。

 過去形なのは、「やっぱこのまんまではいけない」とどうもFreescaleが考えている模様だからだ。今年に入ってからは電子工作キット制作コンテストを開催したり、九十九電機のロボット王国でも取り扱いを始めたり、と積極的なコンシューマ向けの展開を行なっている。ここで主眼となるのは、やはり「モノ作り」。つまり「電子工作」に目を向けてもらうことで、ここでFreescaleの名前を知ってもらおうという話である。

 こうした事もあってか、筆者の手元にFreescaleが本来は開発者向けキットとして提供しているDEMO9S08QG8のキットがやってきた。ちなみにこのキット、上述のロボット王国の他にマルツパーツ館などでも入手可能である。アメリカ国内でのFreescale直販価格は50.00ドル(*1)、国内では6,000~7,000円の値段付けとなっている。で、編集長からは「これ使って夏休みの工作ネタを1つ」というオーダーを頂いたのだが、記事の掲載時期を見ればお分かりのとおり見事に失敗である。どのように失敗したか、という話は後でもう少し詳しく説明したい。

(*1) これは税/送料別。試しに日本までの通販を掛けてみたら、送料込みで75.83ドルとなった。どう考えても国内で購入するほうが安い。

●環境の用意

 さて、パッケージ自体はA4よりもちょっと大きめの箱1つである(写真01)。中をあけると、本体とUSBケーブル、CD-ROMのパッケージと簡単なマニュアルが入っている(写真02)。CD-ROMはCodeWarrior 4.5と5.0、5.0のService Pack、それにAXIOMの製品CD-ROMの4枚が付属している。実はこの評価キットのボードそのものは、米AXIOM 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)。

【写真01】大きさはちょいとかさばるが、重さはたいしたこと無い(というか、軽い)ので店頭で購入、持ち帰りも苦にはならない 【写真02】AXM-0363のFAQを見ると、「真っ白な」USBケーブルが付属している製品の中には故障していて交換が必要なものがあるそうだ。今回は白というよりもややベージュかかった色のものなので問題なし 【写真03】右下のCD-ROMがCodeWarrior 4.5だが、これはHCS12という別のMicroController用なので今回は用なし
【写真04】中央下にある16ピンのICが、今回利用する8bit MCUのMC9S08QG8。中央にあるQFPはUSBコントローラを含むBDMのMC9S12UF32PUという16bit MCU 【写真05】ジャンパピンなどをこのソケットに差し込む形で接続できる。拡張基盤に適当にポストを立てるだけで済むので便利だ。このあたりは後述 【写真06】シリアルでPCと接続する場合、9ピンのオス⇔メスケーブルが必要。ストレートで大丈夫
【写真07】右のボリュームも、プログラムから自由に使える。ACアダプタは2mmφで、7V~18Vの範囲に対応(デフォルトは9V)という話だったが、ためしに手元のUSBハブに付属していた5V 2Aのものを繋いでも正常に動作した

 さて、まずは環境の作成だ。とりあえずWindowsマシンを1台用意し、まずはCodeWarrior 5.0のインストールである(写真08)。CodeWarriorとは元々MetroWorksという会社がMac上の開発ツールとして発売したIDE(統合開発環境)だが、その後MotorolaがMetroWorks自体を買収し、自社のMCU向けに各種のCodeWarriorを提供している。今回キットに付属しているものはHCS08というMC9S08QG8の中に入っている8bit MCU専用で、多少の機能制限(プログラムサイズが16KB以内など)が付くものの、実用上はほとんど支障がないバージョンである。ちなみに一切機能制限が無い正規版(現状のバージョンは5.1)の場合、Standard Editionの一番安いもので$1,440とかなり高価であり、Special Editionのお得さが身にしみる。インストールの最後で、ネットワークに繋いでいるとにアップデートチェックが実行される(写真09)。アップデートも、全オプションを選択しておくのが便利だ(写真10)。

 インストールが完了すると、MC9S08QG8用のUSBドライバも同時にインストールされる。この時点でUSBケーブルを使ってMC9S08QG8をPCに繋ぐ(USBバスパワーで駆動できるので、ACアダプタは必ずしも必要ではない)と、ドライバがロードされ(写真11)、最終的にはUSB Multilink 2.0というデバイスとしてPCから認識される(写真12)。

【写真08】このあとWizardでインストールオプションを選択できるが、全機能を入れても大した容量ではないので“Full Install”を選択しておこう 【写真09】CD-ROMからService Packを当てる場合は、ここで“いいえ”を選ぶべし 【写真10】このあと、各Service Pack別に4回もInstall Wizardが走るのがちょっと面倒ではある
【写真11】USB Multilink 2.0というのがデバイスの名前となる 【写真12】このUB Multilink 2.0がUSBコントローラ配下にない、というのがミソ。つまりDEMO9S08QG8ボードをUSBデバイスとして扱うのは不可能である。まぁ仮にこれが可能でも、肝心のMC9S08QG8はUSBインターフェイスを持っていないのであまり意味はないのだが 【写真13】ジャンパ位置

●サンプルプログラムのロード

 さて、環境の準備が出来たらちょっと実際に動作を確認してみたい。まずEMO9S08QG8ボードからUSBケーブルを外し(何しろUSBデバイスではないので、「デバイスの取り外し」は不要だ)、ジャンパを確認する。写真13にジャンパ位置をまとめたが

・User Option Jumper : 全てClose
・COM Enable : Open
・Power Select : “VB”側をClose
・VX Enable : Close(これは必須ではない)

になっていることを確認する。この状態で再びUSBコネクタを差し込むと、“USB”と“USB PWR”、それに“VDD”というLEDが点灯するはずだ。この状態では

・MC9S08QG8そのもの
・BDM(Background Debug Mode)用のMC9S12UF32PU

の両方に、USBバスパワーで電力を供給している。電源が供給されると、MC9S08QG8は内蔵しているフラッシュメモリに書き込まれたプログラムを読み出し、自動的に実行を開始する。最初に書き込まれているプログラムは「LED1は、SW1を押すたびにON/OFFを切り替える。LED2は点滅を繰り返す」というシンプルなもの。実際電源を入れると、これがあっさり立ち上がる(動画01)。

 ただいつまでもLEDを点滅させていても仕方がないので、もう少し他のこともしてみよう。AXM-0363 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)。Debugを呼び出すと“True-Time Simulator & Real-Time Debbuger”と呼ばれるツールが立ち上がるが、それに先んじてこんなダイアログ(写真17)が表示される。ここまでの手順に間違いがなければ、USBポート経由でのプログラムロードが選択されており、またCPUにはHCS08が選ばれているはずなので、これを確認して“Connect”ボタンを押す。するとFlash Memoryに書き込むかどうかのダイアログが表示される(写真18)ので、Yesを選択するとUSB経由で今Makeしたプログラムが書き込まれるはずだ。完了すると、デバッガの画面が表示される(写真19)。

 ここでデバッガから実行を選択すればプログラムは走り出すのだが、その前にちょっとやっておくべき事がある。RS-232CケーブルでDEMO9S08QG8ボードとPCを繋ぎ、PC側で適当なターミナルソフトを立ち上げておくことだ。MC9S08QG8はシリアルポートの制御も可能であり、これを利用してDEMO9S08QG8_APPにはシリアルポート経由で対話式に処理を行なえる一種のインタープリタが実装されている。そのために、PC側にその相手となるターミナルソフトが必要になる。今回は定番TeraTermのUTF-8/TTSSH2対応版を入手して使ったが、別に普通のTeraTermでもいいし、その他のターミナルソフトでも問題はない。通信パラメータは4800baud 8bit None Parity Stop bit 1に設定しておく(写真20)。ここまでの手順に問題がなければ、デバッガ画面で“Run”を選択するとターミナル画面にメニューが出現するはずだ(写真21)。

【写真14】ここではためしにデスクトップに展開したが、CodeWarriorは内部でファイルを絶対パスで持っているようで、後でこのフォルダを別の位置に移動すると正しく読み込めない場合があったので注意してほしい 【写真15】ここではソースコードを展開して表示しているが、最初は何も表示されていない 【写真16】メニューの“Project”→“Make”(もしくはF7キー)と“Project”→“Debug”(もしくはF5キー)でも可能
【写真17】にここでは、例えばシリアル/パラレルポートでのダウンロードとか、実機を使わずにシミュレーションでの実行なども選択できる 【写真18】MC9S08QG8は1度に1つしかプログラムをロードできず、またプログラムは必ず内蔵のフラッシュメモリに格納されていないといけない。このため、これを実行すると工場出荷時のプログラムは消える事になる 【写真19】デバッガ画面。後でだいぶ活躍したが、正直いってウィンドウがかなり多いので、快適に利用したいと思うと最低でもSXGA、出来ればUXGAもしくはSXGA 2画面が欲しいところ。この画面では既にデバッガが実行中である
【写真20】このパラメータは、単にDEMO9S08QG8_APPでそう設定されているだけの話で、深い意味はない 【写真21】メニュー形式で色々動作をテストできる。もっともこのプログラム、単体ではあまり意味がないというか、各機能の動作テスト用という趣が強いので、ボードの構成を理解しないと使いにくい。逆に自分でハードウェアを作っていろいろ繋げる際のテストとか、シリアルポートの使い方を理解するのには最適である

●自分でプログラミングしてみる

 さて、ここからはC言語の知識が必要になる。さすがにC言語の解説までやってると原稿量が爆発するのでご容赦いただきたい。とりあえず簡単なところで

・LED1が高速(数回/秒)で点滅する
・LED2が低速(1回/2秒)で点滅する

といったプログラムを組んでみることにしたい。まずはCodeWarriorを単独で起動する(写真22)。デフォルトではWizardが立ち上がるので(写真23)、ここで“Create New Project”を選ぶ。まず基本設定(写真24)ではC言語を選び、プロジェクト名とディレクトリを入力する。CPUの選択では“HCS08QG Family”から“MC9S08QG8”を、Connectionは“P&E Multilink/Cyclone Pro”を選択する(写真25)。

 次は追加ファイルの設定(写真26)だが、新規に作るのだからここは何もなしである(写真26)。問題は次で、デフォルトではここが“None”になっているが、ここで“Processor Expert”を選ぶ必要がある(写真27)。次は言語環境だが、概ねデフォルトのままで良いだろう(写真28)。最後にLintを掛けるかどうかの質問が出てくるが(写真29)、とりあえず作るレベルだからNoのままでよいだろう。

 Wizardが終るとまずProcessor Expertが起動する。最初にCPUの選択が出てくるので、ここでは“MC9S08QG8_16”のみをチェックしておく。ついでProjectのビルドをどうするかの選択が出てくる。最終製品であればReleaseビルドのみなのだろうが、今はDebugビルドのみでよい。以上の設定が終ると、やっとCodeWarriorが立ち上がる(写真33)。

【写真22】CodeWarrior IDEが目的のメニュー 【写真23】Wizardを使いたくない場合は、一番下の“Start Using CodeWarrior”を選ぶ 【写真24】ディレクトリはLocation+Project名という構造。言語は色々選ぶとその分ランタイムが増えるので、必要な言語のみ選択するのが賢明
【写真25】これはほぼ決まりごと 【写真26】あらかじめ追加すべきソースファイルなどがあればここで指定するが、後からでも追加は可能 【写真27】Processor Expert自体は後で出てくる
【写真28】プログラムサイズがよほど大きくなるのでなければminimal startupとかTiny modelは必要ない。Floating Pointはまぁ普通必要ないだろう 【写真29】これはCodeWarriorで大規模システムを作っていた頃の名残ではないかと思う 【写真30】Processor Expertは要するにGUIを使ってCPUやI/Oの設定をすると、必要な初期化コードやCallback Routineのテンプレートを作成してくれるツール。お陰でデバイス初期化とかがえらく楽である
【写真31】要するにパッケージの違いでピンの本数などが変わってくるためにこの選択が必要になる 【写真32】Windowsの世界では、Debugビルドだと最適化を甘くしてソースとマシンコードの連携を取り易くするといった話が出てくるが、試した限りではそういうことはないようで、単にDebug用のスタブやシンボルテーブルを生成するか否かといった違いに見える。強いて言えばReleaseビルドにすると、BDM用のI/Oピンもプログラムに開放されるのが大きな違いだろう 【写真33】初期設定完了状態。16本のピンがどう使われているかがわかりやすく示される

 さて、まずはLEDの制御である。マニュアルによれば

ポート名 ピン
LED1 PTB6 6
LED2 PTB7 5

となっている。つまり6番ピン(ポート名PTB6)をHighにすればLED1が点灯、Lowにすれば消灯という仕組みだ。これはLED2も同じである。そこでまずはBean Selectorで“CPU Internal Peripherals”→“Port I/O”を選び、ここの“BitI/O”をダブルクリックすると、プロジェクトにそのBeanが追加されると共に、Inspectorに詳細設定が出てくる(写真34)。ここではBit1をLED1に割り当てる事にするので、“Pin for I/O”に“PTB6_SDA_XTAL”を(写真35)、“Direction”には“Output”を選択しておく(写真36)。同様にBit2も追加し、こちらは“PTB7_SCL_EXTAL”を割り当てる。こちらもやはり“Output”だ。

 これとは別に、一定期間で点滅させるためには、一定期間を通知するための方法が必要である。まずはLED2の方を考えよう。数秒に1回という目的だと、例えば1秒に1回ずつ割り込みを掛け、割り込みルーチンの中でON/OFFを切り替えれば良い。こうした場合にはTimerInterrupt(TimerInt)が有用である。Beans Selectorで“Timer”→“TimerInt”をダブルクリックし、これをプロジェクトに追加する(写真37)。これを使うと、指定した時間間隔毎に割り込みが掛かり、ISR(Interrupt Service Routine)が呼ばれる。で、時間間隔はBeans Inspectorの中で指定を行なう(写真38)。

 これでLED2は片付いたがLED1はどうするか? 残念ながら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のタイマー代わりに使うことにした。

 さて、以上でProcessor Expert周りの作業は完了である。この時点で一度Makeを掛けると、必要な初期化コードとコールバックのテンプレートを作成してくれる。

 生成されたコードがList1(Test.c)とList2(Event.c)である。

-------------------------------------------------------------------------------
List1:Test.c
-------------------------------------------------------------------------------
/** ###################################################################
** Filename : test.C
** Project : test
** Processor : MC9S08QG8CPB
** Version : Driver 01.09
** Compiler : Metrowerks HCS08 C Compiler
** Date/Time : 2006/08/31, 8:40
** Abstract :
** Main module.
** Here is to be placed user's code.
** Settings :
** Contents :
** No public methods
**
** (c) Copyright UNIS, spol. s r.o. 1997-2005
** UNIS, spol. s r.o.
** Jundrovska 33
** 624 00 Brno
** Czech Republic
** http : www.processorexpert.com
** mail : info@processorexpert.com
** ###################################################################*/
/* MODULE test */


/* Including used modules for compiling procedure */
#include "Cpu.h"
#include "Events.h"
#include "Bit1.h"
#include "Bit2.h"
#include "TI1.h"
#include "FC161.h"
/* Include shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"

void main(void)
{
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/

/* Write your code here */
/* For example: for(;;) { } */

/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END test */
/*
** ###################################################################
**
** This file was created by UNIS Processor Expert 2.97.01 [03.73]
** for the Freescale HCS08 series of microcontrollers.
**
** ###################################################################
*/

-------------------------------------------------------------------------------
List2:Event.c
-------------------------------------------------------------------------------
/** ###################################################################
** Filename : Events.C
** Project : test
** Processor : MC9S08QG8CPB
** Beantype : Events
** Version : Driver 01.02
** Compiler : Metrowerks HCS08 C Compiler
** Date/Time : 2006/08/31, 8:40
** Abstract :
** This is user's event module.
** Put your event handler code here.
** Settings :
** Contents :
** TI1_OnInterrupt - void TI1_OnInterrupt(void);
**
** (c) Copyright UNIS, spol. s r.o. 1997-2005
** UNIS, spol. s r.o.
** Jundrovska 33
** 624 00 Brno
** Czech Republic
** http : www.processorexpert.com
** mail : info@processorexpert.com
** ###################################################################*/
/* MODULE Events */


#include "Cpu.h"
#include "Events.h"

/*
** ===================================================================
** Event : TI1_OnInterrupt (module Events)
**
** From bean : TI1 [TimerInt]
** Description :
** When a timer interrupt occurs this event is called (only
** when the bean is enabled - "Enable" and the events are
** enabled - "EnableEvent").
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void TI1_OnInterrupt(void)
{
/* Write your code here ... */

}

/* END Events */

/*
** ###################################################################
**
** This file was created by UNIS Processor Expert 2.97.01 [03.73]
** for the Freescale HCS08 series of microcontrollers.
**
** ###################################################################
*/

 見ればわかるとおり、プログラムはTest.cの先頭から走り始め、そのままぐるぐる回っている。Test.cの最後が

/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

となっていることからわかる通り、要するに無限ループでぐるぐる回りっぱなしという代物だ。この部分は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_PutVal(~Bit1_GetVal()); でいいじゃないか」とか突っ込みが入りそうだが、Bit1_GetVal()がマクロで実装されてる関係で、これがあまり上手く動かないのでこんなコードとなった。Event.cの方も同様である。こちらはタイマーが勝手にタイミングを決めてくれるので、単にLED2のON/OFFをするだけだ。

-------------------------------------------------------------------------------
List3:Test.c(Modified)
-------------------------------------------------------------------------------

void main(void)
{
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* LED 1 brinking */
for(;;) {
Cpu_Delay100US(2000);
Bit1_PutVal(Bit1_GetVal()?FALSE:TRUE); /* Reverse LED1 status */
}

/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

-------------------------------------------------------------------------------
List4:Event.c(Modified)
-------------------------------------------------------------------------------

void TI1_OnInterrupt(void)
{
Bit2_PutVal(Bit2_GetVal()?FALSE:TRUE); /* Reverse LED2 status */
}

 このコーディングが終わったら、再びMakeを行ない、エラーがなければDebugを開始する。この手順は先ほどと同じであり、問題なければ点滅する(動画02)。

【写真34】左のプロジェクトツリーに“Beans”と“Bit1:BitIO”が追加されているのがわかる。左はそのBit1の設定 【写真35】1本のピンに複数の機能が割り当てられている関係で、ピン名がかなり長いが、要するにPTB6というポート名をあてている 【写真36】LEDは光るだけなのでOutputに設定する
【写真37】まだ割り込み周期を設定していないので、プロジェクトウィンドウでは“!”マークがついているのがわかる。指定すべき個所がわかりやすく示されるので、設定はやりやすい 【写真38】何も1,000msにしなくても1secでいいのでは?とか言われそうだが、まぁ気分の問題。厳密に言えばmsだとTimerの解像度が1段細かくなるので負荷がやや増える事になるが、そこまでクリティカルなものではないので、とりあえず指定

●工作の課題に向けて

 そんなわけで、ここまでは順調であった訳だが、ここからがいけなかった。とりあえず色々作れる目処は立ったが、DEMO9S08QG8ボード単体で出来ることには限界がある。夏休みの工作というからにはやはりもうひとひねりしないと、このまま出したら失格を食らうのは目に見えている。そこで「何かデバイスをつけないと」という事になる。

 最初は温度センサーとモーターコントローラでも入れて、PCのファンコントロールをUSB経由でプログラムから出来ないかとか思っていたが、MC9S08QG8がUSBで接続できないのでこの案は放棄。そういうわけで、上述のパーツ王国まで足を伸ばして色々見ていて見つけたのがこの超音波測距センサー(写真40)。浅草ギ研が同社のH8マイコンに接続するためのキットとして販売しているものだが、ぱっと見た限りDEMO9S08QG8ボードでも使えそうである。というわけで、早速購入。これだけだと接続がちょいと面倒なので、ユニバーサル基盤とピンヘッド(写真41)を千石電商で購入した。

 さて、まずは動作するかどうかの確認である。超音波測距センサーのページにも説明があるが、センサー自体は5V電源とGND、それにトリガー/信号ピン(以前はこれが別だったが今は一緒になっている)の3本の端子だけで構成されている。トリガー/信号ピンはTTLレベルだから、DEMO9S08QG8のI/O端子に直結しても問題はなさそうだ。で、DEMO9S08QG8の裏面に出ているI/O Port 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円。ド太いケーブルは、ジャンク箱の中に落ちてた電源配線用のものだが、もうすこし細いケーブル買ってくれば良かったと後悔。 【写真42】この表はDEMO9S08QG8 Users Manualからの抜粋。
【写真43】配線が余りに太すぎ。赤が+5V、黒がGND、黄色がトリガー/信号である。 【写真44】片方が発信、片方が受信である。で、音波が行き戻りする時間から距離を測定するというわかりやすい仕組み。 【写真45】この状態でハンダ付けすれば固定される。
【写真46】必要なのは1本だけなのだが、それだとあまりに機械的強度が乏しいので、全部で10本のピンヘッドを取り付ける。このうち1本(10番ピン:PTB6に接続)が超音波距離センサーのトリガー/信号に接続されている。 【写真47】USBはデバッグ専用で、単体動作時はACアダプタだけで動く。これを電池に切り替えて、適当なガワを作れば、一応工作らしい体裁は整うと目論んだ訳だ。

 さて、ここまでは順調(とかいいながら配線間違えたりしたので、実質1時間強掛かっている)だったが、問題はここからである。作るものとしては、連続的に(例えば毎秒10回とか)距離を測定し、ある閾値(例えば1m)以内だったらLEDを点灯するといったものを想定していた。最終的にはLEDの代わりに圧電ブザーなんかをつなげれば完璧というわけだ。その測距センサーの使い方だが、先の超音波測距センサーのページにもあるが

(1) 信号ピンがLowであることを確認
(2) トリガを5μs以上入れる
(3) 出力が立ち上がるのを待つ
(4) 立ち上がっている時間を測定する
(5) 測定時間から距離を算出して、LEDを点灯する

といった具合になる。このうち

・毎秒10回の部分は、TimerIntを使えば簡単に実現できる。
・LEDの点灯も既に実験済み。

というわけで、

(a) トリガを5μs以上入れる
(b) 立ち上がっている時間を測定する

の2つがネックになる。

 実はこれに必要な部品(CodeWarriorで言うところのBean)は既にある。ちょっと写真37に戻ると、FreeCnt8/16/32というBeanがあるのがわかるはずだ。これは8bit/16bit/32bitのカウンタで、解像度は最小1μsである。これを使うと例えばトリガを入れるのは

word StartTime, StopTime;

FC161_Reset();
FC161_GetTimeUS(&StartTime);
Bit1_SetVal(TRUE);
for (;;) {
FC161_GetTimeUS(&StopTime);
if ( StopTime - StartTime > 5 ) 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++/アセンブラ以外の開発環境はないから、これらに慣れていない人にはちょっと敷居が高いかもしれない。ただ逆にこのあたりが問題にならない人には、とてもよいオモチャになることを保証する。まぁ久々に楽しい日々であった。

□freescaleのホームページ
http://www.freescale.co.jp/
□製品情報(英語)
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MC9S08QG8

バックナンバー

(2006年9月1日)

[Reported by 槻ノ木隆]


【PC Watchホームページ】


PC Watch編集部 pc-watch-info@impress.co.jp ご質問に対して、個別にご回答はいたしません

Copyright (c) 2006 Impress Corporation, an Impress Group company. All rights reserved.