How to connect HC-05

I hope there are some HC-05 experts as I am pulling my hair out at this!

I am trying to connect my HC-05 to an ELM327 OBD2 bluetooth connector.

The only micro controller that I have to hand at the minute is a Wemos D1 mini, not ideal as there are only one set of serial pins and they are shared with the USB.

So I have connected the HC-05 as follows:
Wemos → HC-05
5v → 5v (vin)
gnd → gnd
RX → TX
TX → RX

I have an I2C LCD display also connected as I can’t use the serial monitor. I am doing the AT Commands in code.

I am powering the Wemos with the 5v pin.

My AT Command code looks like:

#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

const byte rxPin = 3; // Wire this to Tx Pin of ESP8266
const byte txPin = 1; // Wire this to Rx Pin of ESP8266

// We'll use a software serial interface to connect to ESP8266
SoftwareSerial bt_serial(rxPin, txPin);

void setup()
{
    delay(7000);
    bt_serial.begin(38400); // Change this to the baudrate used by ESP8266

    // Initialize the LCD
    lcd.init();
    lcd.backlight();

    delay(1000);

    lcd.setCursor(0, 0);
    lcd.print("Sending AT");
    bt_serial.println("AT");
    delay(1000);
    String in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();

//    lcd.setCursor(0, 0);
//    lcd.print("Sending AT+INQC");
//    bt_serial.println("AT+INQC");
//    delay(1000);
//    in_data = bt_serial.readStringUntil('\n');
//    lcd.setCursor(0, 1);
//    lcd.print("Response:");
//    lcd.setCursor(0, 2);
//    lcd.print(in_data);
//    delay(2000);
//    lcd.clear();

    lcd.setCursor(0, 0);
    lcd.print("Sending AT+UART?");
    bt_serial.println("AT+UART?");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+ORGL");
    bt_serial.println("AT+ORGL");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+ROLE=1");
    bt_serial.println("AT+ROLE=1");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+RESET");
    bt_serial.println("AT+RESET");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+ADCN?");
    bt_serial.println("AT+ADCN?");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+RMAAD");
    bt_serial.println("AT+RMAAD");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+PAIR");
    bt_serial.println("AT+PAIR=001D,A5,68988C,20");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+BIND");
    bt_serial.println("AT+BIND=001D,A5,68988C");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
    delay(2000);
    lcd.clear();


    lcd.setCursor(0, 0);
    lcd.print("Sending AT+LINK");
    bt_serial.println("AT+LINK=001D,A5,68988C");
    delay(1000);
    in_data = bt_serial.readStringUntil('\n');
    lcd.setCursor(0, 1);
    lcd.print("Response:");
    lcd.setCursor(0, 2);
    lcd.print(in_data);
}

void loop()
{
}

I got the MAC of the ELM327 by connecting it to my Mac and finding out there.
I hold the button on the HC-05 as I give it power and the LED does slow blinking.
All the commands come back with a response of OK. (sounds good)

I then load this code onto the wemos:

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

LiquidCrystal_I2C lcd(0x27, 20, 4);


SoftwareSerial mySerial(3, 1); // RX, TX
#define ELM_PORT mySerial


ELM327 myELM327;


uint32_t rpm = 0;


void setup()
{
    // Initialize the LCD
    lcd.init();
    lcd.backlight();

  ELM_PORT.begin(9600);

    lcd.setCursor(0, 0);
  lcd.print("Attempting connect");

  if (!myELM327.begin(ELM_PORT))
  {
    delay(2000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Failed connect");
    while (1);
  }

    delay(2000);
    lcd.clear();
    lcd.setCursor(0, 0);
  lcd.println("Connected to ELM327");
}


void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RPM: ");
    lcd.setCursor(0, 1);
    lcd.print(rpm);
  }
  else
  {
    lcd.clear();
    lcd.print(F("\tERROR: "));
//    Serial.println(myELM327.status);S
    delay(333);
  }
}

The LED on the HC-05 just blinks very fast (not sure what it is meant to do when connected) and it just says failed to connect :frowning:

What am I doing wrong?

I initially followed this:

But the link command always failed.

I then saw this:

This allowed me to get the link command to pass. I don’t understand the bit at the bottom with AT+DISC. I tried loading the above AT Commands, powering down, loading code with just AT, AT+DISC, AT+LINK. The DISC fails with something like NO_SLCE and the LINK just FAILs.

AT+PSWD? shows 1234 and this is correct for the ELM327.

Any help would be appreciated.

Are you using this

board to connect the HC-05?

Remove the LCD.

Get the HC-05 working first.
Google for Martyn Currey's tutorial about the HC-05. He uses an Arduino .

GolamMostafa:
Are you using this

board to connect the HC-05?

The board I'm using is similar but a bit different.
Attached a picture.

ieee488:
Remove the LCD.

Get the HC-05 working first.
Google for Martyn Currey’s tutorial about the HC-05. He uses an Arduino .

I can’t remove the LCD, it is the only way that I can see what the AT commands return. I can’t use the serial monitor as the usb serial uses the same serial bus as the tx/rx pins that the HC-05 uses (I think thats the correct terminology).

I have used the lcd on its own and with neopixels etc before and had no bother so hopefully its not an issue.

Seems to be easier to use an arduino as it has two serial buses so can use the serial monitor to input the AT Commands

That guide that you pointed out is very good, I used it to find out the firmware of my HC-05. My firmware is 3.0-20170601 which different to his :frowning:

The HC-05 can be connected to another set of pins on the Arduino and use something like SoftwareSerial to communicate with it. And write debug messages to Serial Monitor.

.

If you look here you can see what I did to connect my HC-05 to my ELM327:

  • AT+UART=115200,0,0
  • AT+CMODE=0
  • AT+ROLE=1
  • AT+RESET
  • AT+INQM=0,5,9
  • AT+INIT
  • AT+INQ
    (discovered the address of the OBD-II scanner is 1D:A5:1F16BB - yours might be different)
  • AT+PAIR=1D,A5,1F16BB,20
  • AT+BIND=1D,A5,1F16BB
  • AT+LINK=1D,A5,1F16BB
  • AT+RESET

ieee488:
The HC-05 can be connected to another set of pins on the Arduino and use something like SoftwareSerial to communicate with it. And write debug messages to Serial Monitor.

.

Unfortunately I couldn’t get that to work with the board I’m using. I think you can only do TX with one of the other GPIO pins. But not RX.

Power_Broker:
If you look here you can see what I did to connect my HC-05 to my ELM327:

Thanks :slight_smile: I’ll give this a go. Do you know if your HC-05 was v2 or v3 firmware?
I found that you might have to enter the pair, bind and link commands in a different AT mode for v3. You hold the button after startup instead of before.
After its setup with the AT commands Can I just upload some code using ELMduino and I don’t have to worry about the bluetooth it will auto connect? (This might be a silly question sorry)

I see on the ELMduino there is examples for esp32. I have one of these ordered so I don’t have to use a separate HC-05. Are these setup using the same AT commands?

Thanks

av4625:
Thanks :slight_smile: I'll give this a go. Do you know if your HC-05 was v2 or v3 firmware?

I honestly don't know

av4625:
After its setup with the AT commands Can I just upload some code using ELMduino and I don't have to worry about the bluetooth it will auto connect? (This might be a silly question sorry)

Yes, the AT commands are only a one-time necessity and the devices will automatically re-connect on startup.

av4625:
I see on the ELMduino there is examples for esp32. I have one of these ordered so I don't have to use a separate HC-05. Are these setup using the same AT commands?

The really nice thing about the ESP32 is that you don't need AT commands at all to connect to the ELM327. Just make sure the ELM327 isn't already connected to a device, load the sketch and watch it work!

av4625:
Unfortunately I couldn't get that to work with the board I'm using. I think you can only do TX with one of the other GPIO pins. But not RX.

So it turns out I completely lied here, I tried to get this to work for ages earlier and it wouldn't. Must have had a stupid bug somewhere as I can get it to work now. Will try this with Power_Broker's commands tomorrow with the ELM327. I'll also try with the different AT command modes for v3 HC-05's

Thanks everyone

Power_Broker:
The really nice thing about the ESP32 is that you don't need AT commands at all to connect to the ELM327. Just make sure the ELM327 isn't already connected to a device, load the sketch and watch it work!

This sounds awesome! How does it know what to connect to!? Does it need the mac address of the ELM327? I saw the ELMduino examples using BluetoothSerial instead of SoftwareSerial!

Is there much lag with bluetooth? I want to get rpm data.

av4625:
Does it need the mac address of the ELM327?

I think it is possible to use the MAC address, but you don't need it. Pretty much all ELM327 scanners have the name "OBDII" as their bluetooth device names. This name is used to automatically connect the ESP32 to the ELM327.

av4625:
I saw the ELMduino examples using BluetoothSerial instead of SoftwareSerial!

Yes, it has bluetooth built-in to the board, so SoftwareSerial isn't needed.

av4625:
Is there much lag with bluetooth? I want to get rpm data.

Not too much lag. You can get a response from a single query in about 0.1 seconds.

Power_Broker:
I think it is possible to use the MAC address, but you don't need it. Pretty much all ELM327 scanners have the name "OBDII" as their bluetooth device names. This name is used to automatically connect the ESP32 to the ELM327.

Yes, it has bluetooth built-in to the board, so SoftwareSerial isn't needed.

Not too much lag. You can get a response from a single query in about 0.1 seconds.

That sounds very handy!

Thanks for all the answers! I appreciate it!

Got it to connect today :slight_smile: had to use the second AT command mode for pair, bind and link.

Only issue I have now is that I want to fast blink a neopixel when the RPM is over a certain value. Because the get rpm function blocks and waits obviously it makes the pixel blink strangely.

Basically doing something similar to blink without delay. Pixel blinks every 75 milliseconds and I read rpm every 150 milliseconds. But it takes the get rpm command just over 100 milliseconds to complete.

Might need a second microcontroller to control the pixel.

Thanks Everyone

av4625:
Only issue I have now is that I want to fast blink a neopixel when the RPM is over a certain value. Because the get rpm function blocks and waits obviously it makes the pixel blink strangely.

Yeah, sorry about that, I'll probably get around to making the library non-blocking one day (it'll take quite an effort)...

Power_Broker:
Yeah, sorry about that, I’ll probably get around to making the library non-blocking one day (it’ll take quite an effort)…

Yea defo not easy on a 1 core microcontroller. I’m not even sure how to do that for a library. I’m used to working on a single threaded async event driven system. But we don’t need specific timing like blink a pixel every 75ms while doing something else.

I just found out that the ESP32’s that are getting delivered tomorrow have 2 cores! I bought them so I wouldn’t need a separate HC-05. I can read data on one core and do pixel stuff on the other core. Hopefully it’s as easy as it sounds.

EDIT: I guess you could have functions that would query if there was a response and then another that would get the response if it was there. But that changes the whole “look” to the library