つれづれなる備忘録

日々の発見をあるがままに綴る

TinkercadによるArduinoシミュレーション26 ~ 波形情報の表示

1. アナログ波形の情報表示

 今回はArduinoに入力されるアナログ波形の情報表示の方法を紹介する。Arduino側のアナログピンに入力される波形や波形情報は、簡易的にはオシロスコープなど計測器を接続しない限り知ることができない。

 そこでアナログピンの入力により取得した電圧値を処理することによって、基本的な統計情報である、最大電圧、最小電圧、平均値、標準偏差を表示する方法を示す。また電圧値の基づいて、シリアルモニタ上に疑似的なプロットを表示する方法についても触れる。

2. アナログ波形の統計情報表示

 Tinkercad上でArduinoとファンクションジェネレータを配置し、ArduinoのアナログピンA0とGNDにファンクションジェネレータの正と負端子を接続するだけでよい。スケッチについては、アナログピンに入力された電圧を読み出して、変数valに格納後電圧に変換して統計情報を得るための演算に利用する。アナログピンの入力については下記記事も参照。

atatat.hatenablog.com

波形の統計情報を計算するにはある間隔に渡って電圧値を取り込み、それらの電圧値に対して最大、最小等の値を決定する。今回は電圧値を取り込む間隔をループ回数(count=5000;)で指定することにした。 最大値を求める方法は、取り込んだ電圧が前回の値よりも多ければ最大値更新し、大きくなければ更新しないという処理を行う。最小値は最大値と逆の処理になる。

また平均値Vは、取り込んだ電圧の総和を取り込んだ個数(指定したループ回数)で割る。すなわち

 \displaystyle \overline{V}=\frac{\sum_{i} V_i}{n}

標準偏差σは電圧の2乗和を個数で割った数値から平均値の2乗を減算し、平方根をとる。すなわち

 \displaystyle \sigma=\sqrt{\frac{\sum_i V_i^ 2}{n}-\overline{V}^ 2}

また統計情報を取得するのに指定のカウント数に達するまでにかかった時間をmillis()で取得し、前回取得した時間と差分することで、サンプリング時間を表示するようにした。 以下スケッチを示す。

int val=0;
float V, Vmax=0, Vmin=5, Vav, Vtot, Vsd, V2;
unsigned long ts=0,tp=0,dur=0;
int count=1;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  
  val=analogRead(0); //アナログピン読み出し
  V=(float)val*5/1022; //電圧値に変換
  
  if(V>=Vmax){ //最大値
    Vmax=V;
  }
  if(V<=Vmin){ //最小値
    Vmin=V;
  }
  Vtot=Vtot+V; // 合計(平均、分散算出)
  V2=V2+V*V; // 二乗和(分散算出)
  
  if(count%5000==0){
    
    Serial.println("Waveform statics");
    Serial.print("Max: ");
    Serial.println(Vmax);
    Serial.print("Min: ");
    Serial.println(Vmin);
    Vav=Vtot/count; //平均値
    Vsd=sqrt((V2/count-Vav*Vav)); //標準偏差
    Serial.print("Ave :");
    Serial.println(Vav);
    Serial.print("Sd :");
    Serial.println(Vsd);
    ts=tp; //前回の表示時刻
    tp=millis(); //今回の表示時刻取得
    dur=tp-ts; //サンプリング時間=今回-前回の表示時刻
    Serial.print("Sampling duration :");
    Serial.print(dur);
    Serial.println(" ms");
   
   //以下数値の初期化
    Vmax=0;
    Vmin=5;
    Vav=0;
    Vtot=0;
    Vsd=0;
    V2=0;
    count=1;
  }
  count++; //ループ回数
}

ファンクションジェネレータから50Hzの0-5Vの矩形を入力したときのTinkercadでのシミュレーション例を下に示す。5000ループ達するのに648msかかっているが、単純にはアナログ電圧を1つ取得するのに約130usかかっている計算になる。Arduinoのリファレンス(Arduino 日本語リファレンス)によるとanalogRead()の処理は約100usかかるとあり、ほぼ同じ値である。30us分の差は、シリアルモニタへの表示、統計情報のための計算処理時間の可能性が高い。

アナログ波形の統計情報表示
アナログ波形の統計情報表示

3. アナログ波形の簡易表示

 アナログ波形を簡易的に表示する方法として、取得した電圧の大きさに応じてシリアルモニタ上に*を表示する。下のスケッチの場合は5Vまで10当分して*をひとつづつ増やしていくというものである。ただし、*を描画するのに時間を要するため、周波数が高い波形には適用できない。

int val=0;
float V;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  delay(1000);
}

void loop()
{
  val=analogRead(0); 
  graph(val); //グラフ表示関数
}
void graph(int val){
   V=(float)val/1022*5;
  if (V<0.5){
    Serial.println("*");
  }
  else if(V>=0.5 & V<1.0){
     Serial.println("**");
  }
  else if(V>=1.0 & V<1.5){
     Serial.println("***");
  }
  else if(V>=1.5 & V<2.0){
     Serial.println("****");
  }
  else if(V>=2.0 & V<2.5){
     Serial.println("*****");
  }
  else if(V>=2.5 & V<3.0){
     Serial.println("******");
  }
  else if(V>=3.0 & V<3.5){
     Serial.println("*******");
  }
  else if(V>=3.5 & V<4.0){
     Serial.println("********");
  }
  else if(V>=4.0 & V<4.5){
     Serial.println("*********");
  }
  else{
    Serial.println("**********");
  }
}

10Hzの正弦波を発生させたときの、Tinkercadでのシミュレーション結果を下に示す。正弦波とわかる程度には表示できていると思う。より滑らかに表示するためには*を増やせばよいが、その分描画時間が必要になるので、より遅い波形でないとうまく表示できない。

アナログ波形表示
アナログ波形表示

4. まとめ

  今回はArduinoに入力されるアナログ波形の情報表示として統計情報の表示方法と簡易的な波形表示の方法を紹介した。