スイッチの仕様を考え、プログラムに落とし込もう!マイクロマウスで始める組み込み開発入門(7)(2/3 ページ)

» 2012年11月02日 12時50分 公開
[三月兎MONOist]

スイッチの動作を考える

 Pi:Co Classicの状態をユーザーに知らせる方法は、2つ考えられます。1つは、LEDの点灯、もう1つはブザー音です。ここでは、前回覚えたLEDの点灯とスイッチを組み合わせて、ユーザーに選択モードを知らせる方法を採用します。

 それでは、スイッチとLEDをどのように組み合わせたら、使い勝手の良いシステムになるでしょうか。以降で検討してみましょう。

 Pi:Co Classicには、前方に4個のLEDが搭載されています。この場合、LEDの点灯パターンで2進数を表示するのが“電子工作の王道”です。2進数なら、0〜15までを表示できますね。全LEDが消灯している「0」を除き、1〜15をモード表示としましょう。

  • 「スイッチ1」を押すたびに、LEDが点灯/消灯し、2進数の1〜15を順に表示する
  • 「スイッチ2」を押すと、表示されている“モードn”のプログラムを実行する

 では、「スイッチ3」には、どんな役割を持たせましょうか? 「スイッチ2」を実行A、「スイッチ3」を実行Bとすれば、15×2で30個のモードを搭載できます。そんなにたくさんのモードが必要ないのであれば、「スイッチ3」を2進数の減算に使うこともできます。「スイッチ1」の動作を、1→2→……→15→1→2→……とした場合、スイッチをうっかり押し過ぎて目標の数字をオーバーしてしまうと、やり直しが面倒ですね。「スイッチ3」で減算できれば、使いやすくなります。

 「いやいや、モードは30個必要! でも、ユーザーインタフェースとして減算もほしい!!」――そんな要求があったら、どうしますか?

 その場合、「スイッチ3」を“シフトキー”とするのも1つの案です。

スイッチ1:モード選択(インクリメント) 
スイッチ2:実行A

スイッチ3+スイッチ1:モード選択(デクリメント) 
スイッチ3+スイッチ2:実行B

 こうすれば、要求仕様をかなえることができます。

 そして、もう1つ検討すべきなのは「どのスイッチに、どの機能を割り当てるのか?」です。

 「実行」スイッチは、“青はススメ”のイメージで青にしましょうか? でも、それだと、モード選択が2つ並んでしまいます。それぞれのスイッチに人差し指、中指を乗せると、押しにくくないでしょうか? 指は1本しか使わないから、スイッチが並んでいても問題はないでしょうか? そもそもスイッチが並んでいると、間違いやすくはないでしょうか?

 世の中に出回っている全ての製品は、スイッチの配置だけではなく、色や形状にも意図があります。使いやすい製品もあれば、使用するたびに小さな違和を感じる製品もあります。その違いは何から生じるのでしょうか? 日ごろから、そうした意識を持って身の回りを観察していると、モノづくりをする際に必要なセンスが磨かれると思います。

北上

えみちゃんは、どのスイッチに、何の機能を割り当てたい?


えみ

えっと〜。モードは15個もあれば、十分かなと思いますね。

30個作ってもきっと覚えられないでしょうしぃ〜。


北上

ふむふむ。


えみ

で、真ん中の黄色のスイッチを「実行」に使いたいですね。

何て言うかぁ〜、中心にあると「GO!」って気がしません?


北上

いいんじゃない。

となると、加算・減算スイッチを両端に分けるんだね。


えみ

はい! その方が、スイッチの押し間違いが減るんじゃないかなって思います。

右端の青を加算、左端の赤を減算にしたいですね。


北上

OK! いいと思うよ。


えみ

やった! 正解ですか?


北上

いや。こういうのって、正解は1つじゃないんだよ。だから基本的に、えみちゃんのセンスで決めればいいんだよね。

「ただ、何となくぅ〜」じゃなくて、“なぜ、そうしたいのか”、自分なりの理由があることが大切だよ。


えみ

えへっ!!


北上

じゃあ、その仕様でプログラムを組んでいこう!!


えみ

ハイッ!!



スイッチの制御プログラムはカンタン!?

 それでは、スイッチを制御するプログラムを作りましょう。えみちゃんが考えたスイッチの動作は、以下のような仕様になります。

  • モードは1〜15を用意
  • LEDの点灯で、モードの選択状況をユーザーに明示
  • 「青」スイッチ:加算。1〜15を表示。「15」の次は「1」に戻る
  • 「黄」スイッチ:実行。表示されているモードを実行する
  • 「赤」スイッチ:減算。15〜1を表示。「1」の次は「15」に戻る

 プログラミングを始める前に、スイッチを制御するのに必要な情報を、マニュアルの「基板ポート一覧」と「回路図」から取得しておきましょう。タクトスイッチと書かれているPB1〜PB3が該当のスイッチです。

基板ポート一覧 表1 基板ポート一覧(PiCo:Classic 取扱説明書_ver1.08.pdfより抜粋)
STK-7125回路図 画像2 STK-7125回路図のプッシュスイッチ部分
プッシュスイッチの回路図 画像3 プッシュスイッチの回路図

 マイコンプログラムで、スイッチの状態を取得するには、該当するポートを入力に設定し、ドライバ関数内でreturnするだけでOKです。

 では、前回と同じ要領で、スイッチを制御する関数を書いていきましょう。

 まず、I/Oポート初期化関数に、スイッチのポートを追加します(ソースコード1)。

void init_io(void)
{
    //スイッチ
    PFC.PBIORL.BIT.B1    = 0;    //PB1を入力に設定(青)
    PFC.PBIORL.BIT.B2    = 0;    //PB2を入力に設定(黄)
    PFC.PBIORL.BIT.B3    = 0;    //PB3を入力に設定(赤)
 
    //LED
    …… 以下略(前回記述) ……
}
ソースコード1 「init.c」内のI/Oポート初期化関数に、スイッチのポートを追加する。ポートの初期値は「0」なので、このソースコードを書かなくても動作に影響はない

 続いて、「common.h」内にスイッチオンの状態を定義します(ソースコード2)。Pi:Co Classicの場合、スイッチが押されていないとき、ポートの電位は“1(High)”、スイッチが押されるとポートはグランドに接続され、電位は“0(Low)”になります。ですから「SW_ON」を“0”で定義します。

//SW ON
#define SW_ON    0    //SW ON
ソースコード2 呼び出し側、実行側で同じ定義を使用するものは、「common.h」内に記述する

 そして、「drv.h」内にスイッチの各ポートの名前を定義し(ソースコード3)、「drv.c」内に記述した関数でポート名を取得すれば、スイッチの状態を読み取ることができます(ソースコード4)。

//スイッチポート
#define SW_BLUE    PB.DR.BIT.B1    //青スイッチ
#define SW_YELLOW    PB.DR.BIT.B2    //黄スイッチ
#define SW_RED    PB.DR.BIT.B3    //赤スイッチ
ソースコード3 「drv.h」内にスイッチのポートを定義する

unsigned char drv_sw_b(void)
{
    //スイッチドライバ(青)
    //スイッチを読み込む
    return SW_BLUE;
}
ソースコード4 「drv.c」内に、スイッチの状態を読んで返す「drv_sw_b」関数を作成。赤、黄スイッチも同様に記述する

 「ctrl.c」内には、3つのスイッチの状態を一度に取得する関数を記述します。この関数では、最初に押されたスイッチが常に優先されています(ソースコード5)。

void ctrl_sw_all(unsigned char *o_sw_b,
         unsigned char *o_sw_y,
         unsigned char *o_sw_r)
{
    //スイッチ処理(一括)
    *o_sw_b = drv_sw_b();        //青スイッチ
    *o_sw_y = drv_sw_y();        //黄スイッチ
    *o_sw_r = drv_sw_r();        //赤スイッチ
    //どれかのスイッチがONならば、全てのスイッチがOFFになるまで待つ
    if (*o_sw_b == SW_ON || *o_sw_y == SW_ON || *o_sw_r == SW_ON)
    {
        while(drv_sw_b() == SW_ON || drv_sw_y() == SW_ON || drv_sw_r() == SW_ON);
    }
}
ソースコード5 3つのスイッチの状態を読み込む関数。最初に押されたスイッチの値がSW_ONで返る

北上

よし、これでスイッチの制御ができるよ。


えみ

スイッチの制御って、押されているか? いないか? を判断するだけだから、すごーくカンタンですね!


北上

そうだねぇ〜(ニヤリ)。

じゃあ、スイッチを押したらLEDを2進数表示する関数を作ろうか。


えみ

はいっ!!



Copyright © ITmedia, Inc. All Rights Reserved.