スイッチが押されている間LEDを点灯したり、手を開閉してキャラクタの動きを制御したりするときに、スイッチが押されている間LEDを点灯し離されたらLEDを消灯する、あるいは手を開いている間キャラクタが動作し手を閉じたらキャラクタが静止するような制御方法はよくあることです。これに対して、スイッチが一度押されたら次に押されるまでLEDが点灯し続け、次に押されたときに消灯するというような動作(トグル動作)をさせる制御方法もあります。
スイッチが押されていない状態から押された状態に変化したところを捉える、手が開いている状態から閉じた状態に変化したところを捉える というように状態の変化を捉えるということです。このような状態変化を捉えることを立ち上がり(立ち下がり)検出といいます。
例えば図に示すようにグー、パーや0V(ゼロボルト)、5Vをグラフのように表してみると、時間経過(図の左から右に時間が経過している)に沿って、最初から①の点までグー(あるいは0V)、①からパー(あるいは5V)、②からグー、③からパー、④からグー、⑤からパーのようになっていることが分かります。
次にこの状態をコンピュータで読み込むことを考えます。コンピュータでは計算時間などがかかるため、図のグラフのように連続的に値を見ることが出来ず、ある短い時間Δt毎にスイッチや手の開閉のデータを見に行くことになります。その様子を図の下に書いたデータに示します。
スイッチ(センサ)が押されていないとき0、押されたときに1が読み込まれるとするとそのデータは下の図のセンサデータのようになります。図はスイッチが押されていないときに0V(ゼロボルト)、押されたときに5Vが入っている様子を示しています。その下のセンサデータはセンサデータを時間に沿ってΔt毎に読みに行ったときに、センサのデータが0Vなら0、5Vなら1として表しています。
このデータを使うと最初に示したスイッチが押されている間LEDを点灯したりするような動作が実現できます。すなわちデータが1のときにLEDを点灯し、データが0のときにLEDを消灯すればよいわけです。
一方、スイッチが一度押されたら次に押されるまでLEDが点灯し続け、次に押されたときに消灯するという制御を実現するにはどうすればいいでしょうか?
それを実現するためにはスイッチが押されていない状態から押された状態に変化したところを捉える、あるいはその逆の押されている状態から押されていない状態に変化したところを捉えればいいのです。図の0Vから5Vに変化しているところや5Vから0Vに変化しているところが分かればいいわけです。先にも書きましたが、このような状態変化を捉えることを立ち上がり(立ち下がり)検出といいます。
さて、これをプログラムで実現するにはどうすればいいでしょうか? センサデータはその時点での電圧に応じて0か1の値を示しています。ここで現在のセンサデータと前回のセンサデータの差を見てみます。
下の図の前回との差のところに書いてある数字は、その上のセンサデータから1つ左のセンサデータを引いた値を示しています。Ⓐを見ると赤枠で囲んだ右上のセンサデータ(現在のセンサデータ)から左上のセンサデータ(前回のセンサデータ)を引いて、右下の差0が計算出来ています。Ⓑでは現在(今回)のセンサデータが1で前回のセンサデータが0ですから差は1となり、Ⓒでは今回が0、前回が1なので差は-1となります。
これから分かることはⒶのように前回と今回で変化がなければ差は0、Ⓑのように前回が0で今回が1であれば差が1、Ⓒのように前回が1で今回が0であれば差が-1となることが分かります。すなわち変化がなければ差は0、0Vから5Vへ立ち上がる変化があれば差が1、5Vから0Vへ立ち下がる変化があれば差が-1となるわけです。
ということでこれをまとめると以下のようになります。
ということでこれを使ってプログラムで立ち上がり、立下りを検出するには以下のようにすればよいことになります。ArduinoのC言語形式で書いています。
int s, ps; //s:現在のセンサデータ、ps:前回のセンサデータ
void setup(){
・・・・
s = 0; //現在のセンサデータ初期化
ps = s; //前回のセンサデータ初期化
}
void loop(){
ps = s; //psにsを代入してloop()の1回前のセンサデータsをpsに保存
//これでpsがこのloop()で新たに取得するセンサデータsに対して1回前のセンサデータとなる
s = digitalRead(n); //現在のセンサデータの取得
int d = s – ps; //前回のセンサデータとの差を計算
if(d == 1){ //差が1であれば立ち上がりが検出できているのでその処理
立ち上がり処理
}else{
if(d == -1){ //差が-1であれば立ち下がりが検出できているのでその処理
立ち下がり処理
}else{
それ以外のときの処理
}
}
}
参考URL