【Arduino】スピードメータ,タコメーターの製作

(更新)2018/01/12 サーボを用いたメータの項目を追加
2018/02/16プログラムについて補足を追加


現在,ECUの製作の記事を書いていますが,この機能の一部として,タコメータ/スピードメータがあります. 今回は,この機能だけに内容を絞って説明していきたいと思います.


まず,Arduinoなどのマイコンを使用して,回転数を測る方法は,大きく分けて2種類あります.

  • 一定期間にセンサが反応した回数を測定する方法

これは,一定時間でのセンサの反応回数をカウントする方法です.

例として,1秒間にセンサが50回反応した場合,(50÷1)×60より,3000[rpm]であるということがわかります.

しかし,この方法にはデメリットがあります.それは,低回転数時に精度が悪くなってしまうという問題です.以下の例を使用して検証してみましょう.

 1秒間に100回 6000[rpm]
 1秒間に101回 6060[rpm]   ↓ +1.0%
 1秒間に102回 6120[rpm]   ↓ +0.99%
 1秒間に1回 60[rpm]
 1秒間に2回 120[rpm]     ↓ +200%
 1秒間に3回 180[rpm]     ↓ +150%

このように,低回転数の場合は60,120,180というように相対的に分解能が足りなくなっています. また,この例では計算された回転数が60の倍数しかないことからわかるように,正確な回転数ではなく,一番近い60の倍数になります.

これをこれを回避できるのが,次の方法です.


センサの反応の間隔を測定する方法

この方法は,センサが前回反応した時との時間差より,回転数を計測する方法です.

例として,前回のセンサの反応が0.03秒前だったとすると,60÷0.03=2000[rpm]であるということがわかります.

これのメリットは,上の方法と違い,常に正確な値が出ます.

時間差: 0.052[sec] 1154[rpm]
時間差: 0.056[sec] 1071[rpm]
時間差: 0.076[sec] 789[rpm]
時間差:   0.11[sec] 546[rpm]
時間差:   0.13[sec] 462[rpm]


Arduinoでの回路図とプログラム

今回は,2番目の方法を使用して,回転数計を製作していきたいと思います.

Arduinoでは,pulseIn()という関数でパルス幅(時間)を測定することが可能ですが,関数の実行中は他の処理ができなくなってしまうので,今回は,外部割り込みを使用した方法を使います.(ECUの処理は時間に厳しく,pulseIn()だとちゃんと動かなかったため)

今回は,”外部割り込み”というピンを使用したので,Arduino UNOの場合は,2番と3番ピン以外では動作しないことに注意してください.(Arduino MEGAでも使用可)

回路図はこちらです. (コンデンサは,チャタリングという現象を抑えるものです.コンデンサを抜いてボタンを押してみると,押していないのに,複数回押されたことになるのがわかると思います.)


プログラムは,こちらです.

Arduinoに書き込み,シリアルモニタを開いてみてください. ボタンを押した瞬間に,回転数や時間差などが表示されるはずです.


[番外編]

ここで測定した回転数を,車のアナログメーターのように表示させたいときの方法を説明します.

まず,サーボモーターを用意します. そして,橙線を9番,赤線を+,黒線をーに接続します. 次にこのプログラムを書き込んでみてください.

ボタンを押す早さに応じて動きます. 手でやると,動きがぎこちないですが,実際の回転物は滑らかに動くので,メーターも滑らかに動くようになります.

動作したでしょうか? この機能をECUに組み込んでスピードメーター,タコメーターを実現させました

30件のコメント

  1. ありがとうございます!

    こちらの記事を応用して、時間がある時にタコメータとスピードメーターを作ってみたいと思います!

    メーターはステッピングモータではなくて、サーボモータを使うんですね。

    勉強になります!

  2. お世話になっております。
    ぼんじんです。

    Arduinoが届いたので、教わったコードを入力して、実際にやってみました。うまく動きました。感動です!
    シリアルモニタというのも使えて、さらに感動です!
    以前、A_Termというものを使ってモニタで見たことがあったのですが、それも付属で使えて難しい設定もいらないのは、驚きました。

    タクトスイッチをスピードセンサーに換えてやってみたら、なんと結果が表示されました!
    再度の感動です!

    あとは、サーボモーターを買って、アナログメーターに組み込んでみようと思います。

    それと、アンドロイドでの表示にも挑戦したいです。
    頑張ります。

    またまた、質問をさせていただいてよろしいでしょうか。

    1.アナログメーターに組み込むのは、ステッピングモーターより、教えていただいたサーボモーターの方がよいのでしょうか?

    2.スピードセンサーからの入力パルスを訳あって出力するときに2倍にしたいのですが、どのような方法がよろしいでしょうか?
    教えていただいた「センサの反応の間隔を測定する方法」だと、単純に2倍するわけにはいかず、どのような方法がいいか悩んでいます。

    よろしければ、ご教授ください。

    本当にありがとうございます。これからも、よろしくお願いいたします。

    1. こんにちは

      もう動いたんですね,良かったです.
      Arduinoの使いやすさが体感できたと思います.

      質問について,
      1.確か,ステッピングモーターは軸角度の基準点がなかったはずです.なので,調整をしても,電源を切ったり,角度がずれたりした場合にはずれたままになります.
      一方で,サーボモーターは軸が180度程度しか回らないですが,角度の基準を利用して回転させているので,ずれることはありません.
      スピードメーターならば,このような小型の低トルクのもので十分だと思います.http://akizukidenshi.com/catalog/g/gM-08761/

      2.スピードの出力値を2倍にしたいということでしょうか?(例)200rpm⇨400rpm
      それでしたら,
      tachoRpm = 60000000.0000 / tachoWidth;の部分を,
      tachoRpm = (60000000.0000 / tachoWidth)*2.0;
      に変更することで,出力が2倍になります.

      頑張ってください.

      1. おはようございます。
        こちらは朝の8:09です(笑)。

        返信ありがとうございます!

        なるほど〜と思いながら、ふと、あれ?と思い、使おうと思っているメーターを見ましたら、作用角が約270度ありました。
        そこで、270度以上の…例えば360度の作用角のサーボモーターを探したのですが、お値段が少々お高い…(笑)。

        そこでまた質問なのですが、この記事でのコードにサーボモーターの作用角の基準が設定されていますが、これを単純に上げたら、サーボモーターは対応しますでしょうか?
        物理的に無理なのでしょうか?

        あと、2番目の質問は完全に自分の質問の仕方が悪かったです(笑)。すみません(笑)。

        今、使っている車速センサーの入力が1回転につき2パルス入る仕様のものですが、これを4パルスで、今度は「出力をしたい」という事です。

        これは、サーボモーターへの出力ではなく、実は私が持っている車に電動パワステを装着したい意図がありまして、そのパワステコンピューターが4パルスの車速パルスを必要とするからです。

        メーターの話から逸れてしまいましたが、何卒、ご教授ください。

        よろしくお願いいたします。

      2. もう一つ、すみません。

        arduinoにサーボモーターを直接接続して動かされていますが、これは大丈夫なのでしょうか?

        LED程度のものなら大丈夫でも、その他の機器の接続は控えた方がいいような記事を、どこかで見た気がしましたので…。

        あ、今、中華サイトから360度のサーボモーターをポチッてみました(笑)。
        来るのが楽しみです(笑)。

        1. 1.360度のサーボモーターは使用したことがありませんが,もしコード中の関数で動かなかった場合は,writeMicroseconds()という関数を使用することができます.これは,サーボモーターに入力するパルスの長さを直接操作するものなので,これで対処できるはずです.

          2.入力が,2パルス/revのものを,4パルスに増やして他の機器に出力したいということですね.こちらは,プログラムで対処可能だとおもいます.
          アイデアを思いついたのですが,2パルスということは,一回転する間に電圧の山が2つあるということだと思います.
          パルスの立ち上がりと立ち下がりが出る角度は均等に4等分されているのでしょうか?(立ち上がりから立ち下がりの時間 = 立ち下がりから立ち上がりの時間)

          そうでしたら,パルスが立ち上がったところと,立ち下がった部分は1回転のうち4箇所あると思います.その4箇所を認識した時点でそれぞれパルスを出力すれば,簡単にパルスを出力することができるのではないかと思います.

          3.Arduinoの5V出力端子は200mAまで対応可能です(入出力端子は40mA).ですので,小型のサーボモーターでしたら大丈夫な範囲です.また,今回はスピードメーターという負荷のほぼない環境なのでなおさら大丈夫です.(電流は負荷に比例するため,ちなみに電圧は回転数に比例します)

          大きいサーボモータの場合だったら,場合によっては別電源で5Vを用意してやる必要があるかもしれません.
          といっても,自分が動画で使用していたものは秋月電子で一番強力なものでしたが,無負荷なら動いてくれます.本当は良くないのかもしれないですが,

          自動車に使用するときは「誤動作がある前提で」気をつけてテストしてください.特に車はノイズの多い環境なので.
          ノイズ対策について,インターネットで調べるといいかもしれません.
          プルアップやパスコンなどの様々なノイズ対策の方法があります.

          1. 早速の返信、ありがとうございます!

            なるほど、パルスの立ち上がりと立ち下がりを利用するのですね。

            立ち上がりで2パルス、立ち下がりで2パルスを出力すればいいといった感じでしょうか?

            勉強になります。

            ノイズ対策はまさに必要かなと思っていたところでした。
            プルアップ…パスコン…

            日々、これ常に勉強ですね!
            ありがとうございます!

  3. こんばんわ!

    今日、サーボが届いたので早速やってみました。
    掲載していただいたプログラムをそのままコピペして、タクトスイッチではなく車速センサーにつないでみたところ、回りっぱなしになってしまいました。

    ちょっと原因を究明してみます^^

  4. 調べてみたところ、360度のサーボは「連続回転サーボ」と呼ばれるもので、サーボの命令を与えると、角度ではなく、スピードを指定するようですね。

    これはやはりステッピングモータ式を考える必要がありそうです。

    勉強しまーす (・∀・)

    1. 秋月電子にあるS125 1T 2BBというサーボモータなのですが,これは,360度での角度指定ができるはずです.

      https://youtu.be/d9PiV3TyVDE

      この動画のように指定角度で止まってくれるサーボだと思います.
      100%の確証がないので,是非調べてみてください.

      1. 返信、ありがとうございます。
        いつもすみません。

        S125 1T 2BBについて、他の方が書かれているブログを偶然見付けたのですが、どうもこのサーボについても360度連続に動くようです。

        連続回転のサーボモーターを使おうとすれば、通電時間で角度を調整する方法しかないようですね。

        せっかく買ったので活かしたいのですが、自分の頭がついていっていません(笑)。
        精進します。

        1. https://youtu.be/Mvpo4dNQPvE?t=4m26s
          S125のサーボモーターなのですが,この動画では角度の指定ができているようです.
          また,約1回転を超えるような指定をしてしまうと,サーボのゼロ点が動いてしまうようです.

          同じように,購入したサーボでも同様に動かせないでしょうか?

          以下の簡単なスケッチで動くかどうか試してみてください.
          write()では角度を指定でき(0ー180),
          writeMicroseconds()では,角度を信号のオン時間で指定できます.(約1000ー2000)

          数値をいろいろ変えてみてください.
          サイトの都合上,#includeの後の<Servo.h>が表示されないので,追加してください.

          #include

          Servo myservo;

          void setup() {
          myservo.attach(9); // サーボの信号を入力するピンの番号の指定
          }

          void loop() {
          //writeでの指定
          myservo.write(0);//1回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ
          myservo.write(90);//2回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ
          myservo.write(180);//3回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ

          //writeMicrosecondsでの指定
          writeMicroseconds(1000);//4回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ
          writeMicroseconds(1500);//5回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ
          writeMicroseconds(2000);//6回目の角度の指定
          delay(1000);//サーボが動き終わるまで待つ
          }

          1. ありがとうございます。
            時間を作ってやってみます!

            いつもすみません。
            お世話になります。

  5. こんばんわ。

    早速やってみました。
    しかしながら、やはり回転し続けました(笑)。

    使っているモータはFS90Rというモデルなのですが、Arduinoのコミュニティで検索をかけたら同様に悩んでいる人がいて、質問していましたが、返信内容はおそらく「諦めろ」「回転時間で制御できるが、停止ポイントを見つけることが難しいと思う」といった返信であったのではないかと思います。英語なので詳しくはわかりませんが、そう解釈しました。

    180度以上のものを制御しようと思ったら、やっぱりスッテピングモータとモータドライバの組み合わせが確実のようです。

    それにしても、180度以上を角度制御できるサーボモータがあってもいいような気もしますが、180度以上のサーボって連続回転サーボくらいしかないもんですねぇ(笑)。

    そういう意味でも勉強になりました(笑)。
    難しいもんですね~。
    でも、頑張ってメーター作ります(笑)。

  6. こんばんは!

    面白いモーター見付けました!
    X27.168という、まさに自動車メーター用のステッピングモーターです!

    餅は餅屋(笑)。
    灯台もと暗しでした(笑)。

    これを頼んでみました!
    到着したら、レポートします〜(笑)。

    1. 自動車用でしたらしっかり動いてくれそうですね.
      また,動いたら教えてください!

  7. 大変楽しく読ませてもらっています、還暦を過ぎてarduinoを始めました。タコメーターに興味がありこちらにたどり着きました。一つ疑問があるのですが教えていただけたらと思いコメントしました。microsなのですが70分でリセットしてゼロになるとなっているのですが、これだと70分過ぎの回転数がマイナスになるのではないでしょうか?。始めたばかりなのでとんちんかんな質問かもしれません。よろしかったらご教示ください。還暦爺の大ちゃんです。

    1. コメントありがとうございます.

      確かに,70分程度でオーバーフローという現象が起きてしまい,その時点で一回だけマイナスの値となってしまいますね.
      millis()というミリ秒単位の関数は数十日使えるのですが,スピードメーターではなくタコメーターに使用するのであれば,分解能が少し悪くなってしまいます.

      ですので,値がマイナスになったら,そのデータを飛ばすなどの処理を行うことで,変な値を表示することを回避することができると思います.

      1. 早速のお返事ありがとうございます。最近このページにたどり着きましたが大変わかりやすく助かります。マイナスを飛ばすように変更してみます。今後ともよろしくお願いします。

  8. こんばんは、三浦です。不思議な現象なので、また、相談に来ました。スイッチの代わりにフォトインタラプタに変えたところ1000回転からいきなり高回転に変わっていきます。十数万回転から30万回転とかにです。ホールセンサに変えても全くおなじです。時間の計測がうまくいってないようです。ためしに水晶発振器のついたアルディユーノ互換機に変えても同じ結果でした。自力で調べたのですが解決できずにまた来ました。すみませんがまたご教示願えれば幸いです。

  9. こんにちは、三浦です。前回の問題ですがpulseinというライブラリーで解決しました。フォトインタラプタにてhighとlowを足してパルスの計算をして回転数を出しました。オリエンタルのブラシレスモーターが4000回転までデジタル表示するのですが、全域で1パーセント以下の誤差で確認できました。どうもすみませんでした。

    1. フォトインタラプタでの誤作動があったのですね

      私がエンジンのECUに使用していた時もフォトインタラプタでしたが正常に動作していました。

      ノイズは発生していないでしょうか?また、プルアップ抵抗などを入れても誤作動するでしょうか?

      pulseIn()関数は、処理が完了するまで(パルスが入力されるまで)他の処理は行われなくなるので、他に速度の要求される処理をしている場合は注意が必要です。

  10. 返信ありがとうございます。プルアップ抵抗値を変えてみたり、シュミットトリガをかませてみたりしたのですが全く変わりありませんでした。フォトインタラプタはパナソニックのCNZ1023です。これからステッピングモーターを動かす予定ですがpulsinの性質を教えていただき、また、フォトインタプラタのメーカーを変えたりして試していこうと思います。ありがとうございました。
     

  11. はじめまして。
    大変勉強になるものでした。
    最近ついにArduinoに手を出そうと思ってこの記事話見つけたので購入意欲と製作意欲が倍増です。
    そこで、1つ質問があります。
    例えばある一定値の回転数でランプを付けるとか音を出すとかするにはどう言ったプログラムになるのでしょうか。
    性格上?エンジンをぶん回すことが多いので燃費のことも考慮してある一定値で知ることができればいいなと思いまして。
    ご教授願います。
    Arduinoでできますよね?

    1. 初心者の場合は、まず、回転数を測定するプログラム、ランプをつけるプログラム、音を出すプログラムをそれぞれ分けて制作してみてください

      ネットを調べるとたくさん情報は出てきます。
      まず、If文、for文などの基本的な構文を覚えればできると思います。

      1. 返信ありがとうございます。
        なるほど。了解しました。
        まずは基本的なものを勉強していきたいと思います。

三浦 大 へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。