初心者高校生がArduinoを使ってみる【3】

 こんにちは。みかんです
 三回目の今回は実際に作ったものについて書いていこうと思います。
 まずは、すでに作ることができた車間距離を測定する部分について書こうと思うのですが、この部分は大きく分けて速度計測と、距離測定という二つに分かれています。なので今回は速度計測の部分について書いていきます。

 はじめに、どうやって速度を計測するのかを考えないといけないのですが、これはある程度イメージができていました。というか、私の自転車にもついているサイクルコンピューターと同じ方法です。ということで、授業での予算でホールセンサも買っておきました。【1】で紹介したキットにはホールセンサはついていなかったはずなので気を付けてください。
 ちなみに【1】で紹介したキットというのはこれです

 あ、そういえばほかのサイトも参考にさせてもらいながら作ったんですけど、センサ類が使いやすくまとめられてるキットとかもあるんですね。高かったので私は買えませんでしたが…

 こうゆう便利なのもあるのか。うらやましいな、なんて思いながら作ってました。笑
 いやー、こうも初心者だと自分にどこまで投資すべきか迷いますよね。便利なものがあればあるほど楽しいんでしょうけど、私は試行錯誤する過程に楽しさを見出してるのでむしろこっちのほうが向いてるかも?なんて笑

 おっと、話がそれちゃいました


 それで、作ろうとしたらもう一つ考えなければならないことがありまして、それはどうやって速度を算出するかという問題です。はじめは1秒間にホールセンサが反応した回数から算出しようと思っていました。なぜなら、その方法で作っているサイトが多く見かけられたからです。しかし、あるサイト(すみません、どのサイトかは忘れてしまいました。見つけられ次第urlを貼っておきます)でその算出方法の弱点が紹介されていました。それは低速時に不正確になるというものです。たしかにこれは盲点でした。低速時になればなるほど一回の増減で大きく値が変化してしまいます。そこで、紹介されていたのが二回の反応を一セットとして、二回の反応の時間差から速度を算出するというものでした。この方法はなぜかあまりメジャーではないようで、またこのサイトでも具体的なソースコードが公開されていなかったのでここでかなり時間がかかってしまいました。(私の検索不足だったらすみません!!)
 ですが、最終的には満足のいくものになったので良かったと思います。そして、そのソースコードなのですが、公開すべきかはかなり迷いました(一応グループで作っているものなので...)が、私もネットに助けられながらの製作だったのでこれから始める人のためにも公開しておこうと思います。ですが、グループで反対意見が出たら公開をやめることになるかもしれないのでいつまで公開できるかはわかりません。ごめんなさい

 ではまずは使った部品からですね。<付属>というのは、私が購入したキットにも付属していたものです。ですが、一応部品はなるべく商品ページのurlを貼りつけておきます。貼ってあるページが秋月電子さんのものなのは私がいつも使ってるサイトだからであって特に意味はありません

※これはまだ完成形ではありません。このページで後程紹介します

ArduinoUno本体 ※付属のキットもあります。私の買ったキットとは違う種類のものを使用したため、今回は<付属>がついていません
ブレッドボード<付属> ※ただし2個あったほうがやりやすいです。また、大きさがこの商品の倍くらいのものもあるはずです。用途に合わせて購入してください
ホールセンサ [A1324LUA-T]
ジャンパーケーブル<付属>

 そして、これからブレッドボード図を描いて紹介しようと思ったらパソコンが低スペックなのと、私の脳も低スペックなせいで全然描けなかったので、作ってみる人は頑張ってください笑
 一応、プログラムでピンの指定はしてあるので、その通りにつないで電源の供給さえすれば動くはずです!
 いまは、授業の中間発表用に一度組んでしまっているのでいつになるかはわかりませんが写真でも貼っておきますね

 とりあえず、ホールセンサからの値をアナログ0番ピンで受け取ってもらえれば大丈夫です。
 あ、電源供給を忘れずに...私はそれを一度忘れてるので...

//速度計測

//時間計測用の変数の定義
unsigned long tm_1;
unsigned long tm_2;

void setup(){

  //シリアル通信を開始
  Serial.begin(9600);

}

void loop() {

  //カウント用の変数を定義
  int count = 0;

  //ホールセンサ用の変数を定義
  int base = 2500; //ゼロガウス(0G) = 2.5V(2500mV)
  float gaus = 0;

  //一度目のホールセンサ反応の計測
  while(count <= 0){ //カウントが0より大きくなるまで繰り返す

    //ホールセンサからの入力をガウス(磁束密度)に変換する。この部分はなくてもよいが、その場合N極とS極に対応するそれぞれのホールセンサの値を条件に指定する必要があるため、ここで整理することをお勧めする。イメージ的には絶対値をとるかんじ
    float voltage = (analogRead(A0)/1024.0)*5.0*1000;

    if(base <= voltage){ //N極のとき
      gaus = (voltage-base)/5.0;
    }else{ S極のとき
      gaus = (base-voltage)/5.0;
    }

    if(gaus >= 50){ //磁束密度が50以上のとき。地磁気等による反応を防ぐため

     //時間測定
      tm_1 = millis();

      //カウントを1にする。繰り返しの終了
      count = count+1
    }
  }

  //磁束密度の値を0にする。
  gaus = 0;

  //一度に二回反応しないようにするための待ち時間。要調整
  delay(100);

  //一回目の繰り返しの終了を確認するためのプログラム。実行したい際は下の//を消す
  //Serial.println(count); //最後のlnが改行を表す

  while(count <= 1){ //カウントが1より大きくなるまで繰り返す
    float voltage = (analogRead(A0)/1024.0)*5.0*1000;

    if(base <= voltage){
      gaus = (voltage-base)/5.0;
    }else{
      gaus = (base-voltage)/5.0;
    }

    if(gaus >= 50){
      tm_2 = millis();
      count = count+1
    }
  }

  gaus = 0;

  //時間関係の変数を追加で定義
  int tm_1i;
  int tm_2i;
  int tm_dif;

  //時間測定で得られる変数はfloatという型で小数まで入っているため、計算しやすいintという型の整数のみの型に変換する
  tm_1i = (int)tm_1;
  tm_2i = (int)tm_2;

  //二回目に反応した際の時間から、一回目に反応した際の時間を引く。
  tm_dif = tm_2i-tm_1i;

  //速度用の変数を定義
  float = vel;

  //速度を算出。計算内容は 1000(1秒=1000ms)÷tm_dif(一回転にかかる時間)×3600(1時間=60分=3600秒)÷100(1m=100cm)÷1000(1km=1000m)×2(直径=半径×2)×3.14(円周)×35(タイヤの半径。この場合は35cmと仮定)
  vel = 1000.00/tm_dif*3600.00/100.00/1000.00*2.00*3.14*35.00;

  //シリアル通信で速度をパソコンに表示
  Serial.print(vel); //速度の値を表示
  Serial.println("km/h");  //km/hという文字を表示

  //一度に二回(ry
  delay(100);
}

 ということで、一度完成したかのように見えたのですが持ち出して使ってみたら問題点が発生しました。それはパソコンがないと使えないということです。プログラムの実行自体は電源さえ用意すればArduino単体で行えますが、速度の出力にシリアル通信を使用したため外部電源のみで動かしたときに速度を確認できないという状況になってしまいました。そこで、LCDモジュールを使用して速度を表示することにしました。

 なので、これから作るものは先ほどの部品に加えて

 LCDモジュール<付属>

 が必要になります。ただ、このリンクのものはキットに付属したものとは異なるような気がします。キットしか買っていないので何とも言えませんが

 といことで、ソースコードはこちらです

//速度計測+ディスプレイ表示

//lcd用のライブラリを追加
#include <LiquidCrystal.h>

//lcdで使用するピンを指定
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//時間計測用の変数の定義
unsigned long tm_1;
unsigned long tm_2;

void setup(){

  //シリアル通信を開始。あってもなくても変わらないが、シリアル通信を使ってプログラムがどこまで実行されたかを確認したいときに使用
  //Serial.begin(9600);

  //lcdの使用範囲を定義。この場合は、16桁2行。ここが何桁何行まで行けるのかはそれぞれ決まっているので確認すること
  lcd.begin(16,2)

}

void loop() {

  //文字の入力開始位置を指定
 lcd.setCursor(6,0);

  //6桁目1行目にkm/hという文字を表示
  lcd.print("km/h");
  
  //カウント用の変数を定義
  int count = 0;

  //ホールセンサ用の変数を定義
  int base = 2500; //ゼロガウス(0G) = 2.5V(2500mV)
  float gaus = 0;

  //一度目のホールセンサ反応の計測
  while(count <= 0){ //カウントが0より大きくなるまで繰り返す

    //ホールセンサからの入力をガウス(磁束密度)に変換する。この部分はなくてもよいが、その場合N極とS極に対応するそれぞれのホールセンサの値を条件に指定する必要があるため、ここで整理することをお勧めする。イメージ的には絶対値をとるかんじ
    float voltage = (analogRead(A0)/1024.0)*5.0*1000;

    if(base <= voltage){ //N極のとき
      gaus = (voltage-base)/5.0;
    }else{ S極のとき
      gaus = (base-voltage)/5.0;
    }

    if(gaus >= 50){ //磁束密度が50以上のとき。地磁気等による反応を防ぐため

     //時間測定
      tm_1 = millis();

      //カウントを1にする。繰り返しの終了
      count = count+1
    }
  }

  //磁束密度の値を0にする。
  gaus = 0;

  //一度に二回反応しないようにするための待ち時間。要調整
  delay(100);

  //一回目の繰り返しの終了を確認するためのプログラム。実行したい際は下の//を消す
  //Serial.println(count); //最後のlnが改行を表す

  while(count <= 1){ //カウントが1より大きくなるまで繰り返す
    float voltage = (analogRead(A0)/1024.0)*5.0*1000;

    if(base <= voltage){
      gaus = (voltage-base)/5.0;
    }else{
      gaus = (base-voltage)/5.0;
    }

    if(gaus >= 50){
      tm_2 = millis();
      count = count+1
    }
  }

  gaus = 0;

  //時間関係の変数を追加で定義
  int tm_1i;
  int tm_2i;
  int tm_dif;

  //時間測定で得られる変数はfloatという型で小数まで入っているため、計算しやすいintという型の整数のみの型に変換する
  tm_1i = (int)tm_1;
  tm_2i = (int)tm_2;

  //二回目に反応した際の時間から、一回目に反応した際の時間を引く。
  tm_dif = tm_2i-tm_1i;

  //速度用の変数を定義
  float = vel;

  //速度を算出。計算内容は 1000(1秒=1000ms)÷tm_dif(一回転にかかる時間)×3600(1時間=60分=3600秒)÷100(1m=100cm)÷1000(1km=1000m)×2(直径=半径×2)×3.14(円周)×35(タイヤの半径。この場合は35cmと仮定)
  vel = 1000.00/tm_dif*3600.00/100.00/1000.00*2.00*3.14*35.00;

  lcd.setCursor(0,0);
  lcd.print(vel);  //velの値を表示

  //一度に二回(ry
  delay(100);
}

 シリアル通信でパソコンに表示していた部分をLCDに表示しただけなので大して変わりませんでしたね。ですが、これによってパソコンがなくとも速度が測れるようになりました。では、今回はこの辺にして次回は距離測定の話をしようと思います。
 では、さようなら