Mejoras de funcionamiento: robustez en parser getAB y timeout de comunicacion OBD2
This commit is contained in:
parent
98bbbf0109
commit
658cb520d7
2 changed files with 94 additions and 52 deletions
|
|
@ -634,40 +634,87 @@ void initScreen() {
|
||||||
/*-------------------------------*/
|
/*-------------------------------*/
|
||||||
|
|
||||||
// get A B from response return in global A B variable
|
// get A B from response return in global A B variable
|
||||||
void getAB(String elm_rsp) { // 41 05 2A 3C 01>
|
void getAB(String elm_rsp, String currentPid) { // 41 05 2A 3C 01>
|
||||||
if (pidList[pidIndex] == "ATRV") {
|
A = 0;
|
||||||
|
B = 0;
|
||||||
|
if (currentPid == "ATRV") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (elm_rsp.indexOf("NO DATA") != -1) { // pid no data
|
if (elm_rsp.indexOf("NO DATA") != -1 ||
|
||||||
A = 0;
|
elm_rsp.indexOf("UNABLE") != -1 ||
|
||||||
B = 0;
|
elm_rsp.indexOf("ERROR") != -1 ||
|
||||||
|
elm_rsp.indexOf("STOPPED") != -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check if pid is 2 or 3 command length.
|
|
||||||
uint8_t charcnt = pidList[pidIndex].length() / 2; // 0105->2,221E1C->3
|
// Normalize: replace carriage returns, newlines, and prompt chars with spaces
|
||||||
String strs[8];
|
elm_rsp.replace('\r', ' ');
|
||||||
uint8_t StringCount = 0;
|
elm_rsp.replace('\n', ' ');
|
||||||
while (elm_rsp.length() > 0) { // keep reading each char
|
elm_rsp.replace('>', ' ');
|
||||||
int index = elm_rsp.indexOf(' '); // check space
|
|
||||||
if (index == -1) // No space found
|
// Extract expected PID hex byte (e.g. "0105" -> "05", "010C" -> "0C", "010D" -> "0D")
|
||||||
{ // only data without space is now in strs {41,05,aa,bb}
|
String pidByte = (currentPid.length() >= 4) ? currentPid.substring(2) : currentPid;
|
||||||
strs[StringCount++] = elm_rsp; // last byte
|
pidByte.toUpperCase();
|
||||||
if (StringCount > charcnt + 1) {
|
|
||||||
A = strtol(strs[charcnt].c_str(), NULL, 16); // byte 3 save to A
|
// 1. Tokenized search: look for "41" followed by PID byte
|
||||||
B = strtol(strs[charcnt + 1].c_str(), NULL, 16); // byte 4 save to B
|
String tokens[16];
|
||||||
} else if (StringCount > charcnt) {
|
uint8_t tokenCount = 0;
|
||||||
A = strtol(strs[charcnt].c_str(), NULL, 16);
|
int startIdx = 0;
|
||||||
B = 0;
|
while (startIdx < elm_rsp.length() && tokenCount < 16) {
|
||||||
}
|
while (startIdx < elm_rsp.length() && elm_rsp.charAt(startIdx) == ' ') {
|
||||||
break;
|
startIdx++;
|
||||||
} 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
|
if (startIdx >= elm_rsp.length()) break;
|
||||||
|
int endIdx = elm_rsp.indexOf(' ', startIdx);
|
||||||
|
if (endIdx == -1) endIdx = elm_rsp.length();
|
||||||
|
tokens[tokenCount++] = elm_rsp.substring(startIdx, endIdx);
|
||||||
|
startIdx = endIdx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < tokenCount; i++) {
|
||||||
|
tokens[i].toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i + 1 < tokenCount; i++) {
|
||||||
|
if (tokens[i] == "41" && tokens[i + 1] == pidByte) {
|
||||||
|
if (i + 2 < tokenCount) {
|
||||||
|
A = strtol(tokens[i + 2].c_str(), NULL, 16);
|
||||||
|
}
|
||||||
|
if (i + 3 < tokenCount) {
|
||||||
|
B = strtol(tokens[i + 3].c_str(), NULL, 16);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Compact string fallback (in case adapter sends responses without spaces, e.g. "410D32")
|
||||||
|
String compact = "";
|
||||||
|
for (int i = 0; i < elm_rsp.length(); i++) {
|
||||||
|
char c = elm_rsp.charAt(i);
|
||||||
|
if (c != ' ') compact += (char)toupper(c);
|
||||||
|
}
|
||||||
|
String targetPrefix = "41" + pidByte;
|
||||||
|
int fIdx = compact.indexOf(targetPrefix);
|
||||||
|
if (fIdx != -1) {
|
||||||
|
int dataIdx = fIdx + targetPrefix.length();
|
||||||
|
if (dataIdx + 2 <= compact.length()) {
|
||||||
|
A = strtol(compact.substring(dataIdx, dataIdx + 2).c_str(), NULL, 16);
|
||||||
|
}
|
||||||
|
if (dataIdx + 4 <= compact.length()) {
|
||||||
|
B = strtol(compact.substring(dataIdx + 2, dataIdx + 4).c_str(), NULL, 16);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Positional fallback as in original author code
|
||||||
|
uint8_t charcnt = currentPid.length() / 2;
|
||||||
|
if (tokenCount > charcnt + 1) {
|
||||||
|
A = strtol(tokens[charcnt].c_str(), NULL, 16);
|
||||||
|
B = strtol(tokens[charcnt + 1].c_str(), NULL, 16);
|
||||||
|
} else if (tokenCount > charcnt) {
|
||||||
|
A = strtol(tokens[charcnt].c_str(), NULL, 16);
|
||||||
|
B = 0;
|
||||||
|
}
|
||||||
} // getAB
|
} // getAB
|
||||||
/*-------------------------------*/
|
/*-------------------------------*/
|
||||||
void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
|
void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
|
||||||
|
|
@ -684,7 +731,7 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
|
||||||
bool digit = pidConfig[pidIdx][7].toInt();
|
bool digit = pidConfig[pidIdx][7].toInt();
|
||||||
int warn = warningValue[pidIdx].toInt();
|
int warn = warningValue[pidIdx].toInt();
|
||||||
|
|
||||||
getAB(response);
|
getAB(response, pidList[pidNo]);
|
||||||
float data = 0.0;
|
float data = 0.0;
|
||||||
switch (formula) {
|
switch (formula) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -705,12 +752,12 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
|
||||||
case 5:
|
case 5:
|
||||||
data = (256 * A + B) / 16.0;
|
data = (256 * A + B) / 16.0;
|
||||||
if (data > 150 || data < 0)
|
if (data > 150 || data < 0)
|
||||||
data = old_data[pidIndex];
|
data = old_data[pidNo];
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
data = (A * 256 + B) * 5 / 72 - 18;
|
data = (A * 256 + B) * 5 / 72 - 18;
|
||||||
if (data > 150 || data < 0)
|
if (data > 150 || data < 0)
|
||||||
data = old_data[pidIndex];
|
data = old_data[pidNo];
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
data = A; // km/h (PID 010D Vehicle Speed)
|
data = A; // km/h (PID 010D Vehicle Speed)
|
||||||
|
|
|
||||||
|
|
@ -327,29 +327,24 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
|
||||||
bt_message = "";
|
bt_message = "";
|
||||||
for (uint8_t initIndex = 0; initIndex < elm327InitCount; initIndex++) { //send init ELM327 AT command
|
for (uint8_t initIndex = 0; initIndex < elm327InitCount; initIndex++) { //send init ELM327 AT command
|
||||||
BTSerial.print(elm327Init[initIndex] + "\r");
|
BTSerial.print(elm327Init[initIndex] + "\r");
|
||||||
uint32_t waitTimeout = (initIndex == elm327InitCount - 1) ? 5000 : 1500;
|
if (initIndex == elm327InitCount - 1) delay(2000); //wait for 0100 Searching..protocal
|
||||||
uint32_t startWait = millis();
|
else delay(100); //must add delay , unless will skip BTSerial.avaialble>0
|
||||||
while (millis() - startWait < waitTimeout) {
|
while (BTSerial.available() > 0) {
|
||||||
if (BTSerial.available() > 0) {
|
char incomingChar = BTSerial.read();
|
||||||
char incomingChar = BTSerial.read();
|
if (incomingChar == '>') { //check prompt
|
||||||
if (incomingChar == '>') { //check prompt
|
BTSerial.flush(); //clear buffer
|
||||||
BTSerial.flush(); //clear buffer
|
|
||||||
#ifdef SERIAL_DEBUG
|
#ifdef SERIAL_DEBUG
|
||||||
Serial.println(bt_message);
|
Serial.println(bt_message);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TERMINAL
|
#ifdef TERMINAL
|
||||||
Terminal(bt_message, 0, 48, 320, 191);
|
Terminal(bt_message, 0, 48, 320, 191);
|
||||||
#endif
|
#endif
|
||||||
if (initIndex == 1) BTSerial.print("\r"); //ATBRD23 response
|
if (initIndex == 1) BTSerial.print("\r"); //ATBRD23 response
|
||||||
bt_message = "";
|
bt_message = "";
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
bt_message.concat(incomingChar); //keep elm327 respond
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delay(10);
|
bt_message.concat(incomingChar); //keep elm327 respond
|
||||||
}
|
}
|
||||||
} //while waitTimeout
|
} //while
|
||||||
} //for
|
} //for
|
||||||
|
|
||||||
initScreen();
|
initScreen();
|
||||||
|
|
@ -461,8 +456,8 @@ void loop() {
|
||||||
//----------------------
|
//----------------------
|
||||||
//BLUETOOTH read
|
//BLUETOOTH read
|
||||||
static uint32_t lastPidSendTime = 0;
|
static uint32_t lastPidSendTime = 0;
|
||||||
// Watchdog: If waiting for prompt for more than 1500ms, recover!
|
// Watchdog: If waiting for prompt for more than 6000ms (standard OBD2 maximum ECU timeout), recover!
|
||||||
if (!prompt && (millis() - lastPidSendTime > 1500)) {
|
if (!prompt && (millis() - lastPidSendTime > 6000)) {
|
||||||
#ifdef SERIAL_DEBUG
|
#ifdef SERIAL_DEBUG
|
||||||
Serial.printf("PID timeout for %s, recovering...\n", pidList[pidIndex].c_str());
|
Serial.printf("PID timeout for %s, recovering...\n", pidList[pidIndex].c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -480,7 +475,7 @@ void loop() {
|
||||||
Serial.println(bt_message);
|
Serial.println(bt_message);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TERMINAL //for degbugging
|
#ifdef TERMINAL //for degbugging
|
||||||
getAB(bt_message);
|
getAB(bt_message, pidList[pidIndex]);
|
||||||
Terminal(bt_message + "->" + String(A) + "," + String(B), 0, 48, 320, 191);
|
Terminal(bt_message + "->" + String(A) + "," + String(B), 0, 48, 320, 191);
|
||||||
#endif
|
#endif
|
||||||
prompt = true; //pid response ready to calculate & display
|
prompt = true; //pid response ready to calculate & display
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue