[PR]記事内のアフィリエイトリンクから収入を得る場合があります
スポンサーリンク

N-BOX(JF3)ECON運転はそのままアイドリングストップのみキャンセラー自作

ESP32使って手作りアイドリングストップキャンセラーを作ったので紹介する。

アマゾンやらメルカリやらで売られているものとは違うものを作った。

N-BOX(JF3)アイドリングストップのみキャンセラー自作

スポンサーリンク

アイドリングストップキャンセラーなど当初は不要と思っていた

大した機能じゃなくね?

市販品は殆どの場合ECONスイッチの裏側のカプラーに割り込ませて制御するっぽい。なかには電源も別途ヒューズボックスから取り出さなければならないものもあるようだが▼これが一番ポン付けで簡単そう。


もともとアイドリングストップという機能は信号停車中なんかにエンジンをアイドリングさせておくとガソリンがもったいし経済的じゃないしという理由からついたものである。

一時期はすべての車に装備されたんじゃないかと思うくらいの勢いがあったと思う。(想像)

市販品高すぎww

Amazonやらメルカリで売られているアイドリングストップキャンセラーなる商品は3000円台から5000円ぐらいで4000円~5000円ぐらいがボリュームゾーンの価格帯のようだ。

なんだか高い。まあ材料費だけじゃなくアイデア料も含んでいるとはいえ元を取るまでに相当乗らないと無理なんじゃね?って思ってしまうほど。

マイコンボード使えば余裕でできんじゃね?とも思う。

ないよりあったほうがいいと言うのは正しいか

そんなアイドリングストップ機能は近年見直されつつあり、新車に実装されなくなってきているようなんだ。

ユーザーとしてはバッテリーを保護したいとか、スターターを保護したいなどアイドリングストップをしない理由はさまざまなれど最大の理由は財布を保護したいという理由なはず。

アイドリングストップするほうが財布にダメージが大きい傾向にあるという統計結果があるかどうかは知らんが、世の中のアイドリングストップ装着車に乗ってる多くの人がアイドリングストップキャンセル機能を後付しようという(元に商品は市場に溢れ売れ続けている)のはバッテリー保護、スターター保護は二の次で何より財布を保護したいためであろう。

ないよりあったほうがいいと言われていたアイドリングストップ機能は近年ではなくてもいい機能に成り下がった。

市販のアイドリングストップキャンセラーの問題点

そんなわけで自分も遅ればせながらアイドリングストップキャンセルの機能を自車(N-BOX)に盛り込もうと思いついたわけであるが市販品には一つの懸念があった。

それはECONボタンのキャンセルであって、厳密にはアイドリングストップのみのキャンセルではないということだ。

つまりECONボタンの裏側に装着するキャンセラーはエコ走行も同時にキャンセルしてしまい、ガソリン消費の激しい走りになってしまうわけだ。そういうのが好きな輩ならいいけど自分はそうではない。

本来売られている大半の商品はアイドリングストップキャンセラーというよりエコモードキャンセラーというのが正確なのだ。

それを回避したい。アイドリングストップだけキャンセルし、普段はエコモードで走りたい。

それを解決するのがボンネット配線の一時的な断線処理だ。どうやらエンジン始動時にボンネットが空いているとなぜかアイドリングストップにならないらしい。その特性を利用した今回の改造だ。

もちろん実際にボンネットを開けるわけではないし、ずっと開けっ放し状態にしておくと常に警告されるのでウザく、一時的にボンネット開放状態にするのだ。

作ってみた

ソフトウェア

ロジックは大したことなかった。

フローチャートは以下。

アイドリングストップキャンセラーフローチャート

①エンジン始動とともに電源が入る。自動車は12Vだが、USB電源は5Vであり5VのUSB電源からマイコンボードへ電力供給することでいける

②アイドリングストップキャンセル可否の判断は特定のGPIOポートをショートさせておくか否かで決める。例えば27番ポートをGNDをロッカスイッチを挟んで設置しておく。ロッカースイッチがオンならアイドリングストップキャンセル機能を発動させるというロジック

③ボンネット配線の間にノーマルクローズリレーを挟んでおく。普段は常にクローズなのでなにも手を加えていないのと同じ機能になり特定の条件下でのみ断線をするというわけ

④リレーを断線状態にしたのちに8秒間待機する。delay処理を1行書くだけ

⑤ノーマルクローズリレーへの信号を止めクローズ状態に戻す。これによりボンネットが閉じた状態に戻る

ハードウェア

回路図

手書きで恐縮だけどこんな簡単な回路だ。SIGNというのが信号線でESP32から好きな出力ポートを選んで設定しよう。
アイドリングストップキャンセラー回路図

必要な部品

ここに挙げているのは自分のシステムと同じものではなく一例なので好みのものを使ってほしい。

必要な工具

  • 自分の場合半田ごて
    配線を切って自前のリード線をはんだ付けした
  • 電工ペンチ
  • テスター

プログラム

今回のプログラムはアイドリングストップキャンセルの機能だけでなく、ブラインドスポットモニター機能も盛り込んであるのでかなり余分な要素がまざっている。

アイドリングストップキャンセラーの機能だけならsetup()の中の最初の数行だけで足りるのだ。

だからあまりこのプログラムは参考にならないかもしれないが許してほしい。

あとWi-Fi機能なんてのも入れてあってBlynkレガシーとつながるようにもしてある。特に意味はないんだけどやっぱりWi-Fi使えるESP32ならWi-Fi繋がないと面白くないじゃない?という理由。

不要なら削ってほしい。

//#define BONNET_TOGGLE_DUMMY
#define NONE_TEMP_SENSOR  //温度計取り付けたらコメントにする
//#define INTERVAL_DEBUG //タイマーインターバル デバッグ中は長く取る
#define FUNC_START LOW //ボンネットリレースイッチ操作時に使う
#define FUNC_END HIGH
/*
 * ESP32 HC-SR04による距離の測定
 * 2020.2.10
 * JH7UBC Keiji Hata
 */
const char* FirmwareVersion = "0.1.16";
//#define FIXED_DISTANCE //距離を固定してデバッグ
// 0.0.2 温度計つなげるまで暫定25℃ 初期化でバージョン、ファイル名表示、タイマー間隔
// 0.0.3 時間表示変更 その他デバッグ表示
// 0.0.4 トリガーエコーポート変更
// 0.0.5 トリガー処理抜いていてたがやはり必要
// 0.0.6 オンディレイ、オフディレイをそれぞれIOビットで切り替える
// 0.0.7 IOビット切り替えやめ
// 0.0.8 左のみでデバッグ
// 0.0.9 コメント訂正
// 0.0.10 ピン番号重複バグ
// 0.0.11 サブスレッド内にdelay抜け
// 0.0.12 ルーチン内開始終了デバッグ表示やめ
// 0.0.13 trig後のdelaymicrosec10→11
// 0.0.14 TRIGポートpinModeしてなかった
// 0.0.15 distanceLのところdistanceRにしてた
// 0.0.16 距離範囲を見直し なぜか12メートルとかでる
// 0.0.17 インターバル通常に戻す
// 0.0.18 Wi-Fi Blynkと接続するコード
// 0.0.19 iPhoneホットスポット追加
// 0.0.20 タイマー、生存報告、温度測定それぞれのインターバル整理
// 0.0.21 setupでblynk authとIPaddress表示
// 0.0.22 デバッグ
// 0.0.23 timerをBlynk.timerに変更
// 0.0.24 distant処理呼ばないデバッグ
// 0.0.25 Blynk.config前後でコメント表示
// 0.0.26 Blynkつながったので接続処理戻す
// 0.0.27 数値表示桁調整2023-03-21
// 0.0.28 VPIN_RIGH,VPIN_LEFTの処理バグ
// 0.0.29 Blynkに距離データ投げるときに桁減らす
// 0.0.30 EEPROM利用してスイッチ状態を保持する,温度計測ロジック変更
// 0.1.01 エラーなし
// 0.1.02 LEDポート設定、スイッチポート設定
// 0.1.03 ボタンスキャン処理AIによる
// 0.1.04 キースキャン結果表示
// 0.1.05 キースキャン処理変更
// 0.1.06 チャタリング判定時間調整
// 0.1.07 20秒経って呼ばれるべきが200秒だった、EEPROMへの書き込みすべきか分岐
// 0.1.08 キースキャンプログラム変更
// 0.1.09 setup内でWi-Fi接続時に処理分岐
// 0.1.10 Wi-Fi未接続時にフラグ立ててloop内で余分な処理しないようにする
// 0.1.11 EcoModeStateが変わったら表示(デバッグ)
// 0.1.12 EEPROM.read→readByte write→writeByte <EEPROM.h>→"EEPROM.h"
// 0.1.13 EEPROM.beginの失敗確認
// 0.1.14 Wi-Fi接続タイムアウトまで500msec x 5
// 0.1.15 エンジン始動後8秒間ボンネット配線をリレーで切る処理に変更
// 0.1.16 エンジン始動後ボンネット断線処理して8秒ディレイして戻してからsetup処理する

#include <SPIFFS.h>
#include <EEPROM.h>
#include <DHT.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <WiFiMulti.h>
#include <ArduinoOTA.h>
#include "private.h"
#include <BlynkSimpleEsp32.h>
// 左センサー 右センサーGPIO
#define Trig_Pin_L    17
#define Trig_Pin_R    25 //orange
#define Echo_Pin_L    16
#define Echo_Pin_R    12 //yellow
#define LEFT_LED_PIN  4
#define RIGH_LED_PIN  18
#define TRIG_L        1
#define TRIG_R        0

#define DHTPIN        15 //DHTセンサーアウトプットピンの指定
#define DHTTYPE DHT11       // DHT型の指定

#define BONNET_TOGGLE  26
#define BONNET_RELAY   27
#define EcoModeLedPin     2
#define LED_BUILTIN       16

#if defined(INTERVAL_DEBUG)
#define TIMER_INTERVAL  2000L
#define REPOINTERVAL    5000L
#define TEMPINTERVAL    10000L // ミリ秒
#else
#define TIMER_INTERVAL  100   // ミリ秒
#define REPOINTERVAL    5000L  // 5秒
#define TEMPINTERVAL    60000L // 60秒
#endif
#define Maximum_measurable_distance 399 //測定可能最大距離400cm

#define VPIN_ALIV   V1
#define VPIN_TEMP   V2
#define VPIN_HUMI   V3
#define VPIN_RIGH   V4
#define VPIN_LEFT   V5
#define VPIN_RTEST  V6
#define VPIN_LTEST  V7

#define WIFIMULTI     //Wi-Fiマルチつかうのでこれは残す
//const int MAX_WAIT = 20000;
#define ECOMODECANCELWAIT 2000L
//int V = 340;//音速
TaskHandle_t thp[2];        // マルチスレッドのタスクハンドル格納用
BlynkTimer timer1;
//hw_timer_t * timer = NULL;

String programName = __FILE__;
DHT dht(DHTPIN, DHTTYPE);   // DHTセンサーライブラリーを使うための設定
float temperature;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile int AliveRepoCounter     = 0;
volatile int DistantCheckCounter  = 0;
volatile int TempCheckCounter     = 0;
volatile bool AliveFlug = false;
double distanceR ,distanceL;
WiFiMulti wifiMulti;
#define         JST 3600*9  // 日本標準時間の定義
IPAddress ServerIPAddr;

// スイッチの状態を保持するEEPROMのアドレス
#define SWITCH_ADDR 0
// スイッチの状態
#define ECOMODE_ON 1
byte EcoModeState = ECOMODE_ON;
bool InitialMove = true;
//byte ButtonState2();
volatile int idlingStopCancelCounter = 0;
//void left_led_control(void *);
//void right_led_control(void *);
//void aliveReport(int);
static bool notWiFi;

void led_blink(int OnSec, int OffSec, int n, int PORT) {
  for (int i = 0; i < n; i++) {
    digitalWrite(PORT, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(OnSec);                       // wait for a second
    digitalWrite(PORT, LOW);    // turn the LED off by making the voltage LOW
    delay(OffSec);                       // wait for a second
  }
}
void IRAM_ATTR onTimer(){
    portENTER_CRITICAL_ISR(&timerMux);
    //ここに変数変更を書き込む
    DistantCheckCounter ++;     // 距離計測タイマー
    AliveRepoCounter ++;        // 生存報告
    TempCheckCounter ++;        // 温度計測
    idlingStopCancelCounter ++; // 初期アイドリングストップキャンセル
    portEXIT_CRITICAL_ISR(&timerMux);  
}
BLYNK_WRITE(VPIN_RTEST)
{
  int a = param.asInt();
  if(a){
    Serial.println("Right test");
    digitalWrite(RIGH_LED_PIN, HIGH);
    delay(1000);
    digitalWrite(RIGH_LED_PIN, LOW);
  }
}
BLYNK_WRITE(VPIN_LTEST)
{
  int a = param.asInt();
  if(a){
    Serial.println("Left test");
    digitalWrite(LEFT_LED_PIN, HIGH);
    delay(1000);
    digitalWrite(LEFT_LED_PIN, LOW);
  }
}
void trim(char* str) {
  // 先頭の空白を取り除く
  while (isspace(*str)) {
    str++;
  }

  if (*str == 0) {  // 全部空白だった場合
    return;
  }

  // 文字列の最後まで進み、末尾の空白を取り除く
  char* end = str + strlen(str) - 1;
  while (end > str && isspace(*end)) {
    end--;
  }

  // 終端文字を設定し、末尾の空白を削除する
  *(end + 1) = 0;
}
BLYNK_CONNECTED()
{
  Blynk.setProperty(VPIN_LTEST, "offLabel","左LEDテスト");
  Blynk.setProperty(VPIN_RTEST, "offLabel","右LEDテスト");
}
void ArduinoOTAProcess()
{
  Serial.print("connected to Wi-Fi ");
  // Blynk AUTH TOKENと接続サーバー定義
  String ssid = WiFi.SSID();
  ssid = WiFi.SSID();
  if(ssid == ssid_name[0])
  {
    ServerIPAddr = DomesticServer;
    Serial.printf("SSID = %s\n",ssid.c_str());
  }else{
    ServerIPAddr = GlobalServer;
    Serial.printf("SSID = %s\n",ssid.c_str());
  }

  /////////////////// Arduino OTA 初期設定 //////////////
  Serial.println("Start ArduinoOTA initialize.");
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("CarDevice");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount
    // SPIFFS using SPIFFS.end()
    Serial.println("Start updating " + type);
  })
  .onEnd([]() {
    Serial.println("\nEnd");
  })
  .onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  })
  .onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("ArduinoOTA setup done.");
  //////////////////////////////////////////////////////////////////
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // 時刻をJSTに補正する呪文
  configTime(JST, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");

  ////////////////////////////////////////////////////////////////////////////
  Serial.printf("BLYNKAUTH = %s\n",BLYNKAUTH);

  int j = 0;
  while(!Blynk.connect()){
    j++;
    if(j>2){
      Serial.println("Blynk not connected");
      break;
    }
    Blynk.config(BLYNKAUTH, ServerIPAddr, 8080);
    delay(500);
    Serial.print(".");
  }   
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  // ファイル名 バージョンナンバー表示
  int lastIndex = programName.lastIndexOf('\\');
  String result = programName.substring(lastIndex + 1);
  Serial.printf("Program name : %s\n",result.c_str());
  Serial.printf("firmware version : %s\n",FirmwareVersion);
  WiFi.mode(WIFI_STA);
  // ポート初期化
  pinMode(EcoModeLedPin, OUTPUT); // on-board LED
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(BONNET_TOGGLE, INPUT_PULLUP);
  pinMode(BONNET_RELAY,  OUTPUT);
  delay(10);
  // ボンネット機能Onならボンネット配線オフ
  #if defined(BONNET_TOGGLE_DUMMY)
  if(1)
  #else
  if(!digitalRead(BONNET_TOGGLE))
  #endif
  {
    Serial.println("Idling stop cancel process start");
    digitalWrite(EcoModeLedPin, HIGH);
    digitalWrite(BONNET_RELAY, FUNC_START);
    delay(8000);
    digitalWrite(BONNET_RELAY, FUNC_END);
    Serial.println("Idling stop cancel process end");
  }
  // Connect to WiFi
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.println("Wi-Fi Multi entry...");
  WiFi.disconnect(true);//Wi-Fiマルチエントリーの前にこれらを入れておくと
  delay(100);          //繋がりやすくなるらしい
  for (int i = 0; i < ROUTERS; i++) {
    wifiMulti.addAP(ssid_name[i], passwords[i]);   // add Wi-Fi networks you want to connect to
  }
  Serial.println("Connecting to Wi-Fi");
  int j=0;
  while(WiFi.status() != WL_CONNECTED){
    if(++j>5){
      Serial.println("Wi-Fi not connected");
      break;
    }
    wifiMulti.run();
    Serial.print(".");
    delay(500);
  }
  // Wi-Fiつながったときだけ以下の処理入る
  if(WiFi.status()==WL_CONNECTED){
    notWiFi = false;
    ArduinoOTAProcess();
  }else{
    notWiFi = true;
  }
  pinMode(LEFT_LED_PIN, OUTPUT);
  pinMode(Trig_Pin_L, OUTPUT);
  pinMode(Echo_Pin_L, INPUT);
  digitalWrite(Trig_Pin_L, LOW);
  delay(1);
  pinMode(RIGH_LED_PIN, OUTPUT);
  pinMode(Trig_Pin_R, OUTPUT);
  pinMode(Echo_Pin_R, INPUT);
  digitalWrite(Trig_Pin_R, LOW);
  delay(1);
  dht.begin();
  // ここの下数行はタイマー割り込みルーチンを設定するお決まりの命令
  timer1.setInterval(TIMER_INTERVAL, onTimer); // check if Blynk server is connected every 3 seconds
//  timer = timerBegin(0, 80, true); // 1us
//  timerAttachInterrupt(timer, &onTimer, true);
//  timerAlarmWrite(timer, TIMER_INTERVAL * 1000, true);//μ秒(秒x1000x1000)
//  timerAlarmEnable(timer);
  ////////////////////////////////////////////////////////////////////////////  
  xTaskCreatePinnedToCore(left_led_control, "left_led_control", 4096, NULL, 2, &thp[0], 0);
  xTaskCreatePinnedToCore(right_led_control, "right_led_control", 4096, NULL, 3, &thp[1],0);
  //xTaskCreatePinnedToCore(
  //   [タスク名], "[タスク名]", 
  //   [スタックメモリサイズ(4096or8192)], [NULL], 
  //   [タスク優先順位(1-24)] 大きいほど優先順位が高い,
  //   [宣言したタスクハンドルのポインタ(&thp[0])], [CoreID(0or1)]); 
  led_blink(50, 20, 20, RIGH_LED_PIN);
  led_blink(50, 20, 20, LEFT_LED_PIN);  

  // EEPROMを初期化
//  if (!EEPROM.begin(sizeof(byte))) {
//    Serial.println("EEPROM initializing failure !!!");
//  }
  // EEPROMからスイッチの状態を読み込み
//  EcoModeState = EEPROM.readByte(SWITCH_ADDR);
//  Serial.printf("EcoModeState : %d\n",EcoModeState);
//  digitalWrite(EcoModeLedPin, EcoModeState);  

  Serial.println("\nSetup done");
}//setup

//Send Trigger pulse
double read_distance(int LR) {
  double time = 0;
  if(LR == TRIG_R){
    digitalWrite(Trig_Pin_R,LOW);
    delayMicroseconds(2);
    digitalWrite(Trig_Pin_R,HIGH);
    delayMicroseconds(11);
    digitalWrite(Trig_Pin_R, LOW);  
    time = pulseIn(Echo_Pin_R, HIGH);
  }else{
    digitalWrite(Trig_Pin_L, LOW);
    delayMicroseconds(2);
    digitalWrite(Trig_Pin_L,HIGH);
    delayMicroseconds(11);
    digitalWrite(Trig_Pin_L, LOW);
    time = pulseIn(Echo_Pin_L, HIGH);
  }
  // 音速  331.5 + (0.6 * 摂氏温度)
  double sonic = 331.5 + ((int)temperature * 0.6);

  double dist = (time * sonic * 100) / 1000000 / 2;
  return dist;
}//read_distance

void loop()
{
  timer1.run(); // Initiates SimpleTimer
  int WLCONNECTED;
  if(!notWiFi){
    WLCONNECTED = WiFi.status();
    if (WLCONNECTED == WL_CONNECTED) {
      // Wi-Fiに接続できた場合の処理
      ArduinoOTA.handle();          // OTAの命令を入れておく
      if(Blynk.connected()){
        Blynk.run();
      }else{
        Blynk.connect();
      }
    } else {
      // Wi-Fiに接続できなかった場合の処理
      Serial.printf("Wi-Fi try to connect %lu\n",millis());
//      WiFi.reconnect();//一瞬で終わるがWi-Fiマルチだと再接続しないみたい
      wifiMulti.run();
      Serial.printf("Wi-Fi end try        %lu\n",millis());
    }
    // 5秒カウント判定
    if(AliveRepoCounter >= REPOINTERVAL / TIMER_INTERVAL){
      portENTER_CRITICAL(&timerMux);
      AliveRepoCounter = 0;
      portEXIT_CRITICAL(&timerMux);
      //    5秒経過
      aliveReport(WLCONNECTED);
    }
  }
  if(DistantCheckCounter){
    portENTER_CRITICAL(&timerMux);
    DistantCheckCounter = 0;
    portEXIT_CRITICAL(&timerMux);
    //    0.1秒経過
    char str[10];
    distanceL = read_distance(TRIG_L);
    sprintf(str, "%.1lf", distanceL);
    Blynk.setProperty(VPIN_LEFT, "offLabel", str);
    distanceR = read_distance(TRIG_R);//戻り値はXXcm
    sprintf(str, "%.1lf", distanceR);
    Blynk.setProperty(VPIN_RIGH, "offLabel", str);
  }
//  EcoModeToggle();
}//loop

void left_led_control(void *args)
{
  int led_status = LOW;
  while(1){
    // 0または測定可能距離を超えていたら消灯
    if((distanceL == 0) || (distanceL >= Maximum_measurable_distance)){
      if(led_status == HIGH){
        led_status = LOW;
        // LEFT LED OFF
        digitalWrite(LEFT_LED_PIN, LOW);
      }
    }else{
      if(led_status == LOW){
        led_status = HIGH;
        // LEFT LED 点灯
        digitalWrite(LEFT_LED_PIN, HIGH);
      }
    }
    delay(1);
  }
}//left_led_control

void right_led_control(void *args)
{
  int led_status = LOW;
  while(1){
    if((distanceR == 0) || (distanceR >= Maximum_measurable_distance)){
      if(led_status == HIGH){
        led_status = LOW;
        // RIGHT LED OFF
        digitalWrite(RIGH_LED_PIN, LOW);
      }
    }else{
      if(led_status == LOW){
        led_status = HIGH;
        // RIGHT LED 点灯
        digitalWrite(RIGH_LED_PIN, HIGH);
      }
    }
    delay(1);
  }
}//right_led_control

void aliveReport(int WiFiCONNECTED)
{
  static byte ecomode;
  if(TempCheckCounter > TEMPINTERVAL / TIMER_INTERVAL){
    portENTER_CRITICAL(&timerMux);
    TempCheckCounter = 0;
    portEXIT_CRITICAL(&timerMux);
    #if defined(NONE_TEMP_SENSOR)
      temperature = 20;
    #else
      float temperature = dht.readTemperature(); // 温度読み取り
      float humidity = dht.readHumidity();   // 湿度読み取り

      // 読み取りに失敗しているかチェック
      // 失敗している場合はもう一度、温湿度の読み取りをする
      if (isnan(temperature) || isnan(humidity)) {
        Serial.println("Failed to read from DHT sensor!");
        return;
      }
      Blynk.setProperty(VPIN_TEMP, "offLabel",temperature);
      Blynk.setProperty(VPIN_HUMI, "offLabel",   humidity);
    #endif
  }
  if(WiFiCONNECTED){
    char str[13]; //char str2[20];
    int int_h,int_m,int_s;
    DisplayTime(str,&int_h,&int_m,&int_s);         // 現在時刻取得
    Blynk.setProperty(VPIN_ALIV, "offLabel",        str);
//    Serial.println("Blynk alive time reports");
  }
  if(ecomode != EcoModeState){
    ecomode = EcoModeState;
    Serial.printf("EcoModeState:%d\n",EcoModeState);
  }
}

アイドリングストップ機能をキャンセルするだけでこんなに長いプログラムが要るんか?っていったら要らない。余分な機能を満載しているから。それについては別の機会で説明できればと思う。

つけてみた

結線改造する場所

参考にさせていただいたサイトはこちら▼
Nボックスカスタムのアイドリングストップのみキャンセル・タイマー調整・中華製リレーに関するカスタム事例|車のカスタム情報はCARTUNE

写真のカプラーを外して(外さなくてもいいけど外したほうが楽)、若草色のリード線がボンネット開閉センサーだ

ただし若草色のリード線は2本あるので間違えないよう注意すること。

位置は車体前方に向かって左から3番目下から2段目の線。上から1段目左から4番目にも若草色の線があるが違うので絶対早とちりしないこと。俺は早とちりして切ってしまって結線しなおすのに1時間かかった。時間よりも無理な体勢の辛さが身に沁みた。

なにしろ究極的にリード線がギリギリで自動車が組み立てられているから余分な設備をつけようとするとマジで苦労する。

エレクトロタップでつけてもいいんだけどリード線が細すぎて接触不良を起こしそうだから俺ははんだ付けでつけた。

▼まだカプラーがついた状態から・・・
N-BOX(JF3)アイドリングストップのみキャンセラー自作

▼下部の爪をマイナスドライバーなどで持ち上げながらぐりぐり揺すってなんとか外す。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

▼拡大した画。最初はここから必要な線の金具だけ外してバイパス回路をつけようと思ったけどぜんぜん外れなくて諦めて切断にいたった。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

▼どれがボンネットセンサーの線なのか確認しているところ。自前のリード線にメス端子をつけたやつを奥のオス端子に噛み込ませているのがわかるだろうか。さらに手前の端子の同じ位置にはスマホのSIMピンを差し込んでそれにテスターを当てる。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

我ながらSIMピンを入れるのはグッドアイデアだと思った。そうじゃないとテスターの端子が入る余地などないのだ。

▼そして分かったのがこの若草色のリード線だけどマジで気をつけてほしい。上の段じゃなくて下から2段目左から3列目だ。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

▼切断したら被覆をカッターで丁寧に剥いた。短すぎるのと細すぎるのとで普通の電工ペンチの被覆部では太刀打ち出来ない。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

そして上記2箇所の被覆を剥いたところと自前のリード線をはんだ付けし▼こういうボックスにいれたESP32とつなげた。

このボックスにはリレーも入っている。
N-BOX(JF3)アイドリングストップのみキャンセラー自作

動作確認

問題なし。

エンジン始動→ESP32電源ON→リレー作動→ボンネット警告がインフォメーションパネルに表示される→8秒後リレー解除→インフォメーションパネル戻る

走行→信号待ち→アイドリングストップにならない

動画も撮って近日中に公開するから一応そっちも見てほしい。これといった山場はないだろうけど。

【追記】夜中に自動車が警告音を出すwww

取り付けて1週間経過しましてその間、夜中に2度ほど自動車が警告音をけたたましく鳴らして近所迷惑レベルになり焦りました。

警報が鳴るのは自動車の鍵がかかっているときにボンネットが開けられると反応するんだと思います。この装置を装着するまでは一度もそういう誤作動はありませんでしたからこれが原因であることは間違いないでしょう。

装置そのもののどこに不具合があるのか理由はわかりません。

わかりませんが考えられる原因はいくつかあります。

  • マイクロコントローラーの電源をカーナビから取っており夜中に瞬間的にUSB出力に通電する?
    →対策1:電源を別の場所(カーナビの別のUSBポートまたは自動車のUSB電源)
    →対策2:装置の主電源を切っておく(ただし毎回エンジン始動のたびに主電源を入れるのはダルい)
  • リレーが安い中国製なのでNC(ノーマルクローズ)を保持していられずあるとき瞬間的に接点が離れる
    →対策1:リレーを変える
    →対策2:リレーを2個用意し並列につなげてみる

今のところ考えられる要因は電源が瞬間的に入ってしまうかリレーがNCをずっと保持していられないということぐらいなので様子を見ながら改善していこうと思います。

なぜか昼間には誤作動しません。

動画

タイトルとURLをコピーしました