現在、車関係のメーターを作っているのですが、車速パルスから速度を求めたりイグニッションコイルのパルスからエンジンの回転数を求めなければなりません。
速度は車速パルスの周波数を求めて換算式に当てはめ、エンジンの回転数は1秒あたりの回転数
を求めて60倍すれば求まります。
そんな感じで「パルスの周波数」を求めればいいのですが、少し考えさせられたのでここに覚え書きとして残しておこうと思います。
スポンサーリンク
パルスの周波数の求め方
周波数の求め方には「直接計数方式」と「レシプロカル方式」の2種類があります。
簡単なざっくりとした説明しかしませんので、詳しくは調べて下さい。
直接計数方式
一定時間のパルス数を数えて周波数を求める方法です。
例えば1秒間のパルス数を数えるとその数が周波数になりますね。(周波数は1秒あたりの振動数)
0.1秒間だけ数えると10倍すれば求まります。
ただ、低周波の場合に有効桁数を多くしようとするとカウントする時間を長くして測定しなければならないデメリットがあります。
1[mHz]の分解能を得るには1000秒のカウント時間が必要になってしまいます。
レシプロカル方式
パルスの周期を測定して、その逆数を計算し周波数を求める方法です。
有効桁数は測定パルスの周波数に関係なく、測定の際の時間分解能で決まります。
そのため低い周波数でも短時間で高い分解能で測定できます。
しかし、高周波の場合は有効桁数を取りにくくなってしまいます。
メーターのパルスの周波数は低い方なのでレシプロカル方式で求めます。
車速を求める
スピードメータの規格がJISで決まっているようで、計算式も載っています。
上記の式を変形して、V(車速)を求める形にすればいいだけです。
スポンサーリンク
下記はArduino風のサンプルコードです。
60[km/h]の時の回転数は637[rpm]で1回転あたりの車速パルス数は4パルスの場合になります。
1000倍を2回しているのはmicros関数でマイクロ秒が返ってきて、計算時に分母に来るので*10^6となります。
あんまり変わらないかもしれないですが、計算回数を少なくしたいので定数などはあらかじめ計算しておきます。
const float ConstSpd = 60.0 * 60 / (637 * 4) * 1000 * 1000; volatile boolean toggle = true; volatile unsigned long SpdTime1 = 0; volatile unsigned long SpdTime2 = 0; volatile unsigned long SpdSub = 0; volatile float SpdVal = 0; void SpdMeasure() { if (toggle) { SpdTime1 = micros(); SpdSub = SpdTime1 - SpdTime2; } else { SpdTime2 = micros(); SpdSub = SpdTime2 - SpdTime1; } toggle = !toggle; SpdVal = ConstSpd / (float)SpdSub; }
外部割り込みに車速パルスを入れ、上記の関数を呼び出せば車速が求まります。
計算はできるだけ簡単に高速にできるようにしたつもりです。
ただこの場合だと車速パルスがない時、つまり0[km/h]の時は割り込みが来ないので測定できなくなってしまいます。
どうにかして0[km/h]を検出する必要がありますね。
例えば、何秒間か割り込みがなければ0[km/h]と判断できますね。
エンジンの回転数を求める
1パルスの周波数から1秒あたりの回転数を求め、1分あたりの回転数(x1000 rpm)を求めます。
1.5パルスで1回転の場合の割り込みプログラムは以下のようになると思います。
const float ConstRot = 60.0 / 1.5 * 1000 * 1000 / 1000; volatile boolean toggle = true; volatile unsigned long RotTime1 = 0; volatile unsigned long RotTime2 = 0; volatile unsigned long RotSub = 0; volatile float RotVal = 0; void RotMeasure() { if (toggle) { RotTime1 = micros(); RotSub = RotTime1 - RotTime2; } else { RotTime2 = micros(); RotSub = RotTime2 - RotTime1; } toggle = !toggle; RotVal = ConstRot / (float)RotSub; }
本当に動くかは保証できませんので、参考程度にしてください。
エンジンの回転数はイグニッションコイルのノイズがひどくて波形整形をしないと正確な数値が得られないのでハードウェア側の工夫が必要でした。
あと、まだ計算式があっているのか不安なのでもうちょっと考えてみようと思います。
スポンサーリンク
>const float ConsSpd = 60 * 60 / (637 * 4) * 1000 * 1000;
const float ConsSpd = 60.0 * 60 / (637 * 4) * 1000 * 1000;
としないと整数で計算されてしまって値がおかしくなりますね
修正しました。
ご指摘ありがとうございます。
脱字がありますね。
定数定義部はConsSpd,ConsRotで
計算部はConstSpd,ConstRotとなっています