analogRead()用のライブラリを作ってみたのですが、digitalRead()に必要なデバウンスも同じようなものなので、こっちもライブラリにしてみました。DebounceFunc for Arduino
既にいくつか有用なライブラリが公開されていて、車輪の再発明と言えなくもないですが、よろしければお使いください。
#メリット
##使い方が簡単
関数なので、インスタンス化したらあとはひたすら値を与え続けるだけです。簡単。
一方、クラスベースのものだと,まず
- Buttonオブジェクト(またはバウンス監視的なもの)を作成
- 対応するピンを登録
- 動作モード、デバウンスタイムなどを設定
などの手順を踏まなければならず、使うときも
- オブジェクトの状態を更新してから
- オブジェクトの状態を尋ねる
というものが多いです。手間が多い。
#デメリット
##個々の関数オブジェクトは独立していて、同一性、関連性、相反性は保証されない。
例えば、関数オブジェクトIsLOW isLowA,isLowB; IsHIGH isHigh;
があったとして、ずっと同じデータを与えていても、```
isLowA(data) == isLowB(data) ,
isLowA(data) != isHigh(data)
または```
IsFALLING isFalling;
IsCHANGE isChange;
```があったとして```
isFalling(data)```が真のときに```isChange(data)```が真になってない瞬間があるかも知れません。
これは、内部で関数を呼んだときの時刻を計算に使っているので、クリティカルな場面では時刻の違いが結果に出てしまうからです。
だいたいは期待した通りになるはずですが厳密ではありません。微妙な時間差がでる場合があります。
#使い方
[ZIPファイルをダウンロード](https://github.com/ttatsf/DebounceFunc/archive/master.zip)して、[スケッチ>ライブラリをインクルード>.ZIP形式のライブラリをインストール... でインストール](https://www.arduino.cc/en/Guide/Libraries)します。
五つの関数オブジェクトクラスがあります。
+ IsFALLING : デバウンスを計算し、状態がFALLING(HIGH->LOWに変化)かどうかを返す
+ IsRISING : デバウンスを計算し、状態がRISING(LOW->HIGHに変化)かどうかを返す
+ IsCHANGE : デバウンスを計算し、状態がCHANGE(FALLINGまたはRISING)かどうかを返す
+ IsLOW : デバウンスを計算し、状態がLOWかどうかを返す
+ IsHIGH : デバウンスを計算し、状態がHIGHかどうかを返す
関数オブジェクトなので、インスタンス化したら関数としてデータを引数で与えます。
```c++
#include <DebounceFunc.h> //ライブラリを読み込む
IsFALLING isFalling; //関数オブジェクトをインスタンス化
const int IN_PIN = 2; //デジタル入力に使用するピン番号を設定
void setup(){
pinMode(IN_PIN,INPUT_PULLUP); //入力ピンをプルアップ入力に設定
}
void loop(){
const int RAW_DATA = digitalRead(IN_PIN); //入力ピンの値を読み込んでRAW_DATAを生成
if (isFalling(RAW_DATA)) { //関数オブジェクトにRAW_DATAを読み込み、デバウンスを計算し、
//状態が目的の状態(この場合はFALLING)なら
//...その場合にしたい処理をここに書きます。
//...
}
}
delay(1); //delay値は望みの動作になるよう調整してください。
//多くすると動作が安定する場合がありますが、一方、動作がおくれがちになりデバウンスの時間の解像度は粗くなります。
}
デフォルトのデバウンスタイムは30msになっています。
単体の場合はIsFALLING foo(5);
配列の場合はIsFALLING bar[3]={10,7,21};
のようにすれば他の値を指定して作ることができます。
#使用例
自分がよく使うAbleton Live用のトランスポートのスケッチです。MIDIUSBが使える32U4用です。
四つのスイッチがそれぞれコントロールチェンジを出力します。それをscene_launch/stop/next/prevにアサインして使っています。
単純なものですが、勝手にシーンが進んだら困るのでデバウンスが必須です。
#include <MIDIUSB.h>
#include <DebounceFunc.h> //ライブラリを読み込む
const int LEDPIN = 13; //LED点灯用
const int INPIN[] = {3,4,5,6}; //使用する入力ピン番号
const int CC_NUM[] = {25,26,27,28}; //使用するコントロールチェンジナンバー
//関数オブジェクトの配列をインスタンス化する
IsFALLING isFalling[4];
IsRISING isRising[4];
void setup() {
for (int i; i < 4; i++) { //ピンをプルアップ入力に設定
pinMode(INPIN[i],INPUT_PULLUP);
}
pinMode(LEDPIN,OUTPUT); //LEDPINを出力に設定
Serial.begin(115200); //MIDIUSBのためのSerial開始
}
void loop() {
for (int i = 0;i < 4; i++) {
const int RAW_DATA = digitalRead(INPIN[i]); //入力ピンの値を読み込んでRAW_DATAを生成
if (isFalling[i](RAW_DATA)) { //関数オブジェクトにRAW_DATAを読み込み、デバウンスを計算する
//デバウンスしたデータが HIGH -> LOW になったら
controlChange(0,CC_NUM[i],127); //値が 127 のコントロールチェンジを作る
MidiUSB.flush(); //MIDIUSBに出力
digitalWrite(LEDPIN,HIGH); //LED点灯
}
if (isRising[i](RAW_DATA)) { //関数オブジェクトにRAW_DATAを読み込み、デバウンスを計算する
//デバウンスしたデータが LOW -> HIGH になったら
controlChange(0,CC_NUM[i],0); //値が 0 のコントロールチェンジを作る
MidiUSB.flush(); //MIDIUSBに出力
digitalWrite(LEDPIN,LOW); //LED消灯
}
}
delay(1);
}
//MIDIUSB用のコントロールチェンジを作る(MIDIUSBの例からコピペ)
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}