例えば、そう例えばの話、NB8の可変慣性吸気システム付きエンジンを、可変慣性吸気システム非対応のECUで制御するとします。
この場合、吸気システムのコントロールをどうしたら良いか...
外付けユニットを作って、制御してしまいましょう。
NB8の可変慣性吸気システムですが、吸気管長を切り換えるバルブをモロに電気で駆動するのはちょっと大変なので、まずソレノイドでバキュームのバルブを開け閉めして、そのバキュームによって間接的にバルブを切り換える仕組みです。
ソレノイドってのは、電磁石によって、電流の有無をメカニカルな変位に変換するデバイスです。
電気回路的には、リレーを駆動するのと同じ駆動回路で制御できます。
あとは、REVカウンターのモジュールをマイコンで用意して、設定した回転数を境にそのソレノイドをON/OFFしてやれば良いワケです。
ということで、回路図 vaisc-cir.pdf
始めはIGfの受けを、IGfパルスは殆ど0Vまで振れるものだと思い込んで、NPNで受けてました。
そしたら、IGfの最低電圧って、0.6Vよりも大きくて、Trがスイッチしなくてパルスを検出できずに失敗。
馬鹿正直に設計するならば、コンパレーターを使う所なのですが、極力回路を簡単にしたかったのと、上は12Vあたりまで振れるから、4.4V辺りがしきい値でもOKだろう、ということでPNPトランジスタで受ける回路になりました。
出力段のTr手前にスイッチがあるのは、高回転側でソレノイドONなのかOFFなのか、判らなかったので(ま、途中で判明したんですけど)、どっちでも良いように極性を切り換えるモノです。
あと、PICのエキスパートならば、リセットピンの処理が横着している点が気になるかもしれません。 んが、車の場合、電源の立ち上がりは早いと決めつけて、Vccプルアップで問題無しとしています。
それから忘れてはいけないのは、ソレノイド(-)(+)間に逆むきに入っているダイオード。 コイルはOFFした瞬間に強力な逆起電力を発生しますので、下手するとドライブしているトランジスタが破壊されます。 そいつを逃がす為にコイルの端子間に逆むきに保護ダイオードを入れます(適当な値の抵抗でも可、電装系の場合抵抗の方が多いかも)。 これ、コイルを半導体で駆動するときの基本。
あとは... そう、7805の前にあるダイオード。 無くても問題無いと思いますが、パワーウィンドウコントローラーを作った時の経験から、電源を取る場所にもよりますけど、強力な負荷が掛かった瞬間など、色々なノイズも重なって、瞬間的に電源入力が5Vを割ることもあり得るということで、その対策に入れてます。 まぁーでも、このアプリケーションの場合、マイコンが落ちても0.3秒後には復帰しますので、きっと現象が起きても気がつかないでしょう。
ハードはこれだけで済んじゃう。 汎用ロジックICで組んだりしたら、このサイズには収まらないと思います。 PICって実に便利。
0.3sec間に何パルス入ってきたかをカウントし、そのカウント数×100が回転数になります。
あとは、ロータリースイッチで設定した回転数と比較して、ソレノイドのON/OFFを決めてやればよろし。
当然、上り方向と下り方向とでは、切り換えの回転数を200rpm程度ずらす、ヒステリシスを持たせます。
マシン語は苦手なので、「どうしてもマシン語でなければ」という箇所以外はCで書きました。
途中の動作チェックの為に入れた冗長なコードもありますけど、短いですし、動いた時点でそれでオッケー。
Cが分からない人はゴメンナサイ、読み飛ばしてくだされ。
// Variable Air Intake System Contoroller
// Ver.2.0 2000.03.18 (c)rs501
//
// RA0-RA3: dirve out
// 0011: low, 1100: high
//
// RA4: IGf pulse in
//
// RB0-RB3: switch point
// 1111:4500rpm - 0000:6000rpm
// RB7: monitor pulse out (debug)
// T = 0.6sec
//----- Register Files--------------------------------------
#define TMR0 0x01
#define PORTA 0x05
#define PORTB 0x06
#define TRISA 0x85
#define TRISB 0x86
#include <16f84.h>
#define TH_H 45 // 4500rpm
#define TH_L 42 // 4200rpm
int option @ OPTION;
int trisa @ TRISA;
int trisb @ TRISB;
int porta @ PORTA;
int portb @ PORTB;
unsigned int tmr0 @TMR0;
// 1msec
void wait_1ms(int wait)
{
int temp;
asm(label w1m
movlw 249
movwf temp
nop
nop
nop
nop
nop
nop
label w1_1
nop
nop
nop
nop
nop
nop
nop
decfsz temp, 1
goto w1_1
decfsz wait, 1
goto w1m
);
}
unsigned int revcount(void)
{
tmr0 = 0; // reset counter.
// wait 0.3sec
wait_1ms(100);
wait_1ms(100);
wait_1ms(100);
return tmr0; // 1count per 100rpm.
}
void main(void)
{
unsigned int th;
unsigned int th_h;
unsigned int th_l;
unsigned int offset;
// Prescaler rate : 1:32 (WDT time out 576ms)
// Assign prescaler to WDT
// TMR0 increment on falling edge
// TMR0 source : RA4 (IGf pulse in)
// INT edge : falling
// ^PortB pull-up : enable
option = 0x3d;
// Set port A[0-3] as outputs, A[4] as input
// Set port B[0-3] as inputs, B[4-7] as outputs
trisa = 0x10;
trisb = 0x0f;
offset = portb & 0x0f ^ 0x0f;
th_h = TH_H + offset;
th_l = TH_L + offset;
th = th_h;
while (1){
if (revcount() < th){
porta = 0x03;
th = th_h;
}else{
porta = 0x0c;
th = th_l;
}
portb = 0xff;
asm (clrwdt); // Clear WDT
if (revcount() < th){
porta = 0x03;
th = th_h;
}else{
portb = 0x0c;
th = th_l;
}
portb = 0x00;
asm (clrwdt); // Clear WDT
// Read setting.
offset = portb & 0x0f ^ 0x0f;
th_h = TH_H + offset;
th_l = TH_L + offset;
}
}
これぐらいだと、ケースの加工も簡単な方です。 図面も描かずに、現物合わせで加工。(^^;)
できあがり。
測定器で検出回転数を正確に測定してみると、ちょっと理論値(?)と公差がずれてたりして、もう少し追い込む余地はありますが、用途から考えて実質的な影響は小さいので、これで完成。
いじょ。