Car Heads Up Display

I ordered one of these bad boys as my OBD-II interface. It is an ELM327-based OBD-II scanner with bluetooth compatibility. This device connects to the car's physical OBD port and reports car data over bluetooth. You also configure the device over bluetooth using custom AT commands.

I plugged it into my car, was able to connect to it with my laptop and send it AT commands over bluetooth. I was also able to monitor vehicle speed (in km/h) and engine RPM with the following commands and their responses:

To set up protocol --> AT SP 0
Response --> OK

To query vehicle speed --> 010D
Response --> 41 0D

To query engine RPM --> 010C
Response --> 41 0C

This website explains in better detail what the above commands do and how to interpret the responses.

I was also able to connect to the OBD scanner with my HC-05 bluetooth module. I wasn't able to successfully send commands with my HC-05, but that battle will be waged another day...

I was able to use the following demo code to quickly get my HC-05 talking with the ELM327:

// 1D,A5,1F16BB

//#define ATMODE 1

void setup()
{
  Serial.begin(115200);
  while(!Serial);

#ifdef ATMODE
  Serial2.begin(38400);
#else
  Serial2.begin(115200);
#endif

  while(!Serial2);
  Serial2.println("AT SP 0");
}

void loop()
{
  byte c;

 #ifdef ATMODE
  if(Serial.available())
  {
    c = Serial.read();
    Serial.write(c);
    Serial2.write(c);
  }

  if(Serial2.available())
  {
    c = Serial2.read();
    Serial.write(c);
  }
#else
  Serial2.println("010C");
  
  while(Serial2.available())
  {
    c = Serial2.read();
    Serial.write(c);
  }
  delay(100);
#endif
}

With line #3 uncommented, I entered the following commands after putting the HC-05 into AT mode:

  • AT
  • 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

Next, I uncommented line #3 and then reuploaded the code. Once the updated code was uploaded, it spat out raw dataframes at about 10Hz!

In order to make interfacing with the OBD scanner as easy as possible, I wrote a library for it: ELMduino GitHub

Here is an example sketch I ran today with my own hardware to get RPM data at ~13Hz:

#include <ELMduino.h>

ELM327 myELM327;

float rpm;
uint64_t currentTime = millis();
uint64_t previousTime = currentTime;
uint16_t samplePeriod = 80;

void setup()
{
  Serial.begin(115200);
  Serial3.begin(115200);
  
  delay(2000);
  
  if(!myELM327.begin(Serial3))
    Serial.println("Couldn't connect to ELM327");

  if(!myELM327.queryRPM(rpm))
  {
    Serial.println("\tTimeout");
  }
  else
    Serial.print("RPM: "); Serial.println(rpm);
}

void loop()
{
  currentTime = millis();
  if((currentTime - previousTime) >= samplePeriod)
  {
    previousTime = currentTime;
    
    if(!myELM327.queryRPM(rpm))
    {
      Serial.println("\tTimeout");
    }
    else
      Serial.print("RPM: "); Serial.println(rpm);
  }
}

NOTE: This will only work if you have already paired your HC bluetooth board with the OBD scanner. Otherwise, it works like a charm!

Next I'm going to add queries in the test sketch for vehicle speed in addition to the already existing queries for RPM.

1 Like

Got speed and rpm data working together with some updates to the library and the test sketch. Here's the sketch:

#include <ELMduino.h>




ELM327 myELM327;

enum fsm{
  get_speed, 
  get_rpm};
fsm state = get_rpm;

float rpm;
float speed_kmph;
float speed_mph;
uint64_t currentTime = millis();
uint64_t previousTime = currentTime;
uint16_t samplePeriod = 100;




void setup()
{
  Serial.begin(115200);
  Serial3.begin(115200);
  
  delay(2000);

  myELM327.begin(Serial3);
}




void loop()
{
  currentTime = millis();
  if((currentTime - previousTime) >= samplePeriod)
  {
    previousTime = currentTime;

    switch(state)
    {
      case get_rpm:
        if(myELM327.queryRPM(rpm))
        {
          updateLEDs();
        }
        else
          Serial.println("\tTimeout");
        state = get_speed;
        break;
        
      case get_speed:
        if(myELM327.querySpeed(speed_kmph))
        {
          speed_mph = speed_kmph * 0.621371;
          updateLEDs();
        }
        else
          Serial.println("\tTimeout");
        state = get_rpm;
        break;
    }
  }
}




void updateLEDs()
{
  Serial.print(rpm); Serial.print(" "); Serial.println(speed_mph);
  
  return;
}

Next step is to get this all working with the LED display.

I designed a PCB for the project!

I'll be using a Teensy 3.5, HC-05, 75 ohm LED current limiting resistors, 2 7-segment LED displays, and a 10-segment LED display.

Here are some pics of the design (gerber files are attached):


Car_HUD_2019-05-30.zip (142 KB)

@sandracarmona

Unfortunately, I'm not fluent in Spanish. Google translate has your message as:

In the high range, more and more smartphones have opted for OLED technology for their screens. We have clear examples in the LG V30, the Galaxy Note 8, the Pixel 2 XL and more recently, the iPhone X, the last one to join this list.

Having an OLED screen allows for more striking designs where the screen is clear protagonist. But are they all advantages? We talk about what we earn but we also lose with OLED screens in our phones

Is this correct?

If so, I'm not sure what your point is. I'm not currently interested in using an OLED display for the HUD. This is because I'll be able to make the LED display brighter than an OLED one. Also, I'm trying to keep this project, so a few 7/10-segment displays are all I need.

Using an OLED display might be a next step development once the initial prototype is complete...maybe.

Did you have any specific questions about this project?

Updated the library and the sketch code since my last update.

Library link: GitHub - PowerBroker2/ELMduino: Arduino OBD-II Bluetooth Scanner Interface Library for Car Hacking Projects
Sketch code: https://github.com/PowerBroker2/ELMduino/blob/master/examples/ELMduino_Test/ELMduino_Test.ino

I also discovered a hardware bug in the PCB design. Basically, I forgot to wire one of the LED control pins to the Arduino. Because of this, I had to solder a flyaway between the two pins. Here's a pic of the job:

Here are some pics of the final hardware product:


IMG_4974.JPG
IMG_4975.JPG
IMG_4976.JPG

Once I get the enclosure designed and everything working, I'll post some videos!

IMG_4974.JPG

IMG_4975.JPG

IMG_4976.JPG

1 Like

Attached is a loose parts list for the project so far (does not include SPI breakout connector).

HUD_parts.txt (1.68 KB)

Today I finished printing a mount/enclosure for the HUD and tested it in a parking lot. Here's a video of the test:

Ok, how in the world do you embed youtube vids in posts?

I am still following actively! This is just great! My projects lasts for years,I don't have anything to share, followers would die for natural causes before my projects ends...

Cheers,
Kari

Ok, this is cooler than all get out! Something I've been wanting to do for a while now.

I've vaguely following this. You tried to use the built in CAN bus stuff from the teensy but backed away and went with the blue tooth thing? Am I getting this right? If so why did you back away from using the teensy? Maybe I'm wrong because I see you have on on your PC board.

I use Teesnys for pretty much all my projects. I see the CAN bus stuff on there and always wanted to try it out.

-jim lee

jimLee:
Ok, this is cooler than all get out! Something I've been wanting to do for a while now.

Coming from someone who designed an all-out Arduino Cell phone, this is high praise; thank you!!!

jimLee:
I've vaguely following this. You tried to use the built in CAN bus stuff from the teensy but backed away and went with the blue tooth thing? Am I getting this right? If so why did you back away from using the teensy? Maybe I'm wrong because I see you have on on your PC board.

Almost correct.

I did originally try to access the CAN port directly via the Teensy (plus CAN transcievers), but after accidentally resetting my car's diagnostics computer two or three times I decided to use the COTS bluetooth OBDII device. Since implementing the bluetooth device, I have yet to have a problem with it like I did when directly using the CAN port.

I still, though, use the Teensy to interface with the bluetooth device and drive the LED displays.

All in all, I've found the documentation on how to hook-up, interface, and (ESPECIALLY) develop code for the Teensy's CAN ports to be vague and nearly non-existant. I did find a CAN library for my T3.5, but the library code mixed with a lack of direction on how to use it caused my car's diagnostics computer to reset when using one of the example sketches (and that's pretty scary when it happens in your Charger R/T :slight_smile: ).

If someone were to do an in-depth look at how Teensy <--> Automotive CAN works and create a super comprehensive tutorial, I'd be interested in trying it out again ( :wink: )

Power_Broker:
Coming from someone who designed an all-out Arduino Cell phone, this is high praise; thank you!!!

Wow thanks! I'd actually gotten the feeling that very few even noticed. I was amazed at how little the feedback was on that. And none whatsoever when I did the RPN calculator.

Anyway, my issue is that, although I know CAN bus is used as a little network in cars, I know nothing about it works or how they are using it. Id' have to get to grips with, er.. the "theory" of CAN bus first. Heck, I don't even know the voltage levels.

What's going on is that, I just bought this little 1999 Miata. It was a cheap thrasher and the last couple owners had been trying to make a race car out of it. Racing stripes, big tires, loud, roll-bars, attracts police like flies to.. Well.. The issue is that right now I have no Speedo or Tach. and really no way to debug where the problem is. So it would be really nice to be able to see what the heck is buzzing around on its little CAN bus. Is there any Tach or Speed packets on the bus? Or is it the instrument cluster that's broken? Things like that.

Also, it would be totally cool to build a little HUD for the thing.

But I have to get my current project finished up before digging into it. (Way over designed plant watering system.)

-jim lee

Big update:

Finally sat down and finished updating the code for this project. Till now, I had some issues with syncing to the ELM327 and keeping sync. With this new update, I immediately sync up to the ELM327 and stay synced. I'm also getting ~3.5 Hz refresh rate for RPM and Speed (mph).

Here's a link to the updated library. I'm going to put in a request for this library to be added to the Arduino IDE's Libraries Manager tonight, so look for it in your IDE in a week or so!

Hopefully I can get around to posting a video of it working soon...

Here is a video of the HUD in operation!

Been a while since I've given an update, but currently I bought an ESP32 and have decided use it in this project. Specifically, I'm going to replace the Teensy 3.5/HC-05 combo with the new ESP32 since it has built-in bluetooth and WiFi capabilities.

With this change, I the project needs an updated library, sketch, and PCB design. I've already updated the ELMduino library to be compatible with the ESP32 and am almost finished with the new PCB design - details to follow. Work on the sketch, however, will take some time considering the new feature I plan to implement: a diagnostics webpage. I can use the ESP32's WiFi capabilities to setup an "access point" for my phone to connect to. Then, the ESP will serve a webpage that contains diagnostics and telemetry information about my car (realtime).

More updates soon!

Here are the details/gerber files for the updated PCB design:

Car_HUD_2020-02-08.zip (131 KB)

Idea of the circuit is nice, but that limits us using mph only, with km/h we would need three digits.

Well, the core of your design probably is easy to change to use other displaying methods.

Cheers,
kari

True, I don't plan on going over 99mph or driving in kph, but it shouldn't bee too hard to add a new LED display. If you use an ESP32, you might run out of pins, but then again, maybe not.

Also, I tested some recent updates to ELMduino and verified everything still works! Looks like max throughput of the ELM327 is 13 total queries per second. This means, if I'm querying for both speed and rpm, I should expect a sample rate of about 6.5Hz - not bad! :smiley:

I also was able to setup a very simple Access Point webserver with dynamic content (AJAX).

Currently printing the new HUD enclosure - pics soon!