ArduinoでLチカ ~発展編~ その②


本記事について

前回作成した記事、ArduinoでLチカ ~発展編~ その①の続きとなります。
未読の方は先にこちらをご一読下さい。
前回の記事の途中で終わっていたプログラムの解説となります。

main関数の処理

main関数と言っていますが、Arduino界隈ではこれに相当するのがloop関数となります。
名前の通り無限ループですね。
ArduinoはOSを持たないマイコンボードなので電源入れたら書き込まれたプログラムを延々実行するだけの存在となるわけです。

title
void loop() {

  if(digitalRead(BTN1) == 1){
    delay(100);
    mode++;
  }

  switch(mode){
    case 1:
      u8x8.drawString(0, 0, "STANDBY!");
      u8x8.drawString(0, 2, "PUSH1BTN");
      ready();
      mode++;
      break;
    case 2:
      if(digitalRead(BTN1) == 1){
        u8x8.refreshDisplay();
        mode += 1;
        }
        break;
    case 3:
      u8x8.drawString(0, 0, "RECMODE!");
      u8x8.drawString(0, 2, "PUSH2BTN");
      btn_read(btn_push);
      u8x8.drawString(0, 0, "STOP!!!!");
      u8x8.drawString(0, 2, "PUSH1BTN");
      mode++;
      break;
    case 4:
      if(digitalRead(BTN1) == 1){
        u8x8.refreshDisplay();
        mode++;
        }
        break;
    case 5:
      u8x8.drawString(0, 0, "PLAYBACK");
      u8x8.drawString(0, 2, "LEDFLASH");
      u8x8.refreshDisplay();
      led_on(btn_push);
      u8x8.drawString(0, 0, "END.....");
      u8x8.drawString(0, 2, "PUSH1BTN");
      for (i = 0; i < (sizeof(btn_push)/sizeof(btn_push[0])); i++){
        btn_push[i] = 0;
      }
      mode = 0;
      break;
  }
  delay(500);
}

スイッチの状態を読み取る

loop関数では、モード切替用に割り当てたスイッチ(BTN1)の状態を無限ループで監視し、
ボタンが押されたら(1が帰ってきたら)
前回の記事にあったmode変数の値を+1します。

mode変数の値をswitch文で判定し、モードを変更するという仕組みです。

電源が入った直後のmode変数の値は0です。(変数宣言時に値を0にしています)
一度BTN1を押すとmode変数が1になり、mode = 1の処理(case 1:)に移行します。

case 1:の処理でready()関数を呼び出す、つまり待機モードに移行するわけですね。

ちょいちょい出てくる
u8x8.drawString(0, 0, "RECMODE!");
u8x8.drawString(0, 2, "PUSH2BTN");

こいつらは、現在のモードが何なのか、わかりやすくするためにprintf()してるととらえておいてください。
(ライブラリにお願いしてディスプレイに文字列を出力しています)

待機モード(ready())が終わったらmode変数をまた+1します(mode = 2になる)

待機状態を挟む

モード遷移を実装する上で重要なのは次のcase 2:の処理を挟むことです。

私は初め
mode = 1なら待機モード
mode = 2なら記録モード
mode = 3なら点灯モード

と記述していたのですが、これだと
mode = 1の待機モードが終わったタイミングでmodeをインクリメントするので
勝手にmode2の処理が始まって意図した動作をしませんでした。
少し考えたら気づく事だと思いますが、初心者ってこういうところでハマるんす・・・

title
case 2:
      if(digitalRead(BTN1) == 1){
        u8x8.refreshDisplay();
        mode += 1;
        }
        break;

このように、ボタン入力を待って入力があったらmode++してあげれば
次のモードに無事遷移できるわけです。

あとはBTN1が押されるたびにmode変数が変化し、
btn_read(btn_push)
led_on(btn_push)
がそれぞれ呼び出されて記録したり点灯したりする、というわけです。

初期化するよ

case :5の処理で、led_onの関数終了後、

title
 for (i = 0; i < (sizeof(btn_push)/sizeof(btn_push[0])); i++){
        btn_push[i] = 0;
      }
      mode = 0;
      break;

こちらの記述でbtn_push[120]内にbtn_read関数で放り込んだ大量に並んだ0と1の値を
全部0に書き換えます。
そしてmode変数も0の戻します。

もう一度BTN1を押すと待機モードに戻り、同じ動作を繰り返すことができます。
これにより電源が入っている限り、何度でも遊べます。

これにて完成!!

ガビガビ画質のgifで伝わりにくいですが・・・
完成品はこんな感じで動きます。
ポチポチボタン押した通りにLチカする!ちゃんと覚えててえらい!

今回の工作に液晶ディスプレイは無くてもいいのですが
プログラミングの勉強してるとコンソールに文字とか出力しますよね?
それがPCの外の世界で表示されると、なんだか作った感があって嬉しくなるので実装しました。

ライブラリ放り込んでるだけなので今回は触れませんでしたが、もう少し勉強してディスプレイの仕組が語れるようになったら解説できればとおもいます。

最後に電源切れてるのは、電源にしたモバイルバッテリーが力尽きたせいです(持ち運べるようにしたかったのさ)

 終わりに

予想外に長ったらしい記事になってしまいましたが、ここまでお読み頂きありがとうございます。

プログラミングを初めてまだ初学者の域を抜け出せていませんが、自学の振り返りや、同じようなことで苦しんでる方のヒントになるような記事として活用出来ればと思っています。

もしこの記事に行き着いた先輩プログラマの方々には
大変恐縮ですが記事の内容の間違いやアドバイスなど頂ければ幸いです。