Arduino
オブジェクト指向
C++11
関数型プログラミング

MIDIスイッチをリファクタリングしてみた

More than 1 year has passed since last update.

Ableton Liveのトランスポート用のスイッチ。
P_20170817_210543.jpg
ボタンを押すと、決められたコントロールチェンジを送信します。それだけです。
いくつか作っていますが、これは一番古いタイプ。Arduino duemilanoveがはいっています。

特に動作に不満はないのですが、新しいっぽい書き方を試してみました。

こんなプログラムにしたい

ボタンが四つあるので、これをなにかオブジェクトの配列にして、

void loop() {
  // forループ。BUTTONSの要素 b について:
  for (auto&& b : BUTTONS ){
 // データによって何かする <- デバウンスする <- bのピンを読む 
    doByData( b     ,     debounce( b ,   digitalRead( b.PIN ) 
    ) );
  }
  delay( 1 );
}

もしくは:

void loop() {
  // forループ。BUTTONSの要素 b について:
  for (auto&& b : BUTTONS ){
 // データが上がったときに何かする <- データが下がったときに何かする <- デバウンスする <- bのピンを読む
    doWhenRaised( b      ,       doWhenDropped( b      ,      b.debounce(    digitalRead( b.PIN ) 
    ) ) );
  }
  delay( 1 );
}

みたいな感じにしたいな...

選択肢...

関数をラムダ式で作る

メリット:書きやすい。
デメリット: オブジェクトのメンバにできない。

スケッチの全体はこうなりました。
クロージャをバラして履歴の変数だけオブジェクトに持たせているのでちょっと変な感じです。

関数を関数オブジェクトで作る

メリット:メンバにできる
デメリット:書くのが面倒。

スケッチの全体はこうなりました。

どちらもちゃんと動きました。

最終調整

これに使ってるスイッチは安物で結構チャタリングが酷いので、delayとdebounceのRATEで調整。
チャタリングは抑えるけど、動作にはついてくるギリギリを狙います。
delay( 2 )、RATE = 12でいい感じになりました。