0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

analogRead()用の関数作ってみた4

Last updated at Posted at 2016-04-05

Arduino(?)に繋いだ可変抵抗を本当に回した時だけ値を受けとるには?
analogRead()用の関数作ってみた
analogRead()用の関数作ってみた2
analogRead()用の関数作ってみた3の続きです。

必要があって過去記事を見返したら、いろいろ間違ってるし。
他のところも、もうちょっと何とかならない?という気がしてきました。

Arduino言語で書いたものは、ちょっと修正されてc++として処理されるようです。
なのでArduino言語のリファレンスに書いてないことでもc++(ただし、ちょっと古めの、らしい)の技なら使えるものがあります。
また、ちょっと便利なライブラリを使おうとすると途端にオブジェクト指向的な考えが必要になってくるし。

c++にはまったく詳しくないのですが、もっとお手軽に便利にArduinoを使いたいのです。
なので試行錯誤。

ところでc++には...

関数オブジェクトというものがあるそうな。

関数そのものを作る(ように見える?)ようにできるらしい。

前稿は

  • FilterとMeterというクラスを作って、
  • それに関数(と変数)をくっつけて...

としました。
ほとんど同じなんだけど、違いは、

  • 関数そのものを作って、
  • メソッド(の替り?)にoperator()を多重定義している

ところ。
オブジェクトにたいして、かっこ演算子()ですることを決められるそうな。

#include <MIDIUSB.h>
class GetAverage{               //関数GetAverageクラスを作る
  static const int MODULUS_AVERAGE = 8;     //クラス変数 値の履歴の数

  private:      //インスタンスに内包される変数たち
    int val_hist[MODULUS_AVERAGE];  //値の履歴
    int sum;            //合計
    byte i_average; //値を出し入れする場所のインデックス
  public:
    GetAverage(){       // コンストラクタ
      val_hist[MODULUS_AVERAGE] = {};   //配列を0で初期化するにはこうだそうな
      sum = 0;      // 0で初期化
      i_average = 0;
    }
    int operator()(int val){        //かっこ演算子()の(多重?)定義
      sum += ( val - val_hist[i_average] ); //新しい値と一番古い値の差分を合計に加算
      val_hist[i_average] = val;        //一番古い値を捨て新しい値を登録
      i_average = ++i_average % MODULUS_AVERAGE;     //インデックスを一つすすめる
      return sum / MODULUS_AVERAGE; //平均を返す
    }

};

class IsChanged{
  static const int MODULUS_CHANGED = 4;
  private:
    int val2_hist[MODULUS_CHANGED];
    byte i_changed;
  public:
    IsChanged(){
      val2_hist[MODULUS_CHANGED] = {};
      i_changed = 0;
    }
    boolean operator()(int val){  //かっこ演算子()の(多重?)定義
      boolean answer = true;  //答え:変化している
      for(int j = 0; j < MODULUS_CHANGED; j++){
        if(val == val2_hist[j]){ //新しい値と以前の値が同じなら...
          answer = false;   //答え:変化してない
          break;  //forループを抜ける
        }
      }
      val2_hist[i_changed] = val; //一番古い値を捨て新しい値を登録
      i_changed = ++i_changed % MODULUS_CHANGED;  ////インデックスを一つ進める
      return answer;  //答を返す
    }
};

使い方

GetAverage,IsChangeを必要な数だけインスタンス化して、あとは同じ考えです。
インスタンスは普通に関数として使えます。

GetAverage getAverage[4];
IsChanged isChanged[4];
const int ANAPIN[4]={0,1,2,3};
const byte CHANNEL = 0;
const byte CC[4] ={25,26,27,28};

void setup() {
  Serial.begin(115200);
}

void loop() {
  int temp;
  for(int i=0;i < 4; i++){
    if( isChanged[i]( temp = getAverage[i]( analogRead(ANAPIN[i]) >> 3 ))){
      controlChange(CHANNEL,CC[i],temp);
      MidiUSB.flush();
    };
  delay(10);
  };
}

//controll value or velocity
// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

今まではインスタンス名.メソッド名()だったものがインスタンス名()で済むようになりました。

実際に手元にあったa-star 32u4で動かしてみました。
ちゃんと動いているようです。
アナログ入力に何もつないでないので、ランダムな値が出ているはずですが、MIDI出力は連続の値になってました。

スクリーンショット 2016-04-05 18.49.57.png
グラフは、MIDI Monitorでデータを100個とったものをLibreOfficeで作図したものです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?