色々方法はあると思う。
軽く思いつくだけでも・・・
この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 ぐらいまではちゃんとパルス幅が計測できるんだねぇ。
今のところは、シリアルモニターに表示しているだけだけど、思ったより正確に取れるので、驚いたなこりゃあ。
ただし、こんな感じで、ファンクションジェネレータから出力された波形を整形している。
大体の数値がわかればよいかなぁと思っているので、これでうまくいくといいなぁ。
楽々だもん。
これは、セオリーとも思われる回路で、(できれば)ショットキーダイオード等を使って、Arduino のアナログ入力に適した電圧(波形に)整形する回路。
元の波形が矩形波(デューティー比 50%)で、この回路を通した後なら、20KHz ぐらいまでならば計測できる。
正弦波とか三角波だと、もう少し落ちるけれど、おそらくは(これから測定する)イグニッションコイルの1次側の波形には通用するかが問題だね。
というよりは、波形整形の部分で工夫して、この回路の後にロジック IC を使って、シュミットトリガインバータとかかけてあげると、良いのかもしれない。(これも基本回路だね)
まぁまぁの結果が得られたのでこの辺りで、今回は、これで終わっておこうかなと思う。
実は、(内緒で)安いデジタルオシロ(また中古)を導入したのだが、これ、便利だねぇ。Auto のボタン一発なので、こんなに便利なの使ってると、アホになってしまいそうだ。
まだあのヴィンテージのオシロ君(愛用品)も使ってるよ~(最近ご機嫌ナナメだけど)
先の 20KHz の時も、実は波形は相当なまっているので、もしかしたら実地環境に近いのかも。
こっちは1KHz の波形。
ファンクションジェネレータも、安い Amazon で買って組み立てたものだけれど、これ、お手軽で便利だね。
秋月でもキットが出てるけれど、こちらはデューティー比も可変できたりする。
でもこっちは1200円(タイムセールでもっと安かったけど)で、ケース付きだもんなぁ。
アクリル板で作られたケースだけれど、こうすればケースになるんだねぇと、わかるから良いかも。
そのうちこれも改造して、そうしようかなぁと思ってる。
デューティー比、変えたいもんなぁ・・・
次回は表示部を少しやろうかなっと。(とりあえずは別のプロジェクトで作りかけの奴を使ってさ)
電子機器が大好きです。
プログラムを書くのをお仕事としていたこともあるので、両方できる PIC や Arduino を使って、いろいろな(役にあんまり立たない)ものを作っています。
実は UNIX 関連のお仕事も長かったので、Raspberry Pi もお手の物なのですけれど、これから触る機会が多くなるのかなぁ。
ボチボチ行きますが、お付き合いください。
若いころの写真なので、現時点では、まだ髪の毛は黒くてありますが、お髭は真っ白になりました。
愛車の国鉄特急カラーのカスタムしたリトルカブで、時々、秋月電子通商の八潮店に出没します。