Unreliable Bluetooth Communication using Elmduino Library

Hi all,

I am using the ELMduino library with an Arduino Uno, HC05 bluetooth module and 20x4 LCD display.

I've gone into the AT settings menu on the HC05 (as shown here), and have successfully paired, bound and linked my ELM327 OBD dongle. As a side note, for anyone struggling at the HC05 stage, if your module has V3 firmware, try this link - it was the only source that worked for me. Anyway, this seems to work fine. On startup, the HC05 quickly flashes twice every 5s, which I believe means connected. Great.

I am struggling to establish reliable data transfer. At first I would constantly get the error "NO DATA" when using the debugging printout, but very occasionally a correct value would be sent over. I would say roughly every 20 seconds a correct RPM value is sent over. More often a value of 0 is sent over, and the vast majority of the time NO DATA is sent.

I was using SoftwareSerial, but have now switched to hardware using pins 0 and 1. Moving the HC05 closer to the ELM327 seems to make no difference so I don't think its a bluetooth signal issue. I am using soldered connections, and wiggling pins also seems to change nothing, so I don't think its a wiring issue. I'm almost more confused that it occasionally pings a correct value across.

The final idea is to display several PID values, which is why my code is adapted from the "multiple_pids" example in the library, but even when testing the "hardwareserial" example querying only RPM, the same very very sporadically successful behaviour was seen.

Any thoughts? Code below.

EDIT: I should also say I am using a voltage divider, and have checked voltages. In fact the USB cable I'm using was only giving around 4.5V, so resistances were adjusted to make sure the HC-05 datalines get 3.3V, so I don't think its that either.

One other potential clue is that even just setting the correct AT commands when pairing the HC05, signals always sent fine, and rarely ever failed, but the return message characters were very often garbled. For example sending like AT+UART?, which should return something like AT+UART:115,200,20, would actually send something like AT+UdRT:11f,20b,20. Not specifically, but often garbled.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include "ELMduino.h"

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#define ELM_PORT Serial
ELM327 myELM327;

typedef enum { RPM,
               COOLANT,
               AIR,
               OIL } obd_pid_states;
obd_pid_states obd_state = RPM;

float rpm = 0;
float coolant_temp = 0;
float air_temp = 0;
float oil_temp = 0;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("RPM:");
  lcd.setCursor(0, 1);
  lcd.print("Tc:");
  lcd.setCursor(0, 2);
  lcd.print("Ta:");
  lcd.setCursor(0, 3);
  lcd.print("To:");

  ELM_PORT.begin(115200);

  if (!myELM327.begin(ELM_PORT, false, 2000))
  {
    while (1);
  }
}

void loop() {

  switch (obd_state){
    case RPM: {
      float temp_rpm = myELM327.rpm();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS){
        rpm = temp_rpm;
        obd_state = COOLANT;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG){
        obd_state = COOLANT;
      }
      
      break;
    }
    
    case COOLANT:{
      float coolant_temp_temp = myELM327.engineCoolantTemp();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
        coolant_temp = coolant_temp_temp;
        obd_state = AIR;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        obd_state = AIR;
      }
      
      break;
    }

    case AIR:{
      float air_temp_temp = myELM327.intakeAirTemp();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
        air_temp = air_temp_temp;
        obd_state = OIL;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        obd_state = OIL;
      }
      
      break;
    }

    case OIL:{
      float oil_temp_temp = myELM327.oilTemp();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
        oil_temp = oil_temp_temp;
        obd_state = RPM;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        obd_state = RPM;
      }
      
      break;
    }
  }

  update_lcd();
   
}


void update_lcd(){
  lcd.setCursor(4, 0);
  lcd.print("                ");
  lcd.setCursor(4, 1);
  lcd.print("                ");
  lcd.setCursor(4, 2);
  lcd.print("                ");
  lcd.setCursor(4, 3);
  lcd.print("                ");
  
  lcd.setCursor(5, 0);
  lcd.print(rpm);
  lcd.setCursor(4, 1);
  lcd.print(coolant_temp);
  lcd.setCursor(4, 2);
  lcd.print(air_temp);
  lcd.setCursor(4, 3);
  lcd.print(oil_temp);
}

Just to add, when running the "Arduino_software_serial_test" from the examples folder, this is the error output.

Timeout detected with overflow of 0ms
Received: 0a0C1NODATA
ERROR: ELM_TIMEOUT
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
	Received char: 0
	Received char: \r
	Received char: a
	Received char: 0
	Received char: C
	Received char: 1
	Received char: \r
	Received char: N
	Received char: O
	Received char: _
	Received char: D
	Received char: A
	Received char: T
	Received char: A
	Received char: \r
	Received char: \r
	Received char: >
Delimiter found.
All chars received: 0a0C1NODATA
ELM responded with errror "NO DATA"
Received: 0a0C1NODATA
ERROR: ELM_NO_DATA
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
	Received char: 0
	Received char: 
	Received char: 1
	Received char: 0
	Received char: C
	Received char: 1
	Received char: \r
	Received char: N
	Received char: O
	Received char: _
	Received char: D
	Received char: A
	Received char: T
	Received char: A
	Received char: \r
	Received char: \r
	Received char: >
Delimiter found.
All chars received: 010C1NODATA
ELM responded with errror "NO DATA"
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1

If I turn debugging off, my terminal looks like this:

Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
RPM: 0
Received: 010C1NODATA
ERROR: ELM_NO_DATA
RPM: 0
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 0a0C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
RPM: 708
RPM: 0
RPM: 0
RPM: 0
Received: 01C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA
ERROR: ELM_NO_DATA
Received: 010C1NODATA

As you can see, just once does a valid RPM value get returned (the 708), with the occasional successful but wrong 0, and then NODATA for most of the time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.