[カブ] Arduinoで作る簡易インジェクションコントローラー(その2)

ボアアップしたFI仕様プレスカブ(97cc)に搭載した簡易インジェクションコントローラを紹介します。

回路構成はブレッドボード上に構築した前回のものに加えてO2センサ出力をモニタ出来るようにしました。燃料噴射時間の増分はECUの出力に対して10%~70%アップで指定出来るようにしています。

 

環境

前回はブレッドボードだけでインジェクションコントローラの回路を組みましたが、今回は実際に道を走るのでユニバーサル基板を使って作ります。今後の機能拡張を考えて基板大きさには少し余裕をもたせました。

  • プレスカブ(2008年式FI仕様、97ccボアアップ済み、形式JBH-AA01)
  • Arduino nano
  • ユニバーサル基板
  • インジェクションコントローラの外箱(3Dプリンタで作成)
動作確認中のインジェクションコントローラ
エンジンエミュレータで動作確認中のインジェクションコントローラ

簡易インジェクションコントローラ(Rev0.1a)の構成

回路

前回から若干変更しています。変更点は以下の2点です。

  • プログラムの都合でArduino nanoの接続端子を変更
  • 新しくO2センサ信号をコンパレータに接続
簡易インジェクションコントローラ回路図(Rev0.1a)
簡易インジェクションコントローラ回路図(Rev0.1a)

O2センサはArduino内蔵のアナログコンパレータに接続して燃調の濃い/薄いが判断出来るようにしました(薄いとArduino nanoのLEDが点灯)。当初はADコンバータで読もうかと考えていましたが、カブに使われているO2センサの出力電圧は約0-1vで理想空燃比近辺で電圧が急激に変化します。濃いor薄いくらいしか判定出来ないのであればコンパレータのほうが高速です。加えてコンパレータなら入力インピーダンスが高いので外にオペアンプを追加しなくとも良さそう、というのが決め手になりました。閾値となる電圧は0.45vとしました(手元にあった抵抗で0.5v近辺に分圧出来るやつを適当に選びました)。

アナログ端子は今後の改良のために使うべくあけてあります。

インジェクションコントローラ基板
インジェクションコントローラ基板(Rev0.1a)、ギボシ端子で接続するようにしましたが結構場所取ります。別なコネクタを使ったほうがいいかも
FETとソケット
FETは耐圧が不足している型番しか手元に無かったので、万が一出先で壊れても対応出来るようソケットにしました

スケッチ

前回はインジェクタ作動時間を一定時間増やしていましたが、これだと高回転時に濃くなりすぎるのではと考えオリジナルから割合で増やす処理に変更しました。計算は固定小数点(小数点以下8bit)を使っています。

また、o2センサの値をArduino nano基板搭載のLEDに表示するようにしました(薄いとLED点灯します)。これがあれば現状として濃いのか薄いのかが分かるのでどれぐらい燃料を増やすかの目安になるのではと思います。


/**
 * Simple Injection Controller for CUB(JBH-AA01)
 * http://www.suke-blog.com
 *
 * @version 0.1a
 */

#include <Arduino.h>
#include <stdio.h>
#include <avr/wdt.h>

#define SERIAL_RATE 115200
#define SERIAL_TIMEOUT 1000

//PIN Config
#define PIN_ECU_INJECTOR_SIG 8
#define PIN_INJECTOR_OUT 11
#define PIN_ECU_SENSOR_O2 7
#define PIN_MODE0 A0
#define PIN_MODE1 A1
#define PIN_MODE2 A2
#define PIN_LED 13

uint8_t g_mode = 0;
uint32_t g_multiplier = 0;
const uint32_t g_modeTable[] = {
 0x000, //0.00
 0x019, //0.10
 0x033, //0.20
 0x0C0, //0.30
 0x04C, //0.40
 0x080, //0.50
 0x099, //0.60
 0x0B3 //0.70
};

// forDebug
static FILE uartout;
static int uart_putchar(char c, FILE *stream) {
 if(Serial.write(c) > 0) {
 return 0;
 } else {
 return -1;
 }
}

void setup(){
 //forDebug
 fdev_setup_stream(&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
 stdout = &uartout;
 // config serial
 Serial.begin(SERIAL_RATE);
 Serial.setTimeout(SERIAL_TIMEOUT);

 //GPIO setting
 pinMode(PIN_ECU_INJECTOR_SIG, INPUT_PULLUP);
 pinMode(PIN_INJECTOR_OUT, OUTPUT);
 pinMode(PIN_MODE0, INPUT_PULLUP);
 pinMode(PIN_MODE1, INPUT_PULLUP);
 pinMode(PIN_MODE2, INPUT_PULLUP);
 pinMode(PIN_LED, OUTPUT);

 //Injector off
 digitalWrite(PIN_INJECTOR_OUT, LOW);

 //o2 sensor led OFF
 digitalWrite(PIN_LED, LOW);

 //Timer1
 TCCR1A = 0x00; //Normal port operation, OC1A/OC1B disconnected.
 TCCR1B = _BV(ICNC1) | _BV(CS11) | _BV(CS10); //InputCaputureNoiseCanceler:Enable, clock/64
 TIMSK1 = 0x00; //InterruptMask: Interrupt disabled.

 //AnalogComparator
 ADCSRB = 0x00; //ADC:Free Running mode
 ACSR = 0x00;
 DIDR1 = _BV(AIN1D) | _BV(AIN0D); //AIN0,1 DigitalInput disabled.

 //ADC
 ADMUX = _BV(REFS0); //Reference:AVCC, Connect:ADC0 pin
 ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); //ADC:Enable,Conversion started.

 //DigitalInput disable
 DIDR1 = _BV(AIN1D) | _BV(AIN0D); //AIN0,1 DigitalInput disabled.
 //DIDR0 = _BV(ADC0D);

 //read ModePin
 g_mode = PINC & 0x07;
 g_multiplier = g_modeTable[g_mode];

 printf("g_mode=%d,\n", g_mode);
 printf("g_multiplier=%f,\n", g_multiplier);
 Serial.end();

 //delay 100ms
 delay(100);

 wdt_enable(WDTO_1S);

 noInterrupts();
}


void loop(){
 uint16_t injectorStartTime = 0;
 uint16_t injectorEndTime = 0;
 uint32_t injectorOnTime = 0;
 uint32_t injectorPlusTime = 0;
 uint8_t temp = 0;

 //wait for injector-on signal from ECU
 while(digitalRead(PIN_ECU_INJECTOR_SIG) != LOW){
 wdt_reset();
 };

 //Injector ON
 digitalWrite(PIN_INJECTOR_OUT, HIGH);
 injectorStartTime = TCNT1; //save injector start time

 //O2 sensor
 temp = ACSR & _BV(ACO);
 if(temp == 0){
 digitalWrite(PIN_LED, LOW);
 }else{
 digitalWrite(PIN_LED, HIGH);
 }

 //wait for injector-off signal from ECU
 while(digitalRead(PIN_ECU_INJECTOR_SIG) != HIGH){};
 injectorEndTime = TCNT1; //save injector end time;

 if(injectorStartTime < injectorEndTime){
 injectorOnTime = (injectorEndTime - injectorStartTime) * 4; //timer 1count = 4usec
 }else{
 injectorOnTime = ((0xFFFF - injectorStartTime) + injectorEndTime) * 4;
 }

 injectorPlusTime = (injectorOnTime * g_multiplier) >> 8;

 //wait Increase time
 delayMicroseconds(injectorPlusTime);

 //Injector OFF
 digitalWrite(PIN_INJECTOR_OUT, LOW);
}

 

コントローラ基板のケース

流石に基板むき出しで実車に搭載するのはマズイかなと思いまして、ちょうどよいサイズが手元になかったので3Dプリンタで作成することにしました。

ケースの3Dモデル
ケースの3Dモデル(蓋無し)、こいつを3Dプリンタで出力しました

蓋はダイソーで購入したいPP板を適当なサイズに切って作りました。半透明なのでLEDの点灯状態くらいは外からも分かります。隙間はそのうちコーキング剤か何かで埋める予定です。

3Dプリンタで作ったケース
基板を収めたところ

 

実車に搭載してみる

設置場所

本当はECUの近くに置きたかったのですが、基板が大きめだったこともあって入りません。諦めて反対側のサイドカバー内(工具入れ)に設置しました。配線類はバッテリー横の隙間を通して反対側まで伸ばしています。

カブの配線分岐
O2センサ等のインジェクションコントローラに必要な配線を分岐します

 

カブの配線分岐
ケースが大きくてこちら側には収まりませんでした。配線を反対側のサイドケースに伸ばしています。

 

インジェクションコントローラの設置
工具入れ側にインジェクションコントローラを設置

 

燃料噴射時間の調整

O2センサの状態を見ながら噴射時間を設定します。理想的には濃い/薄いと行ったり来たりな状態になることだと思うのですが、なかなかぴったりにはなりません。濃いと薄いの境目を見つけてエイヤと暫定値としました。

ジャンパスイッチ
噴射量はジャンパスイッチで切り替えます

 

実際に走ってみて

すでに記事に書いていますがしっかりと走ってくれました。耐久性はまだ不安が残るものの機能としては十分に目的が果たせました(試走中にFETがお亡くなりになったらどうしようかと心配でしたが近所を走って調子を見る分には耐えてくれました。でも、いつか壊れそうなので高耐圧なFETに要交換だと思います)。

R0012638.JPG
いつもの松尾山ベンチコースを走ります。急坂でエンジンに高負荷がかかっているときにスロットルをがぼっと開けるとまだ薄いように感じました

噴射時間設定は一応は上手く機能しているようで、最初に設定した噴射時間だと薄すぎて山を登ったときにスロットルを開けるとエンジンからガタガタと異音が聞こえだしましたが1段階(10%)ほど濃くすると改善しました。

今後の改良点としては、状況(エンジン回転数やスロットル開度とか)に応じて噴射時間を調整出来るようにするとより細かくチューニング出来て楽しそうです。個人的にはデータロガーとしての機能も持たせてやりたいですね。

 

参考

この記事は以下の内容を参考に記載させて頂きました。

コメントを残す

メールアドレスが公開されることはありません。

This blog is kept spam free by WP-SpamFree.