
Introduction
As an automotive enthusiast with an interest in hobbyist electronics, I’ve been wanting to learn more about how the modern car works. The natural beginner project in this area is a simple OBDII display that can show data from the car’s ECU, such as the vehicle speed in MPH or engine speed in RPM.
Set Up
Hardware Used
- Arduino Uno
- CAN Bus Shield from SeedStudio
- OBDII to DB9 Extension Cable
- 1.3″ 128×64 OLED I2C Display
Software Libraries
Wiring
The set up of this project is very simple. The CAN bus shield sits on top of the Arduino Uno. This shield provides connectivity to the vehicle, via the OBDII port in the driver’s footwell.
The OLED display is then connected to the Arduino Uno as a typical I2C device.
- VCC to VCC
- GND to GND
- SCL to Analog Pin 4
- SDA to Analog Pin 5

Programming
The first step is to declare the libraries needed. For connectivity to the vehicle, the CAN.h and OBD2.h libraries written by Sandeep Mistry will be used. For outputting text to the OLED display, the Adafruit_GFX.h and Adafruit_SSD1306.h libraries will be used.
#include <CAN.h> //CAN Bus Communication
#include <OBD2.h> //For vehicle data from ECU
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Next, we will declare the constants for the PIDs we plan to request from the vehicle. A PID is an on-board diagnostic Parameter ID, and is a code that is used to request data from the vehicle. These are defined by SAE standard J1979. These constants are defined in an enum within the OBD2.h library.
// array of PID's to print values of
const int PIDS[] = {
ENGINE_RPM,
VEHICLE_SPEED,
};
We then define our CAN network speed, and set up the display. Followed by variables to store the values received from the vehicle.
//CAN Network Speed Constant
#define CAN_500KBPS 16
// Reset pin not used but needed for library
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define SCREEN_REFRESH_DELAY 1000
//Global variables
int current_Displayed_Speed_MPH = 0; //Current speed displayed on gauge
int current_Displayed_RPM = 0; //Current RPM reading displayed on gauge
Next we can start writing the functions. The first is the setup function. This will initialize the OLED display, write a header line to the screen, and attempt to connect to the vehicle via the CAN bus.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
// initialize OLED with I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
while (!Serial);
// Clear the display
display.clearDisplay();
// Set up to write to display
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.println(F("OBD2 Key Stats"));
display.display();
delay(SCREEN_REFRESH_DELAY);
// Attempt to connect to vehicle CAN bus
while (true) {
display.clearDisplay();
display.print(F("Attempting to connect to OBD2 CAN bus ... "));
display.display();
delay(SCREEN_REFRESH_DELAY);
if (!OBD2.begin()) {
display.clearDisplay();
display.println(F("failed!"));
display.display();
delay(SCREEN_REFRESH_DELAY);
} else {
display.clearDisplay();
display.println(F("success"));
display.display();
break;
}
}
Serial.println();
} //end function setup
In our loop function, the Arduino requests the current speed of the vehicle, converts that to miles per hour from the kilometers per hour the vehicle responds with, and requests the engine speed in RPM. These values are then stored in the variables we already created.
void loop() {
//Update RPM value
float current_RPM = OBD2.pidRead(ENGINE_RPM); //Request RPM from ECU
current_Displayed_RPM = current_RPM;
//Update speed value
float current_Speed = OBD2.pidRead(VEHICLE_SPEED); //Request speed from ECU, returns speed in km/h
current_Speed = current_Speed / 1.609344; //Convert to mph
current_Displayed_Speed_MPH = current_Speed;
//Update display
delay(SCREEN_REFRESH_DELAY);
UpdateDisplay();
display.display();
} //end function loop
The loop function then calls the UpdateDisplay() function to write these values to the screen.
void UpdateDisplay() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("OBDII Key Stats: ");
display.setCursor(0,10);
display.print("Current Speed: ");
display.print(current_Displayed_Speed_MPH);
display.print(" MPH");
display.setCursor(0,20);
display.print("Current RPM: ");
display.print(current_Displayed_RPM);
display.print(" RPM");
} //end function UpdateDisplay
Summary
This was a fun little project to learn how to use the OBD2 library. The library contains PIDs for a whole range of vehicle sensor data and can be used as part of much larger projects. Eventually I intend to expand on this and use this library for future projects and vehicle modding.