PowerBroker2 / ELMduino

Arduino OBD-II Bluetooth Scanner Interface Library for Car Hacking Projects
MIT License
587 stars 117 forks source link

Reading more values #208

Closed Janek4 closed 5 months ago

Janek4 commented 6 months ago

Hi, I need to read and print more values like speed, rpms, traveled distance, bat. voltage, fuel consumption, etc.... I'm beginner in arduino and ESP. So I modified the code and naively thought that maybe it could work. I have ESP32-DevKitC and ELM327 v1.5

'#include "BluetoothSerial.h"
#include "ELMduino.h"

BluetoothSerial SerialBT;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial

ELM327 myELM327;

void setup() {
#if LED_BUILTIN
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
#endif
    DEBUG_PORT.begin(115200);
    //SerialBT.setPin("1234");
    ELM_PORT.begin("OBD II", true);

    if (!ELM_PORT.connect("OBD II")) {
        DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1");
        while (1);
    }

    if (!myELM327.begin(ELM_PORT, true, 2000)) {
        Serial.println("Couldn't connect to OBD scanner - Phase 2");
        while (1);
    }

    Serial.println("Connected to ELM327");
}

void loop() {
    //time = millis();
    float rpm = myELM327.rpm();
    float kph = myELM327.kph();
    float temp = myELM327.engineCoolantTemp();
    float volts = myELM327.batteryVoltage();
    if (myELM327.nb_rx_state == ELM_SUCCESS) {
        Serial.print("Battery Voltage: ");
        Serial.println(volts);
        //delay();
    }
    else if (myELM327.nb_rx_state != ELM_GETTING_MSG) {
        myELM327.printError();
    }

    if (myELM327.nb_rx_state == ELM_SUCCESS) {
        Serial.print("RPMS: ");
        Serial.println(rpm);
        //delay();
    }
    else if (myELM327.nb_rx_state != ELM_GETTING_MSG) {
        myELM327.printError();
    }
    if (myELM327.nb_rx_state == ELM_SUCCESS) {
        Serial.print("SPEED in KM/H: ");
        Serial.println(kph);
        //delay();
    }
    else if (myELM327.nb_rx_state != ELM_GETTING_MSG) {
        myELM327.printError();
    }
    if (myELM327.nb_rx_state == ELM_SUCCESS) {
        Serial.print("Coolant Temp.: ");
        Serial.println(temp);
        //delay();
    }
    else if (myELM327.nb_rx_state != ELM_GETTING_MSG) {
        myELM327.printError();
    }
}'
jimwhitelaw commented 6 months ago

That loop isn’t going to work. Have a look at the multiple pids example program. You need to manage the query state to only query one value at a time (repeatedly) until you get a result, then move to the next one.

Janek4 commented 6 months ago

That loop isn’t going to work. Have a look at the multiple pids example program. You need to manage the query state to only query one value at a time (repeatedly) until you get a result, then move to the next one.

so this "should" work?

#include "ELMduino.h"
#define ELM_PORT Serial1

const bool DEBUG        = true;
const int  TIMEOUT      = 2000;
const bool HALT_ON_FAIL = false;

ELM327 ELMo;

typedef enum { ENG_RPM, SPEED, TEMPERATURE, VOLTAGE} obd_pid_states;
obd_pid_states obd_state = ENG_RPM;

float rpm = 0;
float kph = 0;
float temp = 0;
float volt = 0;

void setup() {
  Serial.begin(115200);
  ELM_PORT.begin(115200);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELMo.begin(ELM_PORT, DEBUG, TIMEOUT)) {
    Serial.println("Couldn't connect to OBD scanner");

    if (HALT_ON_FAIL)
      while (1);
  }

  Serial.println("Connected to ELM327");
}

void loop() {
  switch (obd_state) {
    case ENG_RPM: {
      rpm = ELMo.rpm();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("rpm: ");
        Serial.println(rpm);
        obd_state = SPEED;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = SPEED;
      }
      break;
    }

    case SPEED: {
      kph = ELMo.kph();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("kph: ");
        Serial.println(kph);
        obd_state = TEMPERATURE;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = TEMPERATURE;
      }
      break;
    }

    case TEMPERATURE: {
      temp = ELMo.engineCoolantTemp();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("temp: ");
        Serial.println(temp);
        obd_state = VOLTAGE;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = VOLTAGE;
      }
      break;
    }

    case VOLTAGE: {
      volt = ELMo.batteryVoltage();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("volt: ");
        Serial.println(volt);
        obd_state = ENG_RPM;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = ENG_RPM;
      }
      break;
    }
  }
}
PowerBroker2 commented 6 months ago

Please format your code correctly to make it easier to analyze

jimwhitelaw commented 6 months ago

@Janek4, yes that looks like it "should" work. Give it a try!

Janek4 commented 6 months ago

Am I missing something? How do i connect it to elm?

jimwhitelaw commented 6 months ago

This bit of code here is handling the connection.

    //SerialBT.setPin("1234");
    ELM_PORT.begin("OBD II", true);

    if (!ELM_PORT.connect("OBD II")) {
        DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1");
        while (1);
    }

    if (!myELM327.begin(ELM_PORT, true, 2000)) {
        Serial.println("Couldn't connect to OBD scanner - Phase 2");
        while (1);
    }

    Serial.println("Connected to ELM327");

If it's not working, try:

  1. Double check the correct Bluetooth name and pin (if any) of your device. Get this by plugging in the ELM device and getting the info with a phone.
  2. If those are correct and it's still not working, please post your debug (serial) output.
Janek4 commented 6 months ago

well now it works fine, but in serial monitor is this message "ASSERT_WARN(1 8), in lc_task.c at line 1408"

image

code:

#include <BluetoothSerial.h>
#include "ELMduino.h"

const bool DEBUG        = true;
const int  TIMEOUT      = 2000;
const bool HALT_ON_FAIL = false;
BluetoothSerial SerialBT;
ELM327 ELMo;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial

typedef enum {ENG_RPM, SPEED, TEMPERATURE, VOLTAGE} obd_pid_states;
obd_pid_states obd_state = ENG_RPM;

float rpm = 0;
float kph = 0;
float temp = 0;
float volt = 0;

void setup() {
  Serial.begin(115200);
  ELM_PORT.begin(115200);
  //SerialBT.setPin("1234");
  ELM_PORT.begin("OBD II", true);
  if (!ELM_PORT.connect("OBD II")) {
      DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1");
      while (1);
  }

  if (!ELMo.begin(ELM_PORT, true, 2000)) {
      Serial.println("Couldn't connect to OBD scanner - Phase 2");
      while (1);
  }

  Serial.println("Connected to ELM327");
}
void loop() {
  switch (obd_state) {
    case ENG_RPM: {
      rpm = ELMo.rpm();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("rpm: ");
        Serial.println(rpm);
        obd_state = SPEED;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = SPEED;
      }
      break;
    }

    case SPEED: {
      kph = ELMo.kph();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("kph: ");
        Serial.println(kph);
        obd_state = TEMPERATURE;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = TEMPERATURE;
      }
      break;
    }

    case TEMPERATURE: {
      temp = ELMo.engineCoolantTemp();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("temp: ");
        Serial.println(temp);
        obd_state = VOLTAGE;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = VOLTAGE;
      }
      break;
    }

    case VOLTAGE: {
      volt = ELMo.batteryVoltage();
      if (ELMo.nb_rx_state == ELM_SUCCESS) {
        Serial.print("volt: ");
        Serial.println(volt);
        obd_state = ENG_RPM;
      }
      else if (ELMo.nb_rx_state != ELM_GETTING_MSG) {
        ELMo.printError();
        obd_state = ENG_RPM;
      }
      break;
    }
  }
}
PowerBroker2 commented 6 months ago

Your ESP32 may be faulty: https://github.com/PowerBroker2/ELMduino/issues/43#issuecomment-694024390

This may also provide some background (I haven't read the comments in detail, though): https://github.com/espressif/arduino-esp32/issues/6193

Janek4 commented 6 months ago

well...thanks a lot :)

jimwhitelaw commented 6 months ago

@Janek4, I will just add a bit of info about what I see happening. The ELM327 datasheet (p. 88) says that "STOPPED" is returned if any OBD operation is interrupted by a received character. That might be a consequence of whatever is triggering the ASSERT_WARN message. Does your program continue to operate after seeing the ASSERT_WARN message?

Also, I'm not sure if it's relevant, but your debug output shows a battery voltage query, so I will mention it: The battery voltage query/response is different to other PID requests in that the ELM does not get the value from the ECU. Instead, the ELM chip reads the voltage at its own power input pin (from the OBDII plug) and returns that. That can be important for 2 reasons depending on how you are is using that value:

  1. It's not indicative of a valid connection from ELM to ECU.
  2. It's not the voltage value at the ECU or other components, only at the ELM device / OBDII port connector.
Janek4 commented 6 months ago

@jimwhitelaw yes, it continues after that message. And no, it's not relevant to me