2016年10月14日

PL01_パルス変換器を作る

とりあえず、何か作るかなって思って、パルス変換器を考えてみたいと思います。
と言う事で、まずは、パルス変換とは何かと言う事で。

パルス変換器は、簡単に言えば、パルスの発生する周波数を変更するものです。パルスとは、例えば、車速信号や角度信号など、矩形波となっているデジタル信号です。
マイコンで言えば、PWM(Pulse Width Modulation)は矩形波ですが、パルス幅変調です。細かく言うと、PWMでは周波数は変更せず、Dutyを変更します。デューティとは、1周期の内でONとなる率を言います。Duty40%と言えば、HIGHが40%、LOWが60%と言う事です。PWMはその周波数を変更せず、Dutyのみ変更されるので、コンデンサなどで平滑すれば、簡易的なADCとしても使えます。

パルスの周波数を変更する際、逓倍とか分周とか言う言葉も使われます。逓倍とは、パルスの周波数をn数倍する事を言い、分周とは、パルス周波数を1/m倍する事を言います。
つまり、逓倍分周と言った際には、n/m倍する事となり、大よそ様々な倍率設定が可能となるので、一般的に、パルス変換器と言った際には、パルスの逓倍分周器を指す言葉になると思います。

ところで、変換器を作るとして、その周波数を変更すると言う事になれば、電気的に、トリガーとタイマーと倍率によってアナログ的に周波数変換を行えることもありますが、当方は大体マイコンを使うので、変更するにはまず、周波数を確認しないといけないので測定する事が必要になります。そこで、周波数の測定を考えると、ダイレクト式とレシプロカル式と言うのが一般的になります。

ダイレクト式と言うのは、ある一定時間内に発生したパルスをカウントし、回数/時間で周波数とする方式です。1秒間で2回なら2Hz、0.1秒間で10回なら100Hzです。
また、レシプロカル式と言うのは、パルスとパルス間の時間を測り、その時間から、1/時間で周波数とする方式です。1秒なら1Hz、0.1秒なら10Hzです。
どちらの方式も、一般的に用いられています。

ここで、車速情報を考えます。1kmで5040パルス発生する車速情報があったとして、時速60kmで走ると、84Hzです。時速1kmなら、1.4Hzです。この時、ダイレクト式で、1秒間のパルスカウントを行うと、1だったり2だったりします。つまり、1Hzか2Hzとなり、時速1kmは正しく受け取れません。
その為、低い周波数の場合、ダイレクト式では上手く取り切れませんので、レシプロカル式を使う訳ですが、レシプロカル式の場合、例えば、高い周波数ですと、短時間で時間計測や平均化の処理を繰り返さなければならない為、マイコンでは処理しきれない場合があります。つまり、場合によって、方式を変えると言う事になります。

今回は、車速パルスの変換器を考えようと思っているので、レシプロカル式を使ったものを考えたいと思います。
posted by kei3der at 21:14| Comment(0) | PLS | 更新情報をチェックする

PL02_パルス変換器の使い道

パルス変換器とは何かって言うのが、大よそ分かったとして、その使い道に関して考えてみたいと思います。

パルス変換器は、周波数を変換するものであり、何かしらのデジタル信号を変換するものです。その為、使い道って言っても、ほぼ、無数にあるので、とりあえず、当方が使おうかなって思っているものを挙げます。

まずは、今回のメインである車速信号です。車速信号を変更する意味って何か、って事ですが、例えば、2次減速比である、スプロケットを変更するなどで、ギア比が変わると、通常は車速が減ったり増えたりします。これは、タイヤが回った回転数が車速になる為であり、あるパルス数を示す時、タイヤが回る量が変わってしまうと車速が変わってしまうと言う事です。
しかし、その場合でも、パルスを取得している場所がホイールだったら、あるパルス数であっても、タイヤが回る量は変わりません。その為、例えば、エンジンのドライブスプロケットでパルス数を取得しているものに限ると言う事になりますが、それでも、タイヤ外径や、メーター誤差を修正するなど、幾つかの利点も存在します。

次に、エンジンの角度情報、例えば点火時期や吸気圧力のデータを取得する際、エンジンのクランスパルス信号を用いて、角度何度と言う情報があると、データとして活用できる可能性が高まります。そこで、クランクパルスを取得する訳ですが、通常、クランクパルスは、ローターの突起で発生させており、その突起数は、360°を1°で分解できる様には配置していません。つまり、ECUなどでは、ここから分周しているわけですが、同じ様に、分周して角度情報を得ると言う様な話です。

また、例えば、1回転1パルス、つまり1RPの情報があれば、エンジン回転数が得られます。この情報は、点火パルスから拾う事が出来ますが、点火パルスは4stであれば2回転に1回です。場合によって、ノイズを拾うような検出方法なら、気筒数倍のノイズも拾ってしまいますので、1RPのデータは分周しないと出力されません。そこで、パルス変換器を用いると言う事です。

上記は、物によって、パルス整形器を通さないと矩形波としては使い難い場合もあります。例えば、社外のメーターにしたら、ある回転数でエンジン回転数が踊ってしまう、みたいな話です。なので、パルス変換器には、整形器としての役割も担ってもらう様にしたいと思います。
posted by kei3der at 23:27| Comment(0) | PLS | 更新情報をチェックする

2016年11月07日

PL03_車速パルス変換器の作成

ちょっと色々考えていたら、車速用のパルス変換器と、クランクパルスの変換器はちょっと作り方違うなって思ったので、まず、当初の目的であった、車速パルス変換用のプログラムを作ってみようかと。と言うか、作りました。

一旦、定義としては、デジタル信号で受け渡しするので、インプットは矩形波である必要があります。大概のスピードセンサはON/OFFの信号なので、電圧が合えば、そのままで良いと思いますが、正弦波の様な±がある様なのは、整流と電圧制限(MCUの最大電圧まで)を入れる様にします。

また、チャタリングの様な早いノイズ信号が来ると、早い信号をそのまま繰り返してしまう部分があります。とりあえず、メーターだったら、均されると思いますが、そうでなければローパスフィルタを追加した方が良いかもしれません。

とりあえず、ArduinoDUEで確認したので、DUEが標準になってますが、UNO用のコードも書いてあるので、どちらか選択すれば良いと思います。一応、DUEで1000Hzまでは確認していますが、UNOだとどうだろう。下は0.5Hzで切ってます。確認方法は、Fジェネレータとオシロなので、ノイズが多い車両だとフィルタは必須になるかもしれません。

使い方は、例えば、車速を3%速くしたいとすれば、変換係数k=0.97に。車速を6%遅くしたいなら、k=1.06にすれば、パルスがその分変化して出力されます。

一応、実際にメーターで試す場合、ある周波数は不動になる等のノイズ影響が出ないとも限りません。それは困るので、パルスをパススルーする様に、念の為、切り替えのスイッチは付けましょう。

Arduino 車速パルス変換器 ver1.03
const float k = 1.00;
//Use for Arduino DUE
const int input_pin = 10;
//Use for Arduino UNO (PIND = Pin0-7)
//const int input_pin = 2;
const int output_pin = 7;

boolean input_update_flg = false;
boolean input_high_flg = false;
boolean output_high_flg = false;
boolean output_flg = false;
unsigned long micro_tim = 0;
unsigned long old_tim = 0;
unsigned long d_tim = 0;
float d_time_k = 0.0;
unsigned long out_tim = 0;
unsigned long now_tim = 0;
const long min_spd_time = 2000000;

void setup() {
pinMode(output_pin, OUTPUT);
pinMode(input_pin, INPUT);
}

void loop() {
//Use for Arduino DUE
int digitr = PIN(input_pin);
//Use for Arduino UNO
//int digitr = (PIND & _BV(input_pin)) >> input_pin;
if (digitr == HIGH) {
input_high_flg = true;
} else {
input_update_flg = false;
input_high_flg = false;
}
now_tim = micros();
if (input_high_flg && !input_update_flg) {
old_tim = micro_tim;
micro_tim = now_tim;
d_tim = micro_tim - old_tim;
input_update_flg = true;
}
if (min_spd_time <= now_tim - old_tim) {
output_flg = true;
} else {
output_flg = false;
}
if (!output_flg) {
if (out_tim + d_time_k <= now_tim) {
//Use for Arduino DUE
POUT(output_pin, HIGH);
//Use for Arduino UNO
//PORTD |= _BV(output_pin);
out_tim = now_tim;
output_high_flg = true;
}
if (output_high_flg && out_tim + d_time_k / 2.0 <= now_tim) {
//Use for Arduino DUE
POUT(output_pin, LOW);
//Use for Arduino UNO
//PORTD &= ~_BV(output_pin);
d_time_k = d_tim * k;
output_high_flg = false;
}
if (d_time_k < 100.0) d_time_k = 100.0;
}
}

//Use for Arduino DUE
inline void POUT(int pin, boolean val){
if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
else g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
inline int PIN(int pin){
return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}
posted by kei3der at 00:44| Comment(2) | PLS | 更新情報をチェックする

2016年11月13日

PL04_ファンクションジェネレータ

パルス変換を考える上で、元となるパルスを発生させる機械があると便利です。Arduinoでも作れますが、市販されているものでも安価で使えるものがあります。

例えば、FG085は当方も持っていますが、10kHz程度の矩形波が出力できますし、100kHzの正弦波、±5Vの出力も可能なので、使える方だと思うのですが、特に、ユーザー設定で自由波形を発生させられる所が便利で使っています。

ユーザー設定の方法はwebにありますが、一応記述しておきます。

FG085のユーザー設定自由波形出力
1.FG085を接続します。USBシリアルのドライバーをインストールしておきます。
2.jyeLabと言うソフトウェアをダウンロードします。(ver0.6以上)
3.jyeLab.exeを起動し、[Option]-[PortSetup]を開き、FG085のシリアルポートを指定します。設定は115200-8-1-N-N
4.右下の[Connect]ボタンを押下します。繋がっていればインジケータが緑に変わります。
5.[File]-[Open]を開き、ウェブフォームのcsvファイルを選択します。(csvファイルの作り方は以下)
6.エラーを吐きますが、無視します。
7.グラフ部分の左側の[CH1]のバーをドラッグし上下に振ると波形が表示されます。
8.[Generator]-[Download]を開くと、FG085にアップロードします。
9.FG085の[WF]ボタンを押下し、[USER]出力に切り替えます。既に[USER]出力でも1周させます。
10.csvで指定した波形が1周期なので、例えば矩形波を10波作っていれば、100Hzで1000波出力されます。
※エクセルで編集しつつ波形を読み込ませようとすると、更新しない事があるので、jyeLabを開き直して使います。
Image35.png

ウェブフォームのcsvファイル作成
1.フォーマットが決まっているので、とりあえず、ベースをダウンロードします。
2.1列目の17行目からデータ開始で、256個分のデータを使います。それ以降もデータは入っていますが、使われません。
3.0~255までのデータを指定します。0から255までを1刻みで256個分のデータとして使えば、三角波が出力されます。矩形波ならば、0,255,0,255…とすれば、矩形波になります。
4.csvファイルとして保存し、jyeLabで読み込ませます。

とりあえず、細かい部分まで使ってませんが、1chしか出力されないので使い方も限られます。まあ、疑似信号として使う場面もあるかもね、って事で。
posted by kei3der at 23:30| Comment(0) | PLS | 更新情報をチェックする

2016年11月16日

PL05_クランクパルスと点火時期

クランクパルスから1°の角度を分周させようと思っていたんですけど、そもそも、1°毎のパルスを得たいってどんな時だ?って事で、ちょっと考えたら、点火時期を得たいだけなら、そこまで細かいパルス出力を考えなくていいだろうと。

つまり、クランクパルスの波形はある角度からある角度まで回転して出力される為、例えば、7番目と8番目の突起(又は凹み)の間で点火タイミングが得られていれば、
ign_time-T7/T8-T7
の割合に角度(例えば12波なら30°なので)30°を掛け、更にT7のクランク角度を足してやれば点火時期になるだろうと。

と言う事で、
基準突起のクランク角度+360/クランク突起数×(点火の現在時間-基準突起の時間)÷(基準突起の次の時間-基準突起の時間)
で行けるんじゃないって事で確認してみると、あら、行ける。

で、基準突起の位置を出すのに角度円盤付けて何度、ってやってもいい訳ですが、アイドルの際の点火時期がサービスマニュアルに謳われているので、そこから、アイドルの点火タイミングの波形が基準突起に対して何マイクロ秒ずれているか、から修正してやると、

Image36.png

そこから、基準突起の時間に対して次回の基準突起の時間の差分の逆数に2を掛け(2回転に点火1回なので)、1秒当たりなので60を掛けてやると分速になり、回転数になるので、1回転毎のパルス(1PR)も得られると。

とりあえず、これでプログラム組んでみようと思います。
posted by kei3der at 00:13| Comment(0) | PLS | 更新情報をチェックする

2016年11月27日

PL06_クランク角速度と欠歯

まあ、プログラム自体はとっくに組み上がって、確認も大体済んでますが、車両で最終確認終わってないんで、とりあえずまた後で考えるとして、今回は、クランクパルスを発生させている突起と、基準位置を得るための欠歯について考えてみようかと。

クランクの回転は、等速度のモーターでもあるまいし、しかも、4ストロークなら1回転分は慣性力で回っている(単気筒なら)訳で、その回転変動は結構変わっていると。回転する速度を角速度として縦軸で現すと、下の様になっています(測ったデータでは無いですが、概要にて。)

Image37.png

で、クランクのジェネレータロータにある突起は、通常、等間隔で付けられているので、発生するパルスは角速度の変動を受けて下の様になると。(これもまた概要ですが。)

Image38.png

上の図のグレーの位置を欠歯と考えて、パルスの立ち上がりをトリガーにして時間を計測して、点火時期の位置を計測すれば、前回の式で点火時期が分かるはず。

って、簡単でしょうか?欠歯の時間差⊿Tは、他の遅い突起間隔と同じもしくはもっと時間差のある突起間隔もある様に見える訳です。となると、ここが欠歯だ!って判断するには何だか難しい様な気が。欠歯位置の時間差を⊿T0とすると、
⊿T0 > 閾値
だと、まあまず、欠歯の位置は得られません。

って事で、ここが欠歯ですよって言うの判定式を考えると、もはや、前後の間隔差を見るしかない訳です。なので、欠歯位置の前の時間差を⊿T0-1とすると、
⊿T0/⊿T0-1 > 閾値
が満足する閾値を与えれば良いって事になります。
だがしかし、クランク角速度が急変する可能性はある訳で、この閾値で良ければいいですが、ある回転数は無理!って事も考えられるし、多気筒だと変化が違うとか、ノイズもあるかもって事で、更にジャッジする式を与えると、
(⊿T0/⊿T0-2)×(⊿T0/⊿T0-1) > 閾値
(⊿T0/⊿T0-1)×(⊿T0/⊿T0+1) > 閾値
(⊿T0-2は欠歯位置の2個前の時間差、⊿T0+1は次の時間差)
で行けるんじゃねって思う訳です。これでも無理じゃ、って事になると、更に、
(⊿T0/⊿T0-2)×(⊿T0/⊿T0-1)×(⊿T0/⊿T0+1) > 閾値
(⊿T0/⊿T0-2)×(⊿T0/⊿T0-1)+(⊿T0/⊿T0+1)×(⊿T0/⊿T0+2) > 閾値
(⊿T0/⊿T0-2)×(⊿T0/⊿T0-1)×(⊿T0/⊿T0+1)×(⊿T0/⊿T0+2) > 閾値

って事で、兎に角、欠歯の時間差が結構開いてますよって、前後の時間から比率を求めて知れば良いんじゃねって思う訳です。

と言う事で、何だか分かったような分からない様な話ですが、気になったので。
posted by kei3der at 00:44| Comment(0) | PLS | 更新情報をチェックする

PL07_パルス信号の整形①

クランクのピックアップコイルとか点火パルスをコイルで受けるとか、大概は±100Vとかのノイズの様な波形が得られます。それをArduinoなんかのDigitalINに突っ込むのも気が引けると言うか、ダメなので、整流して整形する必要があります。

そこで、下記の回路を組みます。
Image39.png

とりあえず、これで±100Vのコイル信号から、0-5Vっぽい波形が得られます。(3V仕様なら、5Vの部分を3Vにする。)
これは、信号を整流して整形してフィルタしている訳ですが、コイルが発生する電圧はゼロクロスの交流なので、何となく直流回路に負電圧って言うのは気になるわけです。気になって、アイソレーションするか、分圧してオペアンプに突っ込むか、インダクタとか考えましたが、とりあえず、結果的に上手く行ったので良しとします。上手く行かないとか、無理が掛かる様な場合は、この辺を組み合わせて進めてみてください。

で、シュミットトリガ等で矩形波として整形してやれば綺麗にデジタルで使える矩形波が得られます。74HC14等のICを使うと楽なので、繋げると下記になります。
Image40.png

こっちのPULSE INにコイルを繋ぐと定格オーバーですので、先に上記の回路を繋いだ後に、74HC14を繋いでMCU(Arduinoなど)に繋ぎます。

更に言っておくと、点火のパルスを1次線から、分岐して、取るのは無しです。信号が弱くなるのは良いと思えないので。2次線はもっと無謀です。なので、点火のパルスは、1次線を受ける交流電流センサ等のコイルを使うと良いと思います。また、クランクのピックアップコイルは分岐して入力して良いです。
posted by kei3der at 01:45| Comment(0) | PLS | 更新情報をチェックする

2016年12月04日

PL08_点火時期計測装置の作成

ArduinoDUEで点火時期の計測プログラムを作りました。
シリアル通信で、PC等へ出力します。以前作ったSDカードのシリアルロガーに繋いでやる様に修正すれば、ロガーにもなると思いますので、走行中の点火時期ロギングも行けます。

後は、Arduinoのアナログ(ADC)にTPSの出力を繋いだりしてやれば、スロットル回転毎の点火時期が得られるので、標準点火時期マップも作れます。走行中の点火時期って意外に気になる事もあるので、保存して確認したいこともあるでしょう。タイミングライトじゃできないですね。これは。

取得したエンジン回転数(クランク突起から得る)とスロットル開度、点火時期のデータからマップを作成させるプログラムは、今後作ろうと思います。(またもやEXCELで)

・パルス入力は以前書いた回路を組んで、マイナス側はArduinoのGNDに繋ぎます。
・ジェネレータロータの突起数は12で、欠歯は3を想定して作成しています。その為、角度は30°刻みです。
・idle_advは、アイドルの点火時期です。サービスマニュアルから得ます。
・adv_corr_valは、アイドリング中に計測した点火時期がidle_advと合致するように補正します。
・基準突起位置はNo7番(欠歯後の番号)としています。これは、確認した車両のアイドル点火時期がNo8番の後ろにあり、走行中に点火時期が+50°位進むとNo7が近いので基準としました。
・gap_thresholdは、前回説明した欠歯位置の検出用の閾値です。
・もしかしたらArduinoUNOでもM0でも行けるかも?でも、デジタルでループさせてタイミングを読んでいるのでクランクパルスを逃す様な気もしない訳ではないので、アナログ変換や1サイクルが高速なArduinoDUEで作ってます。
・ジェネレータロータの突起から信号を得るので、プログラム修正すればメーターへエンジン回転数信号(1PR)や、外部装置へデータを送信できるので、応用はいくつか効くかもしれません。

Arduino 点火時期計測プログラム ver1.00
const int cr_input_pin = 7;
const int ign_input_pin = 5;
const int cr_pls_angle = 30;
const float idle_adv = 10.0;
const float adv_corr_val = 0.5;
const float gap_threshold = 4.0;

boolean cr_pls_flag = false;
boolean detect_flag = false;
boolean ign_plsin_flag = false;
unsigned long tim[11];
float dT01 = 0.0;
float dT02 = 0.0;
float dT03 = 0.0;
unsigned long ign_tim = 0;
unsigned long now_tim = 0;
float ign_adv = 0.0;
int eg_rpm = 0;

void setup() {
for (int i = 0; i <= 11; i++) {
tim[i] = 0;
}
Serial.begin(115200);
pinMode(cr_input_pin, INPUT);
pinMode(ign_input_pin, INPUT);
}

void loop() {
int digitr_cr = PIN(cr_input_pin);
int digitr_ign = PIN(ign_input_pin);
now_tim = micros();
if (!ign_plsin_flag && digitr_ign == HIGH) {
ign_tim = now_tim;
ign_plsin_flag = true;
}
if (ign_plsin_flag && digitr_ign == LOW) {
ign_plsin_flag = false;
}
if (!cr_pls_flag && digitr_cr == HIGH) {
for (int i = 1; i <= 10; i++) {
tim[i] = tim[i + 1];
}
tim[11] = now_tim;
dT01 = tim[9] - tim[8];
dT02 = tim[10] - tim[9];
dT03 = tim[11] - tim[10];
if (dT02 / dT01 * dT02 / dT03 > gap_threshold) {
detect_flag = true;
}
cr_pls_flag = true;
}
if (cr_pls_flag && digitr_cr == LOW) {
cr_pls_flag = false;
}
if (detect_flag) {
long eg_a = tim[10] - tim[1];
long eg_b = tim[11] - tim[2];
float egr1 = 60000000.0 / float(eg_a);
float egr2 = 60000000.0 / float(eg_b);
eg_rpm = int((egr1 + egr2) / 2.0);
long ign_a = ign_tim - tim[7];
long ign_b = tim[9] - tim[7];
ign_adv = 30.0 + idle_adv + adv_corr_val - 60.0 * float(ign_a) / float(ign_b);
if (ign_adv <= 100 && ign_adv >= -100) {
Serial.print("EG ");
Serial.print(eg_rpm);
Serial.print(" RPM, ADV ");
Serial.print(ign_adv);
Serial.println(" deg.");
}
detect_flag = false;
}
}

inline void POUT(int pin, boolean val) {
if (val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
else g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
inline int PIN(int pin) {
return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}
posted by kei3der at 02:14| Comment(0) | PLS | 更新情報をチェックする

2016年12月05日

PL09_タコメーターの作成

乗っているバイクによっては回転数が表示されないものもあります。エンジン回転数を表示するタコメーターとして、点火のノイズを拾って表示するハンディなものがありますが、それをArduinoで作成してみたいと思います。

まず、点火時期の点火パルスを得るのと同じく、交流電流センサを点火コイル前の1次線に繋ぎます。交流電流センサはこんな感じのもので、1次線に挟むようにします。CTL-6-S32は極小型なので、レイアウトにもそれ程困らないと思います。パルスの整形回路は以前に記載したパルス信号の整形と同じものを使いますが、3.3V仕様として、Arduinoも3.3Vのmini proで良いと思います。
Image41.jpg

表示機はLCD(SO1602A)を用います。
Image19.png

電源は、電池でも可能だと思いますが、AruduinoとLCDの消費電流は100mA程度になりますので、ボタン電池程度だと結構早めに無くなりますが、18650等のリチウムイオンセルを使えば、3000mAh程ありますので、1日は十分持つと思います。TPS63000等を用いた昇降圧DC-DCで3.3Vに降圧して使用すると良いと思います。

場合によって、LCDを変更してコンパクトにし、Arduinoを省電力化する様にすれば、9V電池位のサイズにまで小型化は可能だと思いますし、ペン型の様な形で表示させることも可能だと思います。また、エンジン回転数をアナログ出力するF/Vコンバータ化も可能ですので、工夫してみてはいかがでしょうか。

あと、プログラムとしてはArduinoのライブラリの追加が必要です。Arduinoタブ 「スケッチ」 ⇒ 「ライブラリをインクルード」 ⇒ 「ライブラリを管理」を選び、ライブラリマネージャを開きます。一番上に検索窓があるので、「TWILiquidCrystal」と書き込み、エンターキーを押します。すると、検索上にTWILiquidCrystalが現れるので、それを選択し、「インストール」ボタンを押します。しばらくすると、TWILiquidCrystalの項目の所に「INSTALLED」と表示されます。同様に、「FreqCount」もインストールを行い、閉じるボタンを押し、終了します。

Arduino タコメーター(エンジン回転計)プログラム ver1.00
#include <TWILiquidCrystal.h>
#include <Wire.h>
#include <FreqCount.h>

//Freq input pin = 5 (Arduino UNO)
LiquidCrystal lcd(0x3c);
unsigned long frq = 0;
const int gatetime = 200;

void setup() {
lcd.begin(16, 2);
lcd.clear();
lcd.setBrightness(200);
lcd.setCursor(6, 0);
lcd.print("TACHOMETER");
lcd.setCursor(12, 1);
lcd.print(" rpm");
FreqCount.begin(gatetime);
}

void loop() {
if (FreqCount.available()) {
frq = FreqCount.read();
if (frq >= 9999) frq = 0;
int rev = int(frq * (1000 / float(gatetime)) * 60 * 2);
int revt = int(rev / 10) * 10;
int tmp = revt;
int cnt = 0;
do {
cnt++;
tmp /= 10;
} while (tmp > 0);
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(8 - cnt, 1);
lcd.print(revt);
}
}
posted by kei3der at 00:15| Comment(0) | PLS | 更新情報をチェックする

2016年12月06日

PL10_点火時期計測装置の疑似信号器

点火時期計測装置を作るって事で実車で試しながらやっていると、時間掛かっていたので、Arduinoで点火とクランク信号の疑似信号発生器を作ってみました。FG085だと1chしか作れないし、ファンクションジェネレータでわざわざ設定しなくても作れそうだったので。

これを使って、装置がちゃんと動くか確認できるようになると思います。10000rpmでジェネレータロータの突起数12、欠歯3で作っています。他の設定でも動くと思いますが、ちょっと調整は必要かもしれません。

切り替えのタイミングの適正化を上手く行っていないので、所々でつながりが悪い部分がありますが、一応、この出力を点火時期計測装置に入力してやると下記の様になります。
Image42.png

これは、アナログA0ピンに可変抵抗をかまして、点火時期を可変にするようにしているので、10000rpmでも点火時期のデータとれるね、って確認するためのものです。回転数が固定なのは、タイマーを使っているからで、回転数も可変にするって言うのは出来なくもないですが、考えませんでした。(確認用なので、高速側が取れれば良いかと。)
pin_1がクランクパルス、pin_2が点火信号です。その信号を点火時期計測装置につなぎます。(GNDも繋ぎます。)

ちょっとこれ作った時に思ったのは、エンジンシミュレータを作ってECUに入力してやれば、点火時期のマップを実際に走らなくても作れそうだなって思った事。クランク信号出力なんかはゼロクロスにする必要があったり、カム角とか、吸気圧センサ信号も作る必要があるかもしれませんが、いずれ考えてみたいと思います。

あと、プログラム準備として、事前に「TimerOne」のライブラリを追加しておきます。
Arduinoはmini pro(3.3V 8MHz)で作りました。

Arduino 点火時期計測装置用疑似信号器 Ver1.00
#include <TimerOne.h>
const int pin_1 = 9;
const int pin_2 = 10;
const int onepls_time = 500; // 500usec/t*12t/rev=6msec/rev=10000rpm
const int tooth_val = 12;
const int lostooth_val = 3;

boolean flg1 = false;
boolean flg2 = false;
boolean flg3 = false;
int igndat = 10;
int cnt = 1;
unsigned long ntime = 0;
unsigned long gtime = 0;
unsigned long ftime = 0;
unsigned long htime = 0;

void setup(void) {
pinMode(pin_1, OUTPUT);
pinMode(pin_2, OUTPUT);
Timer1.initialize(onepls_time);
Timer1.attachInterrupt(pin2on);
}

void pin2on() {
if (cnt == tooth_val - 7) {
ftime = micros();
flg1 = true;
}
if (cnt >= tooth_val) {
cnt = 0;
} else if (cnt > tooth_val - lostooth_val) {
igndat = int(analogRead(A0) / 1024.0 * onepls_time * 3);
} else {
digitalWrite(pin_1, HIGH);
gtime = micros();
flg2 = true;
}
cnt++;
}

void loop()
{
ntime = micros();
if (flg2 && gtime + onepls_time / 2 <= ntime) {
digitalWrite(pin_1, LOW);
flg2 = false;
}
if (flg1 && ftime + igndat <= ntime) {
digitalWrite(pin_2, HIGH);
htime = micros();
flg3 = true;
flg1 = false;
}
if (flg3 && htime + onepls_time / 40 <= ntime) {
digitalWrite(pin_2, LOW);
flg3 = false;
}
}
posted by kei3der at 01:03| Comment(0) | PLS | 更新情報をチェックする

2016年12月07日

PL11_点火時期データの確認

点火時期データが取得出来たらマップ化してみます。

マップ化するのに、AFマップ作成した時のEXCELシートを使ってみます。で、そのまま使えるみたいです。EXCEL持ってねえって方には申し訳ないですが。(EXCEL2007以降推奨)

使い方は、点火時期計測装置のデータ(シリアル通信データ)をコピーしてEXCELに貼り付けます。ただ、前回のArduinoプログラムではTPSの入力ができていないので、analogReadをさせる必要があります。プログラム修正はまた後日。

点火時期マップ化EXCELシート ダウンロード

と言う事で、点火時期が分かったから何だ、と言われても困りますが、標準のデータ、マップがあるかないかって言うのはセッティングでは大事です。データを持って走行中の繋がりを見るなど、場面場面で使いたい時があるんじゃないかなって思います。
posted by kei3der at 01:14| Comment(0) | PLS | 更新情報をチェックする

2016年12月08日

PL12_点火時期計測にTPS追加

点火時期計測装置プログラムにTPSデータ取得追加しました。

ただ、TPSは12ビットの電圧データで取得する為、実際のTPS開度に変換しなくてはなりません。
その為、一旦、スロットル開度0%の時のADCの値とスロットル開度100%の時のADCの値を取得し、勾配aと切片bを求めます。
求める為の計算は、以前の記事を参考に計算してみて下さい。(ロガーパラメータAB決定

この計算で、求まったA,Bの値をプログラムのtps_aとtps_bの値に入力する事で、点火時期計測装置を動かした際、TPSの値が%で表示されます。

このシリアル通信のデータを前回の記事のEXCELシートに放り込めば、点火時期マップが作成できるはずです。
お試しください。

Arduino 点火時期計測プログラムTPS+ ver1.00
const int cr_input_pin = 7;
const int ign_input_pin = 5;
const int tps_input_pin = A0;
const int cr_pls_angle = 30;
const float idle_adv = 10.0;
const float adv_corr_val = 0.5;
const float gap_threshold = 4.0;
const float tps_a = 1.0;
const float tps_b = 0.0;

boolean cr_pls_flag = false;
boolean detect_flag = false;
boolean ign_plsin_flag = false;
unsigned long tim[11];
float dT01 = 0.0;
float dT02 = 0.0;
float dT03 = 0.0;
unsigned long ign_tim = 0;
unsigned long oldign_tim = 0;
unsigned long now_tim = 0;
float ign_adv = 0.0;
int eg_rpm = 0;

void setup() {
for (int i = 0; i <= 11; i++) {
tim[i] = 0;
}
Serial.begin(115200);
pinMode(cr_input_pin, INPUT);
pinMode(ign_input_pin, INPUT);
}

void loop() {
int digitr_cr = PIN(cr_input_pin);
int digitr_ign = PIN(ign_input_pin);
now_tim = micros();
if (!ign_plsin_flag && digitr_ign == HIGH) {
ign_tim = now_tim;
ign_plsin_flag = true;
}
if (ign_plsin_flag && digitr_ign == LOW) {
ign_plsin_flag = false;
}
if (!cr_pls_flag && digitr_cr == HIGH) {
for (int i = 1; i <= 10; i++) {
tim[i] = tim[i + 1];
}
tim[11] = now_tim;
dT01 = tim[9] - tim[8];
dT02 = tim[10] - tim[9];
dT03 = tim[11] - tim[10];
if (dT02 * dT02 / dT01 / dT03 > gap_threshold) {
detect_flag = true;
}
cr_pls_flag = true;
}
if (cr_pls_flag && digitr_cr == LOW) {
cr_pls_flag = false;
}
if (detect_flag) {
long eg_a = tim[10] - tim[1];
long eg_b = tim[11] - tim[2];
float egr1 = 60000000.0 / float(eg_a);
float egr2 = 60000000.0 / float(eg_b);
eg_rpm = int((egr1 + egr2) / 2.0);
long ign_a = ign_tim - tim[7];
long ign_b = tim[9] - tim[7];
ign_adv = cr_pls_angle + idle_adv + adv_corr_val - 60.0 * float(ign_a) / float(ign_b);
if (ign_adv <= 100 && ign_adv >= -100) {
int tpst = analogRead(tps_input_pin);
float tps_val = float(tpst) * tps_a + tps_b;
Serial.print(eg_rpm);
Serial.print(",");
Serial.print(tps_val,1);
Serial.print(",");
Serial.println(ign_adv);
}
detect_flag = false;
}
}

inline void POUT(int pin, boolean val) {
if (val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
else g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
inline int PIN(int pin) {
return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}
posted by kei3der at 00:42| Comment(0) | PLS | 更新情報をチェックする

2016年12月09日

PL13_パルス信号の整形②

点火パルスとクランクパルスの信号は、コイルからの電磁誘導なので、電圧は条件によって変わってきます。その為、MCUに入力するには制限内電圧でのデジタル信号に変換しないとならないと言う事で、前に回路を示しましたが、2ch分の回路はこうなりますって言うのを示したいと思います。

Image43.png

D1:1N4007、D2:1N4148、C1:0.1uF、Z1:1N5226、R1:4.7k、R2:2kでどうでしょうか。Vccは3.3Vの仕様になります。2chとも線対称で同じ仕様で行けるとは思いますが、計測したデータが良くないなんて場合には、信号をオシロなんかで見ながら、R1~R4、C1、C2辺りを決めていくといいと思います。R2、R4を可変抵抗にしても良いかもしれませんが、一度決まれば早々変える事もないので。

また、前回の回路に比べて、電圧制限の為、ツェナーダイオードを追加してます。74HC14の入力上限があるので、ダイオードで除ききれない分を落とすイメージです。この部分は、コンパレータ(LM393など)を突っ込んでも良い気がします。入力電圧範囲が大きいので。ただ、ノイズに過敏すぎるかも知れないので、その場合は、シュミット回路にして追加して良いと思います。

まあ、とにかく、センサーやコイルにあわせて適切に合わせていかないと、ノイズが出たり、データがおかしくなったりします。その為、オシロスコープなんかはセンサーの信号見るとき等に良く使うので、安いもので十分ですので、持っておくと良いと思います。オシロスコープは、見えない電気を見る道具、ですので、意外な発見があるかもしれません。
posted by kei3der at 00:44| Comment(0) | PLS | 更新情報をチェックする

2017年07月08日

PL14_安価オシロスコープキット

オシロスコープって使い始めると便利だなって思うわけで、当方もなぜか、標準的なオシロスコープ、ハンディタイプ、USB、安価なキットモデルを複数持っている訳ですが、年初あたりに買ったJYETECHのDSO150ってやつが意外に面白かったので、その紹介を。

物を見ると、テスターサイズのオシロモドキで中華製バリバリだし、キットしか出ていないので、どうなの?って気分だったのですが、組み立ててみると、何なんだこれは、って良い意味で思いました。

そもそも、ハンディ系や安価キット系だと、応答が悪かったり使い難かったり、気分的にオシロっぽく使おうって気が起きないものばかりだったんですが、これは、応答性もモニター表示も悪くない。そして、安い。シンプル過ぎて直感操作が可能。どうも、だんだんと見た目もオシロテスターって気がしてくる。

ただ、なぜバッテリー内臓にしなかったのか。外部用コネクタは付いているのに。充電や昇圧のICは無く、バッテリー仕様ではない。仕方が無いので、電圧は9Vなので角電池の6P型がぴったり合うわけで、当初は6Pのバッテリーケースをくっ付けて使っていましたが、コストパフォーマンス悪い。

使用電流は110~120mAなので、6Pが400mAhだとすると、約3時間です。百均で買ったやつだと、2時間程度しか持ちません。2時間で十分じゃねって思う事もあると思いますが、使っているとあっと言う間です。

という事で、リチウムの充電式に変えます。充電用のモジュールとしては、TP4056を使ったモジュールがサイズ的に良いですし、昇圧としては、LM2735を使ったモジュールがサイズ的に良いと思います。が、あえて昇圧したくないって事はあります。内部の電源は9Vをそのまま使っている訳では無く、レギュレートもしているので、何となく嫌だなと思ったりしますが、3.3Vだけでなく、負圧を作ったり、基準電圧を参照していたりするので、とりあえず9Vで行きます。

RC用のリチウムイオンとか、リチウムポリマーとか大容量を使う際には、すごく気を遣うわけですが、なぜか、小さなモバイル用のアルミパック内臓式にする時にはそうでもない気もする訳ですが、いずれにせよ、溶剤入ったものですし、熱的な影響が出ると危ないので注意しましょう。

で、1000mW/3.7V=270mAあれば1時間くらい持つので、600mAh程度のタイプが良いでしょうか。当方は中華バッテリーの寿命の無さや容量の無意味さ、取り扱いに悩みたくないので、リチウムイオンの14500日本製セルバッテリーを選択しました。これだと、内臓って感じじゃ無くね、って言うか、充電仕様にする必要なくね、って思うわけですが、まあ、良しと。
Image63.jpg

とりあえず、配線は下記の様にしました。あと、昇圧の際、電圧を9.2V以上にするとノイズが入りまくりますので、ダイオード前で9.0Vになるように調整します。逆に7V以下になってくると基準電圧がふらつくように見えますので、バッテリー電圧が2.7Vくらいまで安定する昇圧モジュールを使うと良いと思います。
Image62.png
posted by kei3der at 02:02| Comment(0) | PLS | 更新情報をチェックする

2018年12月02日

PL15_パルス信号の整形③

イグニッションコイルの信号を確認していると、回転数を拾いたいなって思うわけで。以前のパルス信号の整形の回路だと、やはりフィルタの調整を効かせたいし、インピーダンス変換しておいた方がよい気もするのでオペアンプを追加し、パルス状の信号だと74HC14では矩形波も瞬時的になってMPUでは拾えない事もあったりなかったりするので、74HC123Aと言う、シュミットトリガ入力のマルチバイブレータのタイマーで2msecほどの矩形波に変えてみました。

この回路を使えば、調整が効くので、大概の信号やイグニッションの信号(クランプ式電流センサ(CT)など)や、他、もろもろの信号(さすがに高電圧は無理ですが。)をMPUに入れられる様になるので、Arduinoなどのカウンターに信号を入力する時には便利かもしれません。

image91.png

基板表示なので多少見え難いですが、上手く配線すれば、2chで、30x40x20mmのサイズに収まります。

尚、タイマーは2msecと言いましたが、実際には2.5msec程度で400Hz、回転数で言うと24000rpmなので十分だと思いますが、調整したいと思う場合は、74HC123Aに接続しているR=3kの抵抗と、C=1uFのコンデンサを変える事で可能です。

tf [sec] >= (VCC[V] - 0.7) * C[F] / (VCC[V] / R[ohm])
((VCC[V] / R[ohm]) < ±20mA)

で計算すると、3kの1uFで、2.58msecになります。でも、まあ24波とか出てる様なクランク信号だと間に合わないんで、そっちの場合はタイマーじゃ無い方が良いかもしれません。

という事で、パルス信号の入力に関して、気になる人も居るかもしれないので。
posted by kei3der at 23:58| Comment(0) | PLS | 更新情報をチェックする