Hi,
This is my first post, so hello everyone :).
Recently I struggle with a weird response from ELM327. It is acting correctly when I send/receive commands every 500+ms, but when I try do the same with 100ms intervals (I know, that ECU should not be queted more often than 100ms) - finally I get weird resonse. Additionaly, reseting NANO does not help. It starts acting properly after a few minutes of being disconnected.
The goal: get 5 PIDs with ~100ms intervals between each other.
Circuit: NANO, HC05 connected with 1k/2k voltage devider. Microswitch connected to D10 activates power (D12) to HC05 (through transistor).
The full code here:
#include <SoftwareSerial.h>
#define RxD 3
#define TxD 4
#define LED_BLINK_INTERVAL 500
#define LED_PIN 5
#define RPM "010C"
#define IAT "010F"
#define CLT "0105"
#define MAF "0110"
#define SPD "010D"
#define TPS "0111"
#define OBD_FREQ 100
#define MAX_INPUT 30
#define PID_ATTEMPTS_MAX 5
#define MSWITCH 10
#define BTSWITCH 12
SoftwareSerial bluetooth(RxD, TxD);
int btint = -1;
int ledblink = 0;
bool connection = false;
String ELManswer = "";
unsigned long now = 0;
unsigned long nowLED = 0;
bool PIDcorrect = false;
int currentPID = 0;
byte pid_read_switch = 0;
int PIDattempts = 0;
void readData() {
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;
byte inByte;
if (bluetooth.available() > 0) {
inByte = bluetooth.read();
switch (inByte) {
case '\n': // end of text
for (int i = 0; i < input_pos; i++) {
ELManswer = ELManswer + input_line[i];
}
input_line [input_pos] = 0;
input_pos = 0;
while (bluetooth.available() > 0) {
bluetooth.read();
}
break;
case '\r':
for (int i = 0; i < input_pos; i++) {
ELManswer = ELManswer + input_line[i];
}
input_line [input_pos] = 0;
input_pos = 0;
while (bluetooth.available() > 0) {
bluetooth.read();
}
break;
default:
if (input_pos < (MAX_INPUT - 1))
input_line [input_pos++] = inByte;
break;
}
}
}
void ELMinit() {
ELManswer="";
bluetooth.println("ATZ");
now = millis();
Serial.println("ATZ sent...");
while (ELManswer.substring(1, 4) != "ELM" && ELManswer.substring(0, 3) != "ELM" && digitalRead(MSWITCH) == HIGH && millis() - now <= 3000) {
readData();
LED_blink();
}
Serial.println(ELManswer);
if (ELManswer.substring(1, 4) == "ELM" || ELManswer.substring(0, 3) == "ELM") {
Serial.println("ELM connected, sending ATSP0 and 0100...");
bluetooth.println("ATSP3");
now = millis();
while (millis() - now <= 1000 && digitalRead(MSWITCH) == HIGH) {
readData();
LED_blink();
}
ELManswer = "";
bluetooth.println("0100");
now = millis();
while (millis() - now <= 5000 && digitalRead(MSWITCH) == HIGH) {
readData();
LED_blink();
}
connection = true;
digitalWrite(LED_PIN, HIGH);
Serial.println("Connected and initialized");
pid_read_switch = 0;
}
else {
Serial.println("no connection");
}
ELManswer = "";
}
void getPID(String PID) {
if (millis() - now >= OBD_FREQ) {
bluetooth.println(PID);
now = millis();
while (ELManswer == "" && digitalRead(MSWITCH) == HIGH) {
readData();
}
String checkPID = ELManswer.substring(9, 15);
checkPID.replace(" ", "");
if (checkPID == ("41" + PID.substring(2, 4))) {
PIDcorrect = true;
PIDattempts = 0;
}
else {
PIDcorrect = false;
PIDattempts++;
Serial.println(PIDattempts+ELManswer);
if (PIDattempts > PID_ATTEMPTS_MAX) {
connection = false;
PIDattempts = 0;
}
}
if ((PID == RPM || PID == MAF) && PIDcorrect == true) {
String pidString = ELManswer.substring(15, 21);
pidString.replace(" ", "");
currentPID = strtol(pidString.c_str(), NULL, 16);
if (PID == RPM) {
currentPID = currentPID / 4;
}
else { //MAF
currentPID = currentPID / 100;
}
}
else if ((PID == CLT || PID == IAT) && PIDcorrect == true) {
String pidString = ELManswer.substring(15, 18);
pidString.replace(" ", "");
currentPID = strtol(pidString.c_str(), NULL, 16) - 40;
}
else if (PID == TPS && PIDcorrect == true) {
String pidString = ELManswer.substring(15, 18);
pidString.replace(" ", "");
currentPID = strtol(pidString.c_str(), NULL, 16) * 100 / 255;
}
else if (PID == SPD && PIDcorrect == true) {
String pidString = ELManswer.substring(15, 18);
pidString.replace(" ", "");
currentPID = strtol(pidString.c_str(), NULL, 16);
}
// Serial.println(PID + ":" + ELManswer);
ELManswer = "";
}
else {
PIDcorrect = false;
}
}
void LED_blink() {
if (millis() - nowLED >= LED_BLINK_INTERVAL) {
if (digitalRead(LED_PIN) == HIGH) {
digitalWrite(LED_PIN, LOW);
nowLED = millis();
}
else {
digitalWrite(LED_PIN, HIGH);
nowLED = millis();
}
}
}
void setup() {
bluetooth.begin(9600);
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
pinMode(MSWITCH, INPUT_PULLUP);
pinMode(BTSWITCH, OUTPUT);
pinMode(RxD, INPUT);
pinMode(TxD, OUTPUT);
}
void loop() {
if (digitalRead(MSWITCH) == LOW) {
delay(250);
btint = btint * (-1);
}
if (btint == 1) {
// digitalWrite(LED_PIN, HIGH);
digitalWrite(BTSWITCH, HIGH);
if (connection == false) ELMinit();
}
else
{
digitalWrite(LED_PIN, LOW);
digitalWrite(BTSWITCH, LOW);
connection = false;
}
if (connection == true) {
switch (pid_read_switch) {
case 4: //RPM
getPID(RPM);
if (PIDcorrect == true) {
Serial.print("RPM:");
Serial.println(currentPID, DEC);
pid_read_switch++;
}
break;
case 3: //MAF
getPID(MAF);
if (PIDcorrect == true) {
Serial.print("MAF:");
Serial.println(currentPID, DEC);
pid_read_switch++;
}
break;
case 2: //TPS
getPID(TPS);
if (PIDcorrect == true) {
Serial.print("TPS:");
Serial.println(currentPID, DEC);
pid_read_switch++;
}
break;
case 1: //CLT
getPID(CLT);
if (PIDcorrect == true) {
Serial.print("CLT:");
Serial.println(currentPID, DEC);
pid_read_switch++;
}
break;
case 0: //IAT
getPID(IAT);
if (PIDcorrect == true) {
Serial.print("IAT:");
Serial.println(currentPID, DEC);
pid_read_switch++;
}
break;
case 5: //SPD
getPID(SPD);
if (PIDcorrect == true) {
Serial.print("SPD:");
Serial.println(currentPID, DEC);
pid_read_switch = 0;
}
break;
}
}
}
For sure my code contains a lot of beginner mistakes, but I’m doing my best.
As you can see on the image attached, everything works fine for a while and then crashes. “ATZ7 v2.1” (at the bottom) resonse is supposed to be “ELM327 v2.1” (on top). When I dosconnect NANO, it still replies with “ATZ…”. I have to leave it disconnected for a while to work fine again (for a few seconds).
EDIT: forgot to mention, that it is not ELM327 fault itself. It works and responses fine (when I send commands by my phone).
I have no idea why it happens. Really appreciate your help.
Thank you in advance.