From 3e697f360ab1f3f3469c13d6d5c4d76034bac1e4 Mon Sep 17 00:00:00 2001 From: Sebastian Nieto Date: Mon, 7 Sep 2026 21:10:05 -0300 Subject: [PATCH] Fix full-screen arc negative sign bug, switch battery to ATRV, and add PID communication watchdog --- sketch/obd2_gauge/meter.h | 89 ++++++++++++++++++++------------ sketch/obd2_gauge/obd2_gauge.ino | 44 +++++++++++----- 2 files changed, 88 insertions(+), 45 deletions(-) diff --git a/sketch/obd2_gauge/meter.h b/sketch/obd2_gauge/meter.h index 5f58cd0..a75f5ea 100644 --- a/sketch/obd2_gauge/meter.h +++ b/sketch/obd2_gauge/meter.h @@ -524,16 +524,16 @@ void fullScreenMeter(uint8_t cell, uint8_t pid, bool redrawHeader = true) { tft.loadFont(DSEG7_Modern_BoldItalic_80); tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.setTextPadding(155); - tft.drawRightString("---", 230, 155, 1); + tft.setTextPadding(280); + tft.drawCentreString("---", 160, 155, 1); tft.setTextPadding(0); tft.unloadFont(); } else { // Digital numeric mode full screen with DSEG7 Smooth Font (Anti-Aliased) tft.loadFont(DSEG7_Modern_BoldItalic_80); tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.setTextPadding(295); - tft.drawRightString("---", 295, 98, 1); + tft.setTextPadding(300); + tft.drawRightString("---", 305, 98, 1); tft.setTextPadding(0); tft.unloadFont(); } @@ -565,16 +565,16 @@ void plotFullScreen(uint8_t cell, float data, int warn, int min, int max, // Value below the arc using DSEG7 Modern smooth font tft.loadFont(DSEG7_Modern_BoldItalic_80); tft.setTextColor(col, TFT_BLACK); - tft.setTextPadding(155); - tft.drawRightString(numStr.c_str(), 230, 155, 1); + tft.setTextPadding(280); + tft.drawCentreString(numStr.c_str(), 160, 155, 1); tft.setTextPadding(0); tft.unloadFont(); } else { // Digital numeric mode full screen with DSEG7 Smooth Font (Anti-Aliased) tft.loadFont(DSEG7_Modern_BoldItalic_80); tft.setTextColor(col, TFT_BLACK); - tft.setTextPadding(295); - tft.drawRightString(numStr.c_str(), 295, 98, 1); + tft.setTextPadding(300); + tft.drawRightString(numStr.c_str(), 305, 98, 1); tft.setTextPadding(0); tft.unloadFont(); } @@ -611,36 +611,44 @@ void initScreen() { // get A B from response return in global A B variable void getAB(String elm_rsp) { // 41 05 2A 3C 01> - if (elm_rsp == "NO DATA\r\r>") { // pid no data + if (pidList[pidIndex] == "ATRV") { + return; + } + if (elm_rsp.indexOf("NO DATA") != -1) { // pid no data A = 0; B = 0; - - } else { - // check if pid is 2 or 3 command length. - uint8_t charcnt = pidList[pidIndex].length() / 2; // 0105->2,221E1C->3 - String strs[8]; - uint8_t StringCount = 0; - while (elm_rsp.length() > 0) { // keep reading each char - int index = elm_rsp.indexOf(' '); // check space - if (index == -1) // No space found - { // only data without space is now in strs {41,05,aa,bb} - strs[StringCount++] = elm_rsp; // last byte + return; + } + // check if pid is 2 or 3 command length. + uint8_t charcnt = pidList[pidIndex].length() / 2; // 0105->2,221E1C->3 + String strs[8]; + uint8_t StringCount = 0; + while (elm_rsp.length() > 0) { // keep reading each char + int index = elm_rsp.indexOf(' '); // check space + if (index == -1) // No space found + { // only data without space is now in strs {41,05,aa,bb} + strs[StringCount++] = elm_rsp; // last byte + if (StringCount > charcnt + 1) { A = strtol(strs[charcnt].c_str(), NULL, 16); // byte 3 save to A B = strtol(strs[charcnt + 1].c_str(), NULL, 16); // byte 4 save to B - break; - } else { // found space - strs[StringCount++] = - elm_rsp.substring(0, index); // copy strings from 0 to space to strs - elm_rsp = elm_rsp.substring(index + - 1); // copy the rest behind space to elm_rsp + } else if (StringCount > charcnt) { + A = strtol(strs[charcnt].c_str(), NULL, 16); + B = 0; } - } // while - } // else + break; + } else { // found space + strs[StringCount++] = + elm_rsp.substring(0, index); // copy strings from 0 to space to strs + elm_rsp = elm_rsp.substring(index + + 1); // copy the rest behind space to elm_rsp + if (StringCount >= 7) break; + } + } // while } // getAB /*-------------------------------*/ // check engine status if off then turn off gauge -void engine_onoff(float data, uint8_t pid) { // use pcm volt - if (pidList[pid] == "0142") { // pcm voltage +void engine_onoff(float data, uint8_t pid) { // use pcm volt or ATRV + if (pidList[pid] == "0142" || pidList[pid] == "ATRV") { // pcm voltage or ATRV if (data > 0.5 && data < ecu_off_volt) engine_off_count++; else if (data >= ecu_off_volt) @@ -716,10 +724,27 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen case 7: data = A; // km/h (PID 010D Vehicle Speed) break; + case 8: { + // Battery Voltage from ELM327 command "ATRV" (e.g. "14.2V\r\r>") + String s = response; + s.trim(); + int vIdx = s.indexOf('V'); + if (vIdx == -1) vIdx = s.indexOf('v'); + if (vIdx != -1) s = s.substring(0, vIdx); + int lastSpace = s.lastIndexOf(' '); + if (lastSpace != -1) s = s.substring(lastSpace + 1); + int lastCr = s.lastIndexOf('\r'); + if (lastCr != -1) s = s.substring(lastCr + 1); + int lastLf = s.lastIndexOf('\n'); + if (lastLf != -1) s = s.substring(lastLf + 1); + s.trim(); + data = s.toFloat(); + break; + } } - // Engine off check if PCM volt - if (pidConfig[pidIdx][2] == "0142") { + // Engine off check if PCM volt or ATRV + if (pidConfig[pidIdx][2] == "0142" || pidConfig[pidIdx][2] == "ATRV") { engine_onoff(data, pidNo); } diff --git a/sketch/obd2_gauge/obd2_gauge.ino b/sketch/obd2_gauge/obd2_gauge.ino index 7dd00cb..f27bda2 100644 --- a/sketch/obd2_gauge/obd2_gauge.ino +++ b/sketch/obd2_gauge/obd2_gauge.ino @@ -85,7 +85,7 @@ const String pidConfig[4][9] = { //[pid][data] { "Refrigerante", "`C", "0105", "1", "0", "120", "2", "0", "100" }, //0 = Refrigerante (0105) { "Revoluciones", "rpm", "010C", "3", "0", "6000", "0", "0", "5000" }, //1 = Revoluciones (010C) - { "Voltaje", "V", "0142", "4", "0", "16", "1", "1", "15" }, //2 = Voltaje (0142) + { "Voltaje", "V", "ATRV", "8", "0", "16", "1", "1", "15" }, //2 = Voltaje BaterĂ­a (ATRV) { "Velocidad", "km/h", "010D", "7", "0", "180", "0", "0", "130" } //3 = Velocidad (010D) }; @@ -380,24 +380,29 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6] bt_message = ""; for (uint8_t initIndex = 0; initIndex < elm327InitCount; initIndex++) { //send init ELM327 AT command BTSerial.print(elm327Init[initIndex] + "\r"); - if (initIndex == elm327InitCount - 1) delay(2000); //wait for 0100 Searching..protocal - else delay(100); //must add delay , unless will skip BTSerial.avaialble>0 - while (BTSerial.available() > 0) { - char incomingChar = BTSerial.read(); - if (incomingChar == '>') { //check prompt - BTSerial.flush(); //clear buffer + uint32_t waitTimeout = (initIndex == elm327InitCount - 1) ? 5000 : 1500; + uint32_t startWait = millis(); + while (millis() - startWait < waitTimeout) { + if (BTSerial.available() > 0) { + char incomingChar = BTSerial.read(); + if (incomingChar == '>') { //check prompt + BTSerial.flush(); //clear buffer #ifdef SERIAL_DEBUG - Serial.println(bt_message); + Serial.println(bt_message); #endif #ifdef TERMINAL - Terminal(bt_message, 0, 48, 320, 191); + Terminal(bt_message, 0, 48, 320, 191); #endif - if (initIndex == 1) BTSerial.print("\r"); //ATBRD23 response - bt_message = ""; + if (initIndex == 1) BTSerial.print("\r"); //ATBRD23 response + bt_message = ""; + break; + } else { + bt_message.concat(incomingChar); //keep elm327 respond + } } else { - bt_message.concat(incomingChar); //keep elm327 respond + delay(10); } - } //while + } //while waitTimeout } //for initScreen(); @@ -508,6 +513,18 @@ void loop() { } //---------------------- //BLUETOOTH read + static uint32_t lastPidSendTime = 0; + // Watchdog: If waiting for prompt for more than 1500ms, recover! + if (!prompt && (millis() - lastPidSendTime > 1500)) { +#ifdef SERIAL_DEBUG + Serial.printf("PID timeout for %s, recovering...\n", pidList[pidIndex].c_str()); +#endif + BTSerial.flush(); + bt_message = ""; + prompt = true; + skip = true; + } + while (BTSerial.available() > 0) { char incomingChar = BTSerial.read(); if (incomingChar == '>') { //check prompt @@ -570,6 +587,7 @@ void loop() { pidCurrentSkip[pidIndex] = pidReadSkip[pidIndex]; //read max delay loop to current skip = false; BTSerial.print(pidList[pidIndex] + "\r"); //send PID request + lastPidSendTime = millis(); } else { //skip sending request pidCurrentSkip[pidIndex] = pidCurrentSkip[pidIndex] - 1; //decrese loop count prompt = true;