Car Heads Up Display

Link to final(ish) YouTube vid: link


Hello everyone!

This thread is going to be the ongoing build/development log for my next side project; an Arduino based car diagnostics and Heads Up Display (HUD) tool.

Some years ago I had the chance to drive a C6 Corvette with a HUD and loved it! The ability to see your speed and RPM without taking your eyes off the road was amazing. For a long, long time I've wanted to make a HUD for my own car. While doing some research about OBD2 and CAN bus interfacing I figured I might as well have a user interface for actual diagnostics in addition to the HUD - all in one package.

To get started developing this project I've decided to use the following parts:

  • 1 Teensy 3.5 --- Controller
  • 1 Waveshare SN65HVD230 CAN Transceiver --- Signal Converter
  • 1 iKKEGOL OBD-II Male Extension Cable (pigtail) --- Car/Transceiver Interface Cable
  • 1 Diymall 0.95" Blue and Yellow I2C OLED Screen --- Diagnostics Screen
  • Assorted pushbuttons/switches --- User Interface Control

Once I get things working well enough, I'll add a higher power LED display for the HUD and a custom made PCD for final assembly. I will also make a 3D printed enclosure for the device.

Looks like a cool project. As another gear head, looking forward to your progress.

I received all the components for my initial prototype and began soldering today.

Things are looking good so far but I may have some trouble with the OLED screen. Looks like DIYMall (the vendor) has a different hardware setup than the normal Adafruit OLED screen. This means an edited version of the Adafruit OLED library must be used and is provided by DIYMall. The other problem is that I'm using the Teensy's I2C bus Wire1 which is not the normal I2C port used in the OLED library. This unfortunately means I'm going to have to edit the library to get it to work.

Lastly, I'll start to test the OBDII connector pin positions and the CAN transceiver module after I get the OLED screen working.

BTW, I forgot to mention that I'm using an adjustable buck converter as a 12V -> 5V DC power supply. The 12V will come from the OBDII 12V pin. I'm also using two 4.7K Ohm resistors for the I2C pullups.

Tested the OLED screen and it looks like it's a dud. I was able to initialize it using the DIYMall libraries, but I could only get random pixels to light and they would never turn off after initialization, oof.

I decided to get one of these instead. I opted for this specific type because it got rave reviews and it should work with the normal Adafruit OLED screen library.

I also decided to add a fuse for the +12V power coming from the car. Instead of getting a normal car fuse, I opted for a 2A fast blow fuse and got some 5x20mm fuse PCB mounts. Here are the links: fuses, fuse mounts.

Today I also did some testing on my OBDII extension cable. First, I looked up the pinout of the car-side OBDII connector:

From the pinout I noticed I only cared about 5 of the 16 pins:

  • +12V
  • Chassis Ground
  • Signal Ground
  • CAN High
  • CAN Low

Next I looked at my OBDII extension plug's pin labeling, found the pin numbers I cared about, and used the multimeter to find which wire corresponded to which pin. Once I identified each pin, I labeled it using tape and a marker.




Lastly, I was randomly looking around google and I found something I might be able to use for the project. Turns out people sometimes use what is called a scope lens protector for their gun sights. It's a small piece of glass or see-through plastic that sits on a rail mount in front of a gun sight. I might be able to use one of these for the HUD part of the project. Here's what I'm talking about:

ToDo:

  • Connect the plug to my car's OBDII port and test the connections
  • Test the new OLED

Yesterday I got the new OLED screen and it works flawlessly with my Teensy.

Today the 2A fast blow fuses and their mounts came in today. Turns out the mounts don't quite fit a standard PCB hole pattern, so I soldered them inline with the wires from the OBDII cable, hot glued the mounts together, and then soldered a 4 position JST female connector on the end.

I then took it out to the car and tested the connections with my multimeter. First I verified that I was getting +12V from the power wires. Then I verified that there is ~60 Ohms resistance across the CANH and CANL lines (since there are two 120 Ohm terminating resistors in parallel on the CAN line - total resistance should be 60 Ohms). Looks like the wiring of the cable is good!

I also did some reading on Chassis GND vs Signal GND and decided there was no real need to use Signal GND. Because of this, I'm only using Chassis GND as my ground - Signal GND isn't being wired for this project.

Here are some pics:



Sorry that the pics are lopsided, they're right side up on my computer lol

I found a cool 3D printable HUD setup I might edit and use for this project: HUD Link

Did some research on the FlexCAN library that gets installed with teensyduino: although I could be wrong, it looks like it only runs on a T3.6, but there was a header comment in one of the libraries files that said it worked with all of the Teensys. Then I stumbled upon a PJRC forum thread that said something about some FlexCAN library versions working with the T3.5 and some that don't so I decided to just ask on the PJRC forum about it.

So far I have one reply from tonton81 about a library he wrote that is an improved version of the FlexCAN library and works for the T3.5. I plan on testing that library out soon.

I also did some hardware testing today. I hauled out my oscilloscope to my car and hooked it up to the CANH and CANL lines with my car "on". TBH I was just looking to see if there were CAN packet waveforms showing up on the o-scope and not necessarily any data in particular. The reason for this test was because a research team for the University of Tulsa tried to get diagnostics data off of a dodge using the OBD CAN bus. They apparently couldn't do it due to the dodge's CAN bus being present but inactive. Since I have a dodge, I wanted to make sure my CAN bus is active. I'd hate to put in such effort for an impossible project lol.

Check this out for more info.

Turns out - IT WORKS! My CAN bus is active. Now I just have to get the data onto my Teensy.



All this information you give makes me just more confused, but I like this project.

Are these signals and data streams standardized on some level, after all those OBD-adapters I have bought, seems like they have specialized for some brand, VAG is the easiest, my 2006 BMW is not.

Can't wait to see how you get all this together! Nice work so far!
:slight_smile:

Cheers,
Kari

Thanks Kari!

The OBD connector shape is standardized. The pinout is partially standardized - not completely, but partially. The standardized pins (for vehicles in the USA post 2008) are the pins called out in the pinout pic in post #3.

My apologies for being confusing - this is a learning experience for me too.

Power_Broker:
My apologies for being confusing - this is a learning experience for me too.

No no, you are not, you are parsing and analyzing things nicely, it's the information behind that makes me puzzled. My learning curve is getting harder every year.

I really would love the HUD speed on my windscreen, without only the support from GPS. Combination of both of them, OBD and GPS, maybe even helps to calculate estimate tyre wearing (is that a correct word?) at the same time.

Cheers,
Kari

Following too btw :slight_smile:

Soooo, today I uploaded an example of the Improved FlexCan Library and connected it to my car. It reset some things in the diagnostics computer and lit the check engine light. Fortunately, the check engine light cleared itself after about 20min or so, but it spooked me enough to switch to a COTS (Commercial Off the Shelf) approach.

I found a cool website that explains the basics of interfacing with COTS OBD2 to Bluetooth adapters. I plan on connecting to one of those modules with an HC-05 and moving on with the project from there.

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