予告と毎回やることが違いますが、今回はいよいよプログラミング編最後の「プログラムを記憶させる」部分をスタートします。
基板は完成しましたが、スイッチは配線で接続するのでケースに組み込む段階で発表しようと思います。
プログラムモードをどう表示するかを検討する。
当初から考えていたのは、LCD1602を使うことでした。
しかし、未定義の表示は「プログラムセットモードかそうで無いか」だけなのです。
そこで取り合えず、以前の記事で使った、Arduinoに最初から載っているLEDを使用します。
注意点としては、LED_BUILTIN
は、正論理です。
スイッチの長押しの仕組み。
現在の短押しの仕組みのおさらい。
↓
スイッチを離した瞬間に検知する。
↓
検知した瞬間にプログラムを止める。(チャタリングを読み込まないため)
↓
やるべき処理を実行する。
↓
現在の状態を一つ前の状態にコピーする。
これを改造したいところですが、「離した瞬間にそれが長押しだったかどうかを調べる」というやり方では、例えば1秒以上が長押しだったとして、0.99秒ならアウトになるわけですので、二度手間です。
そこでこのように考えます。
長押しの仕組みを考える。
例えばですがこういうのはどうでしょうか?
↓
ボタンを押しっぱなしの間カウンターは増えていく。
↓
長押し時間として予め決めた回数カウントアップしたら「長押し」と判定する。
↓
やるべき処理を実行する。
↓
カウンターをクリアする。
もし、長押し時間回数以下でスイッチから手を離したら
↓
カウンターをクリアする。
では一旦これで試します。
長押ししてPRGset関数へ飛ぶ。
直接関係ある部分だけ記述します。
//sw6 //プログラムセットモード実装 //抜粋 const int SW5 = A5;//プログラムセットボタン unsigned int count = 0; // 1周ループしたら+1 unsigned int swcount = 0; // 1周ループしたら+1 void setup() { pinMode(SW5, INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); } void loop() { a = count % 4; sw(a); count = count + 1; //mode切り替え処理 val[4] = digitalRead(SW4); //スイッチの状態をval[num]に入れる if ((val[4] == 1) && (old_val[4] == 0)) { delay(10);// 10ms待つ。 if (mode == 1) { mode = 0; } else { digitalWrite(LED[4], HIGH); digitalWrite(LED[5], HIGH); digitalWrite(LED[6], HIGH); digitalWrite(LED[7], HIGH); mode = 1; } } old_val[4] = val[4]; //SW5長押しでPRGsetモードへ。 if (!(digitalRead(SW5))) { swcount = swcount + 1; if (swcount >= 50000) { PRGset(); } } else { swcount = 0; } } void PRGset() { while (1) { digitalWrite(LED_BUILTIN, HIGH); } }
swcount
という変数を立てて、一周回る度にカウントアップしています。
前回、countで体験したように、データ型はunsigned int(0-65535の整数)にしました。
長押しでPRGset関数に飛び、その中で無限ループを繰り返します。
ここで、試していただくとわかりますが、マニュアルモードのときの長押し時間と、プログラムモードのときの長押し時間が違います。
(マニュアルモードのときのほうが長い)
プログラム一周でswcountは+1されていきますが、通るルートが違うために、一周の時間が違うために起きます。
今回の場合は実用上支障がないのでこのままにしておきます。
PRGset関数からメインループに戻る。
では同様に、PRGset関数から抜けるのもSW5ボタンの長押しでやることにします。
ここで気をつけるのは、メインループから長押しをしている途中でPRGset関数に飛んだ瞬間には既に、「長押しをしている」状態です。
長押しするタイミングはloop()の中と、PRGset()の中です。
ですのでこうします。
一つ変数を作って、「一旦スイッチから手を離したらモードを切り替える」ことにします。今までも何度かやっている方法ですね。
ではソースの抜粋です。
int SW5mode = 0;//SW5の状態 0がloopで1がPRGset void loop() { digitalWrite(LED_BUILTIN, LOW); if (digitalRead(SW5)) { SW5mode = 0; } a = count % 4; sw(a); count = count + 1; //mode切り替え処理 val[4] = digitalRead(SW4); //スイッチの状態をval[num]に入れる if ((val[4] == 1) && (old_val[4] == 0)) { delay(10);// 10ms待つ。 if (mode == 1) { mode = 0; } else { digitalWrite(LED[4], HIGH); digitalWrite(LED[5], HIGH); digitalWrite(LED[6], HIGH); digitalWrite(LED[7], HIGH); mode = 1; } } old_val[4] = val[4]; //SW5長押しでPRGsetモードへ。 if (SW5mode == 0) { if (!digitalRead(SW5)) { swcount = swcount + 1; if (swcount >= 50000) { PRGset(); } } else { swcount = 0; } } } void PRGset() { digitalWrite(LED_BUILTIN, HIGH); while (1) { if (digitalRead(SW5)) { SW5mode = 1; } //SW5長押しでメインループへ。 if (SW5mode == 1) { if (!digitalRead(SW5)) { swcount = swcount + 1; if (swcount >= 50000) { break; } } else { swcount = 0; } } } }