ピックワールド(PIC World)

インフォメーション

この記事は 2017年11月17日 に以下のカテゴリに投稿されました Arduino Blog.

この記事のタグ

, , , , , , , , , , , ,


Arduino で周波数を計測する – バイクのタコメーターを作りたいんだよ!(その1)

色々方法はあると思う。

軽く思いつくだけでも・・・

  • パルスの出現する回数を計測する  1秒とか1分とかのあいだ、パルスが出てくる回数を数える方法  まぁこれなら、簡単に周波数を求めることができるよね。  1秒なら60倍すればよいし、1分ならそのままでよいわけだ。  ただし、周波数が低い場合に、精度を求めようとすると、この方法だと時間がかかりそう
  • パルス幅を測定する方法  これだと比較的、早い時間で測定できそう。  精度もその時点のものだから、有効桁数という意味では関係なくなる。  ただし、周波数が高くなると、問題が起きそうな感じ

この2つは、上が直接係数方式といってその名の通り。下はレシプロカル方式といって、周波数は周期の逆数だから 周波数(f)= 1 / 周期なので、計算で求める。

他にも方法はあるだろうね。

レシプロカル方式を採用しようと思うが、そのためには、Arduino でパルスの立ち上がりを2回検知して、最初のパルスと、2回目のパルスまでの時間を求めればよいじゃないか!っという考えで進めてみるかと思いきや、ちょっと気になる関数があるんだね。

Arduino には色々な関数が用意されているけれど、どうやら関数1発では、測定できないみたい。

pulseIn(pin, value, timeout);

なんて関数も用意されているのだが、この関数はパルスが High (または Low)状態になっている時間を計測する関数なんだよね。

これだと、デューティー比がわからないと、パルスの周期はわからないや。(と思ったのだが・・)

でもこれ、High の状態と、Low の状態の両方がわかるのだから、コレ足し算すれば、パルス幅(周期)になりそうな感じ。

これがうまくいかないのなら、何らかのタイマーをつかって、パルスのエッジを計測する必要がありそう。

タイマー関数自体は、Arduino には、いくつかが用意されている。

その前に、前後するのではあるけれど、何をしたいのかというと、バイクのタコメーターを作りたいと思っている。

これは、我がカブ号に取り付ける予定の物なのだが、リトルカブがベースで、ボアアップしてあって、かなり快適・快調に走るんだよ。(きもちいい!)

下駄3号とか、国鉄特急カラーとかの別名で呼ばれることもある、1億台出荷されたという、名車のうちの1台。

カブ(リトルカブ)にタコメーターなんていらないだろ!

ってな声は無視する。

というか、このエンジン、クランクのバランスとか、ハイカムとかいろいろ詰まっていて、高回転域の伸びはものすごいから、回転数が知りたいわけよ。

そんな感じで、コイルの1次側からもらってくる信号をもとに、回転数に換算して、表示させたいわけ。(どれぐらい回ってるのか知りたいじゃないの)(たいしたことなくてもさ)

このぐらいなら PIC でももちろん行けるとは思うけれど、コンパイラが有料だとか、開発できるコードのボリュームに制限があるとか、そんな悩みを抱え込むなら、Arduino のほうが良いじゃんなので、Arduino の登場となるわけだ。

さてでも、うまくいくかなぁ?

という不安もある。

ということで、まずは、pulseIn を使って実験してみる。

なお、Arduino の日本語リファレンスのページは、こちら

Arduino 日本語リファレンス

pulseIn(pin, value, timeout)

ピンに入力されるパルスを検出します。たとえば、パルスの種類(value)をHIGHに指定した場合、pulseIn関数は入力がHIGHに変わると同時に時間の計測を始め、またLOWに戻ったら、そこまでの時間(つまりパルスの長さ)をマイクロ秒単位で返します。タイムアウトを指定した場合は、その時間を超えた時点で0を返します。
この関数で計測可能な時間は、経験上、10マイクロ秒から3分です。あまりに長いパルスに対してはエラーとなる可能性があります。
【パラメータ】
pin: パルスを入力するピンの番号 value: 測定するパルスの種類。HIGHまたはLOW timeout(省略可): タイムアウトまでの時間(単位・マイクロ秒)。デフォルトは1秒 (unsigned long)
【戻り値】
パルスの長さ(マイクロ秒)。パルスがスタートする前にタイムアウトとなった場合は0 (unsigned long)。
【例】
パルスがHIGHになっている時間(duration)を調べます。
int pin = 7;unsigned long duration;
void setup() {  pinMode(pin, INPUT);}
void loop() {  duration = pulseIn(pin, HIGH);}

こんな感じ。ってことだから、High と Low と両方測定して、足し算すれば良いのではないかな?っと。

で、最初のソースは、


unsigned long l_time = 0;
unsigned int h_time = 0;
unsigned long t_time = 0;

void setup() {

pinMode( 3, INPUT ); // 3番ピンを INPUT モードに設定    Serial.begin( 9600 );// シリアルポートを 9600bps で開始}

void loop() {

h_time = pulseIn( 3, HIGH ); // まずは3番ピンが High 状態になっている時間を h_time に格納
l_time = pulseIn( 3, LOW); // 次に3番ピンが Low になっている状態を l_time に格納

t_time = h_time + l_time ; // 足し算してパルスの幅(周期)にする
Serial.print( (1.0 / t_time) * 1000000  , DEC ); // シリアルポートに周波数に換算して10進数で出力する μ sec だからかけ算もする
Serial.println( "Hz");       

}

へぇ~

これでも 20KHz ぐらいまではちゃんとパルス幅が計測できるんだねぇ。

今のところは、シリアルモニターに表示しているだけだけど、思ったより正確に取れるので、驚いたなこりゃあ。

ただし、こんな感じで、ファンクションジェネレータから出力された波形を整形している。

大体の数値がわかればよいかなぁと思っているので、これでうまくいくといいなぁ。

楽々だもん。

DC パルスを作る回路(1)_回路図

DC パルスを作る回路(1)_回路図

これは、セオリーとも思われる回路で、(できれば)ショットキーダイオード等を使って、Arduino のアナログ入力に適した電圧(波形に)整形する回路。

元の波形が矩形波(デューティー比 50%)で、この回路を通した後なら、20KHz ぐらいまでならば計測できる。

正弦波とか三角波だと、もう少し落ちるけれど、おそらくは(これから測定する)イグニッションコイルの1次側の波形には通用するかが問題だね。

というよりは、波形整形の部分で工夫して、この回路の後にロジック IC を使って、シュミットトリガインバータとかかけてあげると、良いのかもしれない。(これも基本回路だね)

まぁまぁの結果が得られたのでこの辺りで、今回は、これで終わっておこうかなと思う。

実は、(内緒で)安いデジタルオシロ(また中古)を導入したのだが、これ、便利だねぇ。Auto のボタン一発なので、こんなに便利なの使ってると、アホになってしまいそうだ。

まだあのヴィンテージのオシロ君(愛用品)も使ってるよ~(最近ご機嫌ナナメだけど)

デジタルオシロの波形(20KHz)

デジタルオシロの波形(20KHz)

先の 20KHz の時も、実は波形は相当なまっているので、もしかしたら実地環境に近いのかも。

こっちは1KHz の波形。

1KHz の矩形波をDC5Vに変換

1KHz の矩形波をDC5Vに変換

ファンクションジェネレータも、安い Amazon で買って組み立てたものだけれど、これ、お手軽で便利だね。

秋月でもキットが出てるけれど、こちらはデューティー比も可変できたりする。

でもこっちは1200円(タイムセールでもっと安かったけど)で、ケース付きだもんなぁ。

アクリル板で作られたケースだけれど、こうすればケースになるんだねぇと、わかるから良いかも。

そのうちこれも改造して、そうしようかなぁと思ってる。

デューティー比、変えたいもんなぁ・・・

次回は表示部を少しやろうかなっと。(とりあえずは別のプロジェクトで作りかけの奴を使ってさ)


コメントを残す

最近の投稿

最近のコメント

アーカイブ