ボアアップしたFI仕様プレスカブ(97cc)に搭載した簡易インジェクションコントローラを紹介します。
回路構成はブレッドボード上に構築した前回のものに加えてO2センサ出力をモニタ出来るようにしました。燃料噴射時間の増分はECUの出力に対して10%~70%アップで指定出来るようにしています。
環境
前回はブレッドボードだけでインジェクションコントローラの回路を組みましたが、今回は実際に道を走るのでユニバーサル基板を使って作ります。今後の機能拡張を考えて基板大きさには少し余裕をもたせました。
- プレスカブ(2008年式FI仕様、97ccボアアップ済み、形式JBH-AA01)
- Arduino nano
- ユニバーサル基板
- インジェクションコントローラの外箱(3Dプリンタで作成)
簡易インジェクションコントローラ(Rev0.1a)の構成
回路
前回から若干変更しています。変更点は以下の2点です。
- プログラムの都合でArduino nanoの接続端子を変更
- 新しくO2センサ信号をコンパレータに接続
O2センサはArduino内蔵のアナログコンパレータに接続して燃調の濃い/薄いが判断出来るようにしました(薄いとArduino nanoのLEDが点灯)。当初はADコンバータで読もうかと考えていましたが、カブに使われているO2センサの出力電圧は約0-1vで理想空燃比近辺で電圧が急激に変化します。濃いor薄いくらいしか判定出来ないのであればコンパレータのほうが高速です。加えてコンパレータなら入力インピーダンスが高いので外にオペアンプを追加しなくとも良さそう、というのが決め手になりました。閾値となる電圧は0.45vとしました(手元にあった抵抗で0.5v近辺に分圧出来るやつを適当に選びました)。
アナログ端子は今後の改良のために使うべくあけてあります。
スケッチ
前回はインジェクタ作動時間を一定時間増やしていましたが、これだと高回転時に濃くなりすぎるのではと考えオリジナルから割合で増やす処理に変更しました。計算は固定小数点(小数点以下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プリンタで作成することにしました。
蓋はダイソーで購入したいPP板を適当なサイズに切って作りました。半透明なのでLEDの点灯状態くらいは外からも分かります。隙間はそのうちコーキング剤か何かで埋める予定です。
実車に搭載してみる
設置場所
本当はECUの近くに置きたかったのですが、基板が大きめだったこともあって入りません。諦めて反対側のサイドカバー内(工具入れ)に設置しました。配線類はバッテリー横の隙間を通して反対側まで伸ばしています。
燃料噴射時間の調整
O2センサの状態を見ながら噴射時間を設定します。理想的には濃い/薄いと行ったり来たりな状態になることだと思うのですが、なかなかぴったりにはなりません。濃いと薄いの境目を見つけてエイヤと暫定値としました。
実際に走ってみて
すでに記事に書いていますがしっかりと走ってくれました。耐久性はまだ不安が残るものの機能としては十分に目的が果たせました(試走中にFETがお亡くなりになったらどうしようかと心配でしたが近所を走って調子を見る分には耐えてくれました。でも、いつか壊れそうなので高耐圧なFETに要交換だと思います)。
噴射時間設定は一応は上手く機能しているようで、最初に設定した噴射時間だと薄すぎて山を登ったときにスロットルを開けるとエンジンからガタガタと異音が聞こえだしましたが1段階(10%)ほど濃くすると改善しました。
今後の改良点としては、状況(エンジン回転数やスロットル開度とか)に応じて噴射時間を調整出来るようにするとより細かくチューニング出来て楽しそうです。個人的にはデータロガーとしての機能も持たせてやりたいですね。
インジェクションコントローラの配線図
2017/12/18追記
インジェクションコントローラとECU間のざっくりとした接続を記載します(そういえば今まで配線図とか載せてませんでした。。。コメントありがとうございます)。
参考
この記事は以下の内容を参考に記載させて頂きました。
- 解析まもログ - PICで 自作インジェクションコントローラ
http://pro.kai-seki.net/%E3%83%90%E3%82%A4%E3%82%AF%E3%81%84%E3%81%98%E3%82%8A/pic%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9 - TOSHIBA - メカリレー駆動用 MOSFET の安全設計
https://toshiba.semicon-storage.com/info/docget.jsp?did=30149 - interfacebus.com - Logic Threshold Voltage Levels
http://www.interfacebus.com/voltage_threshold.html - あれたうみと ひるのすなはま - ArduinoのADCを高速化してみた
http://ameblo.jp/aretaumitohirunosunahama/entry-12014713486.html - miso-engine - Arduinoのタイマーライブラリ
http://miso-engine.hatenablog.com/entry/2015/07/20/221014 - シンセ・アンプラグド - Arduino 周波数/周期カウンタ (1)
http://d.hatena.ne.jp/pcm1723/20091207/1260141551 - SIESTA HOMEPAGE - AVR(Arduino)にLM35温度センサをつなげた場合に正しくA/D変換出来ないトラブル
http://siesta.la.coocan.jp/zk/AVR_ADC/AVR_ADC.html - ソフトウェアデザイン館 Sage Plaisir 21 - 固定小数
http://www.sage-p.com/compone/toda/fixdec.htm
初めまして。
他のマイナー車種なのですが、こちらの記事を参考に作成したところ見事に動作しました。同じバイクに乗っている人達にも広めたいのでTwitterでこの記事へのリンクを貼ってもよろしいでしょうか?
こんにちは。
お役に立てたようで何よりです。
記事はリンクフリーなのでご自由にして頂いて構いません。
コメント失礼します。
逆にこの回路で噴射時間を短くすることって出来ませんか?
こんにちは。
この構成だと元のECU噴射時間を計測してx倍する処理なので短くは出来ません。やるとすれば、クランクパルス(エンジン回転数)とスロットル開度センサをArduinoにつないで、それを元に自前の燃調マップを使って制御すればいける、かな。。。
コメント失礼します。
インジェクションコントローラー とECU間の配線の仕方を詳しく教えて頂けませんか?
こんにちは。
記事の最後にざっくりとした配線図を追記してみました(ちなみに、12VとGNDはサービスカプラから取っています)。参考になればと思います。