DEMO9S08QG8評価ボードにタクトスイッチを拡張して、 キーボードを作ってみましょう。 まずは、半音の無いものからはじめます。 Processor Expertを使います。
このアプリケーションは、 DEMO9S08QG8評価ボードに圧電スピーカと抵抗、 それにタクトスイッチ9個を拡張して製作します。
アプリケーションに必要な部分の回路は、 以下のようになっています。
マイコンの以外のすべての部品が拡張部分です。 必要な部品は、以下の通りです。
品名 | 型番 | 個数 | 調達先 |
---|---|---|---|
評価ボード | DEMO9S08QG8 | 1 | Freescale |
ブレッドボード | EIC-801 | 1 | 秋月電子 |
抵抗 | 2.7kΩ 1/6W | 1 | - |
圧電スピーカ | - | 1 | 梅澤無線 |
両端オスピンソケット | 6604P-20G-121 | 2 | 秋月電子 |
20芯フラットケーブル | - | 25cm | - |
20Pフラットケーブルコネクタ | - | 2 | - |
片面ガラスエポキシユニバーサル基板 | 95mm×72mm | 1 | 秋月電子 |
ピンヘッダ | 1×10 | 2 | 秋月電子 |
タクトスイッチ | - | 9 | 秋月電子 |
拡張部分は、ユニバーサル基板とブレッドボードに作りました。
このアプリケーションは、 ユニバーサル基板にタクトスイッチを配置したキーボード基板と DEMO9S08QG8評価ボードを 圧電スピーカと抵抗を配置したブレッドボードに接続して 構成しています。
ご覧のように、ブレッドボードは、評価ボードとキーボード基板および 圧電スピーカとの間の信号交換にしか使っていません。
このステップでは、 キーボード基板にはタクトスイッチしか配置していませんが、 別の製作記事でマイコンと圧電スピーカと電池を取り込んで 独立したアプリケーションに仕立てる計画です。 お楽しみに。
このアプリケーションで入力装置として使用しているのは、 押しボタンスイッチの一種であるタクトスイッチです。 このスイッチには二つの電極があり、 押すとつながり、放すと切れるという簡単な構造になっています。
このスイッチをマイコンの入力端子に一つずつ接続します。 回路図には現れませんが、 マイコン内部には切り離し可能なプルアップ抵抗が内蔵されており、 下の図のようにしてスイッチのON/OFFを検出します。
スイッチを押すと、左の図の矢印のように電流が流れます。 そのため、マイコン内部の入力バッファは、低い電圧を検出し、 "0"信号が入力されたと判定します。
スイッチを放すと、右の図の矢印のように電流が流れますが、 電流が流れて行く先が無いため、 入力端子がVDDの電圧まで上昇すると 電流はとまります。 そのため、マイコン内部の入力バッファは、高い電圧を検出し、 "1"信号が入力されたと判定します。
まず、最初にブレッドボードの準備をします。
評価ボードには、2×16構成のコネクタが搭載されています。 このコネクタの奇数番のみを用いてブレッドボードと接続します。 コネクタの詳細は、太陽計の製作記事をご覧ください。
接続する位置は、ブレッドボードの下の端にある 1番から16番までの穴です。
キーボード基板には、1×10構成のピンヘッダを配置し、 20芯フラットケーブルの一列だけを使ってブレッドボードとつなぎます。
接続する位置は、ブレッドボードの上から二段目の 4番から13番までの穴です。
ブレッドボードでは、 評価ボードとキーボード基板との間の配線を行います。 さらに圧電スピーカと抵抗を配置し、評価ボードと接続します。
次にキーボード基板を用意します。
ユニバーサル基板にタクトスイッチを並べます。 実は、厳密にはタクトスイッチの端子の間隔は ユニバーサル基板の穴の間隔(0.1インチ)の倍数には なっていません。
そのため、ユニバーサル基板にタクトスイッチをそのまま差し込むと 端子に無理な力がかかって破壊する可能性があります。 また、破壊にまで至らなくても、 スイッチが傾いて取り付けられると見た目の美しさを損ないます。
そこで、ユニバーサル基板に差し込む前にあらかじめ端子を 整形してやります。 タクトスイッチは、最初は下の写真のように足が曲がっています。
この足をラジオペンチで挟んで開いてやります。
写真の左側の二本の足が開かれています。 右の未加工の足と比べると良くわかると思います。 左右両方の足を開いたら、ユニバーサル基板に差し込みます。
タクトスイッチの足を開いても、 ユニバーサル基板の穴の間隔よりも多少狭いため、 差し込んだだけでは写真のように傾斜してしまいます。 そこで、タクトスイッチの肩の部分を押して基板に密着させます。
この時に決して基板の裏側から足を引っ張ったりしないでください。 足を引っ張ると抜けてしまう可能性があります。
9個のタクトスイッチを色の順番に並べます。
次にピンヘッダを配置します。
評価ボードは、ボードに実装されたコネクタで ブレッドボードと接続します。 また、キーボード基板は、20芯のフラットケーブルで ブレッドボードと接続します。
ハードウェアができたらソフトウェアを作りましょう。 でも、その前にどんなソフトウェアにするか確認しておきます。
基本的なコンセプトは、 「キーを押したら音が鳴る」ことです。 ただ、どのキーを押しても同じ音が鳴るのでは、 キーボードになりませんから、 どのキーが押されたか判断してキーによって異なる音程の音を出す 機能が必要です。
そこで、どのキーを押したらどんな周波数の音を出すかを決めます。 キーは、全部で9個あり、回路図上に名前をつけてあります。 このキーに対して音階を以下のように割り当てます。
キー | ポート | 音階 | 周波数(Hz) |
---|---|---|---|
SW9 | PTB7 | ド | 523 |
SW8 | PTB6 | レ | 587 |
SW7 | PTB5 | ミ | 659 |
SW6 | PTB4 | ファ | 698 |
SW5 | PTB3 | ソ | 784 |
SW4 | PTB2 | ラ | 880 |
SW3 | PTB1 | シ | 988 |
SW2 | PTB0 | ド | 1047 |
SW1 | PTA1 | レ | 1175 |
周波数は、「ラ」の音を基準にした平均率音階になっています。 これで、安心してソフトウェアにとりかかることができます。
プログラムの開発には、CodeWarriorを使います。 CodeWarriorでは、 一つのプログラムの単位を「プロジェクト」と呼んでいます。 ここでは、新規にプロジェクトを作成します。 ここでは、V5.0を使って説明します。
スタートメニューからCodeWarriorを起動するとCodeWarriorが起動します。
初めてCodeWarriorを起動したときには、 下のような"Startup"ダイアログが出てきますが、 今はこのダイアログは使用しませんので、 をクリックしてダイアログを閉じます。
この後、"Tip of the Day"ダイアログが出てくるかも知れませんが、 これも をクリックして閉じてしまいましょう。
メニューから"File → New Project..."を選ぶと、 "HC(S)08 New Project"ダイアログが開きます。 まずは、"Project Parameters"(プロジェクトのパラメータ)を設定します。
使用する言語に"C"を選び、 プロジェクトを作成する場所を設定します。 この例では、"C:\Projects\CW\Organ1"というディレクトリに "Organ1.mcp"というプロジェクトファイルを作成しています。 設定を終えたら、「次へ」をクリックします。
画面が変わって、 "Device and Connection"(デバイスと接続方法)の設定に移ります。
デバイスには"HCS08 → HCS08QG Family → MC9S08QG8"を選び、 デフォルトの接続方法には"P&E Multilink/Cyclone Pro"を選び、 「次へ」をクリックします。
3枚目の画面は、 "Add Additional Files"(追加するファイル)の設定です。 プロジェクトで使用するソースコードなどがあれば、 ここで設定します。
今回は、追加するファイルはありませんので、 そのまま「次へ」をクリックします。
4枚目の画面は、 "Processor Expert"(プロセッサエキスパート)の設定です。
"Processor Expert"を選んでこの機能の使用を宣言します。 さらに、「次へ」をクリックします。
5枚目の画面は、"C/C++ Options"の設定です。
すべて、デフォルトのままの設定にします。
startup code | ANSI |
memory model | Small |
floating point format | None |
設定を確認して 「次へ」をクリックします。
最後の画面は、"PC-Lint"の設定です。 PC-lint™というのは、 プログラムの書式を検査するためのプログラムです。 今回は使用しません。
"No"をチェックして 「完了」をクリックすると、 新規プロジェクトの作成が始まります。
MC9S08QG8マイコンには、 いくつかの異なる種類のパッケージが存在します。 その中から、今から使おうとしているパッケージが どのパッケージなのかを指定するのが次のウィンドウです。
今回は、評価ボードに搭載されている 16PIN-DIPパッケージを使いますので、 "MC9S08QG8_16"だけを選択して「OK」をクリックします。
これが、新規プロジェクトのための 最後の設定です。 "Select Configurations"(設定を選べ)というのは、 実にあいまいですが、 ここでは、アプリケーション開発の結果を何に使うかを指定します。 もちろん、独立した製品に仕上げるのが最終目的には 違いないのですが、 プログラムの開発中には、デバッガを接続した状態で プログラムを実行する必要もあります。
"Debug"設定は、このようなデバッガを接続した状態を考慮した 設定を行います。 このため、BKGD端子には、デバッガが接続されアプリケーションでは 使用できなくなります。
一方、"Release"設定は、最終製品での使用を考慮した設定を行うため、 すべての端子がアプリケーションに開放されます。
今回は、デバッグ環境である評価ボードでアプリケーション開発を 行いますので、 "Debug"だけを選択して「OK」をクリックします。
以上で、プロセッサエキスパートを使用する 新規プロジェクトができました。
ここから、 プロセッサエキスパートのプロパティを設定していきます。 ここでは、設定箇所だけ示します。 設定方法の詳細は、三値デジタル太陽計を参照ください。
キーは、PORTBとPORTAにまたがって配置されています。 一つ一つのキーをBitIOビーンで定義することもできますが、 ここでは、PORTBをByteIOビーンで定義し、 PTA1をBitIOビーンで定義します。
PORTBには、ByteIOビーンを割り当てます。 "Bean Selector"から "CPU Internal Peripherals → Port I/O → ByteIO"を ダブルクリックで呼び出したら、 以下の項目を設定します。
項目名 | 設定する値 |
---|---|
Port(ポート) | PTB |
Pull Resitor(プル抵抗) | pull up(プルアップ) |
Direction(方向) | Input(入力) |
最終的に属性は以下のようになります。
PTA1には、BitIOビーンを割り当てます。 "Bean Selector"から "CPU Internal Peripherals → Port I/O → BitIO"を ダブルクリックで呼び出したら、 以下の項目を設定します。
項目名 | 設定する値 |
---|---|
Pin for I/O(入出力ピン) | PTA1_KBIP1_ADP1_ACMPMINUS |
Pull Resitor(プル抵抗) | pull up(プルアップ) |
Direction(方向) | Input(入力) |
最終的に属性は以下のようになります。
このアプリケーションでは、 タイマチャネル0が接続されたPTA0から音を出力します。 音を出すときに使用するのがPPGという機能です。
まず、"Bean Selector"から "CPU Internal Peripherals → Timer → PPG"を ダブルクリックで呼び出したら、 以下の項目について設定します。
項目名 | 設定する値 |
---|---|
Output pin(出力端子) | PTA0_KBIP0_TPMCH0_ADP0_ACMPPLUS |
Period(周期) | 1ms |
Starting pulse width(最初のパルス幅) | 0.5ms |
最終的に属性は以下のようになります。
ここで設定した周期は、ダミーです。 プログラムが実行されるとすぐに書き換えられます。
このアプリケーションでは、PPGの出力を出したり止めたりする 必要があります。 この出したり止めたりする機能を持ったメソッドは、 Processor Expertによって準備はされていますが、 標準状態では、コードが生成されません。 そのため、メソッドのコード生成を行わせるための設定が必要になります。
まず、画面左の"Project Panel"の "Beans → PPG1:PPG"を開きます。 ここには、使用可能なメソッドの一覧があります。 この中から"Enable"メソッドを右クリックしてコンテキストメニューを呼び出し、 "Enable"(有効化)を選びます。
すると、"Enable"メソッドのアイコンが、 メソッドが使用可能であることを示す緑のチェックになります。 同様に"Disable"メソッドも"Enable"します。
以上で必要なビーンの宣言は終わりました。
プロセッサエキスパートの設定が終わったら、 プログラムのコーディングを行います。
CodeWarriorのウィンドウの左側にあるプロジェクトペインの ボタンを クリックして、ソースコードを生成させます。
コード生成では、"Organ1.c"というファイルも同時に生成されています。 左端の"Project Panel"ウィンドウに"Organ1.c"というファイルが見えます。
このファイルには、 マイコンがリセットされた後で実行される "main()"関数が記述されています。 ここをダブルクリックすると、 "Organ1.c"ファイルを編集するテキストエディタが開きます。
まずは、このファイルにキー入力を行う関数を定義します。
どうです。 簡単でしょ。
この"getKey(void)"関数は、 押されたキーに対応するbyte型のコードを 返すように作られています。
byte getKey(void) { : }
コードは、左端のスイッチから順に1から9までの数値が割り当てられます。 if文の行列が押されたスイッチを探す部分です。
if (Byte1_GetBit(7) == FALSE) return 1; if (Byte1_GetBit(6) == FALSE) return 2; if (Byte1_GetBit(5) == FALSE) return 3; if (Byte1_GetBit(4) == FALSE) return 4; if (Byte1_GetBit(3) == FALSE) return 5; if (Byte1_GetBit(2) == FALSE) return 6; if (Byte1_GetBit(1) == FALSE) return 7; if (Byte1_GetBit(0) == FALSE) return 8;
最初に調べられるのはPTB7につながったスイッチです。 このスイッチの状態を知らせるのが Byte1_GetBit(7)関数(メソッド)で、 引数の"7"は、調べるポート番号を示します。 もし、スイッチが押されていたら、 この関数は、FALSEを返します。 もし、FALSEが返されたら そのキーに対応するコードを返します。 たとえば、PTB7につながっている左端のスイッチが押されていたら、 "getKey(void)"関数は、"1"を返します。 以下、PORTBのすべてのスイッチについて検査します。
if (Bit1_GetVal() == FALSE) return 9;
次に検査されるのは、PTA1につながったスイッチです。 "BitIO"ビーンの場合には、 Bit1_GetVal()というメソッドを使います。 この関数は、FALSEを返します。 もし、FALSEが返されたら そのキーに対応するコード、ここでは"9"を返します。
return 0;
また、どのキーも押されていなければ、 "getKey(void)"関数は、"0"を返します。
まず、"getKey(void)"関数のテストを行います。 テストを行うために、以下のようなプログラムを用意します。
byte code; // Key code value.
for (;;) { code = getKey(); }
ご覧のように、テストプログラムは簡単です。 "getKey(void)"関数から値を受け取って変数に入れる動作を 無限ループで延々と繰り返すだけです。 表示も何もしていないのは、 受け取った値をデバッガから読み込もうとしているためです。
テストを行うためにマイコンにプログラムを書き込みます。
DEMO9S08QG8評価ボードをUSBケーブルで接続します。
ドロップダウンリストが"P&E Multilink/Cyclone Pro"になっているのを 確認して、 アイコンを クリックするとコンパイル、リンクの後、デバッガが立ち上がります。
USBインターフェースの設定を確認したら、 "Connect"をクリックします。
「Yes」をクリックして、マイコンに書き込みます。
ツールボタンの ボタンを クリックするとマイコンは自律走行を始めます。 ですが、この状態では、キーをいくら押しても何も反応が返ってきません。 反応を確認するにはどのようにしたら良いでしょうか。
このデバッガには、変数をリアルタイムに観測する機能があります。 変数が表示されるのは、"Data:1"という名前のついたサブウィンドウです。
このサブウィンドウの中で右クリックすると コンテキストメニューが現れます。
このメニューから"Mode → Periodical..."を選択すると "Update Rate"(更新頻度)というウィンドウが開きます。
この数値を小さくすると、 変数の変化を頻繁に検査してくれます。 ここでは、デフォルトの"10"を指定して、"OK"ボタンをクリックします。
すると、"Data:1"ウィンドウは、定期的に更新されるようになります。 上の図は、左から4番目のキーを押したときの表示です。 赤い色は、前回表示した値から変更があったことを示しますから、 変化の様子がよくわかります。
このリアルタイム観測機能を使って、 キーと"code"変数の関係を確認したら、 キー入力関数のテストは終了です。
キー入力関数が出来たので、 今度は、キーのコードにしたがって音を出す関数を作ります。
音出力関数は、以下のようになっています。
ちょっと、長いですか?
音出力関数では、与えられたコードに従って、 音階を選び"PPG"を設定します。 この設定で使用されるのは、音の周期なので、 それぞれのコードに対応する周期をテーブルにしておきます。
const word period[] = { 0, 4000000 / 523, // DO 4000000 / 587, // RE 4000000 / 659, // MI 4000000 / 698, // FA 4000000 / 784, // SO 4000000 / 880, // RA 4000000 / 988, // SI 4000000 / 1047, // DO 4000000 / 1175 // RE };
このテーブルでは、周期をマイコンのバスクロック数で表現しています。 そのため、マイコンのバスクロック周波数を音階の周波数で割った値を 計算させてテーブルに格納しています。 このテーブルは、constで宣言されているので、 ROM上に展開されます。
インデックス"0"の値は、キーのコードが"1"から始まっている ためのダミーであり、実際には使用しません。
"playSound(byte)"関数は、与えられたキーコードに対応する音の周期を "PPG"に設定します。
void playSound(byte code) { : }
処理は、"code"が"0"であるか否かによって二つに分かれます。
if (code == 0) { : } else { : }
まず、"code"が"0"の場合、 どのキーも押されていないことを示しますので、 "PPG"の波形を停止させます。 これには、PPG1_Disable()メソッドを使います。
(void)PPG1_Disable();
このメソッドは、その内部で"PPG"の動作状態を把握する機能を 持っているため、 "PPG"が停止している状態で呼び出されても正しく動作します。
次に"code"が"0"でない場合、 いずれかのキーが押されたことを示しますので、 音の周期を設定して、 PPG1_Enable()メソッドで"PPG"を動作させます。
TPMC0V = period[code] / 2; TPMMOD = period[code]; (void)PPG1_Enable();
ここで、メソッドではない記述が現れます。 "TPMC0V"と"TPMMOD"は、タイマモジュールのレジスタを意味します。 本来であれば、"Processor Expert"が準備したメソッドを呼び出して 音の周期を決定するのですが、あいにく、それらのメソッドを使用するための ライセンスは、無償版では提供されていません。 そのため、苦肉の策として、直接タイマモジュールのレジスタを 操作しています。
PPG1_Enable()メソッドも、 その内部で"PPG"の動作状態を把握する機能を持っているため、 "PPG"が動作している状態で呼び出されても正しく動作します。
これで、キー入力をする関数と音を出す関数が揃いましたので、 これらの関数を呼び出してデータを引き渡すメイン関数を 準備します。
キーコードを受け取る部分は、 すでにキー入力関数のテストで使いましたから、 必要なのは、キーコードを"playSound(byte)"関数に渡す プログラム一行の追加だけです。
playSound(code);
これで、キーコードをもとに音を出力する事ができます。
プログラムが完成したら、いよいよ自律制御をさせます。
アプリケーションの実行のために マイコンにプログラムを書き込みます。
DEMO9S08QG8評価ボードをUSBケーブルで接続します。
ドロップダウンリストが"P&E Multilink/Cyclone Pro"になっているのを 確認して、 アイコンを クリックするとコンパイル、リンクの後、デバッガが立ち上がります。
USBインターフェースの設定を確認したら、 "Connect"をクリックします。
「Yes」をクリックして、マイコンに書き込みます。
ツールボタンの ボタンを クリックするとマイコンは自律走行を始めます。 キーを押すとキーに対応した音が出てきます。 これで完成です。
キーを押すと微妙に音程が動いてしまいます。 詳しい原因は不明ですが、 おそらくキーのチャタリングなどが発生して 周期が激しく変化するためであろうと推定しています。
これを防ぐには、キーに対する反応速度を落としてやると 頻繁に周期が変化することはなくなるでしょう。
このアプリケーションでは、9個の音階しか出すことができません。 もっと多くの音階を出すためには、もっと多くのスイッチが 必要ですが、MC9S08QG8には、そんなに多くのスイッチをつなぐ端子は 残っていません。 さて、どのようにしたらもっと多くのスイッチをつなぐことができるように なるのでしょうか。
2006-03-01 発行。
2006-06-15 XHTML版発行。