Store vehicle speed data into variable from OBDII connection

HI ALL!

New to programming and I’m designing a front end collision alert system for my senior project. Got all the variables i need except for the vehicle speed.

Decided to use the ECU in my car to pull speed data. Hardware is an arduino uno r3 w/ Seeed Studio CAN shield. Using OBDII connector to interface.

Can’t seem to find a basic program that will just store the vehicle speed into a variable. Anyone have a simple code to do this?
I’d like to just use what i already have. i purchased the 32 can shield through seeed studio. Here is the code i’m trying to use. Trying to request vehicle speed data and receive it. However, i’m not displaying anything on my OLED except initalization ok.

UPDATE:
HERE is the code i’m currently using but not returning any data. What am i doing wrong?

#include <SeeedGrayOLED.h>
#include <Wire.h>
#include "Arduino.h"
#include <mcp_can.h>
#include <mcp_can_dfs.h>

/*************************************************************************************************
    OBD-II_PIDs TEST CODE
    LOOVEE @ JUN24, 2017

    Query
    send id: 0x7df
      dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0

    Response
    From id: 0x7E9 or 0x7EA or 0x7EB
      dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option)

    https://en.wikipedia.org/wiki/OBD-II_PIDs

    Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
***************************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"



// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

#define PID_ENGIN_PRM       0x0C
#define PID_VEHICLE_SPEED   0x0D
#define PID_COOLANT_TEMP    0x05

#define CAN_ID_PID          0x7DF

unsigned char PID_INPUT;
unsigned char getPid    = 0;
int vSpeed;
void set_mask_filt() {
    /*
        set mask, set both the mask to 0x3ff
    */
    CAN.init_Mask(0, 0, 0x7FC);
    CAN.init_Mask(1, 0, 0x7FC);

    /*
        set filter, we can receive id from 0x04 ~ 0x09
    */
    CAN.init_Filt(0, 0, 0x7E8);
    CAN.init_Filt(1, 0, 0x7E8);

    CAN.init_Filt(2, 0, 0x7E8);
    CAN.init_Filt(3, 0, 0x7E8);
    CAN.init_Filt(4, 0, 0x7E8);
    CAN.init_Filt(5, 0, 0x7E8);
}

void sendPid(unsigned char __pid) {
    unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0};
    SeeedGrayOled.setTextXY(0,0);
    SeeedGrayOled.putString("SEND PID: 0x");  
    
    Serial.println(__pid, HEX);
    
    SeeedGrayOled.putNumber(__pid);
    CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);
}

void setup() {
    Serial.begin(115200);
      Wire.begin();
     SeeedGrayOled.init(SH1107G);  //initialize SEEED Gray OLED display
    SeeedGrayOled.setContrastLevel(100);
    SeeedGrayOled.clearDisplay();           //clear the screen and set start position to top left corner
    SeeedGrayOled.setNormalDisplay();       //Set display to Normal mode
    SeeedGrayOled.setVerticalMode();        // Set to vertical mode for displaying text
    SeeedGrayOled.setTextXY(0,0);
    while (CAN_OK != CAN.begin(CAN_500KBPS)) {            // init can bus : baudrate = 500k
       SeeedGrayOled.putString("CAN BUS Shield init fail");
       SeeedGrayOled.putString(" Init CAN BUS Shield again");
        delay(100);
    }
   SeeedGrayOled.putString("CAN BUS Shield init ok!");
   delay(3000);
   SeeedGrayOled.clearDisplay();
}



void loop() {
    taskCanRecv();
    taskDbg();

    if (getPid) {       // GET A PID
        getPid = 0;
        sendPid(PID_VEHICLE_SPEED);
        PID_INPUT = 0;
    }
}

void taskCanRecv() {
    unsigned char len = 0;
    unsigned char buf[8];

    if (CAN_MSGAVAIL == CAN.checkReceive()) {                // check if get data
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
        SeeedGrayOled.clearDisplay();
       SeeedGrayOled.putString("\r\n------------------------------------------------------------------");
        SeeedGrayOled.putString("Get Data From id: 0x");
        Serial.println(CAN.getCanId(), HEX);
        for (int i = 0; i < len; i++) { // print the data
            
            Serial.print(buf[i], DEC);
            SeeedGrayOled.putString("\t");
            vSpeed = buf[i] / 0.621371; //convert kph to mph
            SeeedGrayOled.setTextXY(6,0);
            SeeedGrayOled.putString("Speed: ");
            SeeedGrayOled.putNumber(vSpeed);
            SeeedGrayOled.putString("mph");
        }
        Serial.println();
    }
}

void taskDbg() {
    while (Serial.available()) {
        char c = Serial.read();

        if (c >= '0' && c <= '9') {
            PID_INPUT *= 0x10;
            PID_INPUT += c - '0';

        } else if (c >= 'A' && c <= 'F') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'A';
        } else if (c >= 'a' && c <= 'f') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'a';
        } else if (c == '\n') { // END
            getPid = 1;
        }
    }
}
// END FILE

You can use the OBD2 library ELMduino.h to get lots of vehicle telemetry (including speed). You can install it through the Arduino IDE’s Libraries Manager.

Here’s an example speed program:

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


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


ELM327 myELM327;


float mph = 0;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(115200);

  Serial.println("Attempting to connect to ELM327...");

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner");
    while (1);
  }

  Serial.println("Connected to ELM327");
}


void loop()
{
  float tempMPH = myELM327.mph();

  if (myELM327.status == ELM_SUCCESS)
  {
    mph = tempMPH;
    Serial.print("MPH: "); Serial.println(mph);
  }
  else
  {
    Serial.print(F("\tERROR: "));
    Serial.println(myELM327.status);
    delay(100);
  }
}

Note that this is for interfacing with an ELM327 OBD2 scanner, not the CAN port directly.

thanks! No codes available for the CAN port huh? I'm interfacing through the port.

Maybe you can consider a PHY like WIG-09555 from Sparkfun.

Interfaces to CAN (including others) and uses the ELM327 AT command set.

Bingblop:
thanks! No codes available for the CAN port huh? I'm interfacing through the port.

OBD2 scanners use the CAN port. You can get a bluetooth OBD2 scanner for like $5 on amazon and then you can easily incorporate it into your project with the ELMduino library.

The library should also work as an interface with the WIG-09555.

Added the code i’m using in the OP and here Can someone please look at that and explain to me what’s not right with it? i’m trying to send and recieve the PID_VEHICLE_SPEED but not displaying anything on my OLED.

#include <SeeedGrayOLED.h>
#include <Wire.h>
#include "Arduino.h"
#include <mcp_can.h>
#include <mcp_can_dfs.h>

/*************************************************************************************************
    OBD-II_PIDs TEST CODE
    LOOVEE @ JUN24, 2017

    Query
    send id: 0x7df
      dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0

    Response
    From id: 0x7E9 or 0x7EA or 0x7EB
      dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option)

    https://en.wikipedia.org/wiki/OBD-II_PIDs

    Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
***************************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"



// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

#define PID_ENGIN_PRM       0x0C
#define PID_VEHICLE_SPEED   0x0D
#define PID_COOLANT_TEMP    0x05

#define CAN_ID_PID          0x7DF

unsigned char PID_INPUT;
unsigned char getPid    = 0;
int vSpeed;
void set_mask_filt() {
    /*
        set mask, set both the mask to 0x3ff
    */
    CAN.init_Mask(0, 0, 0x7FC);
    CAN.init_Mask(1, 0, 0x7FC);

    /*
        set filter, we can receive id from 0x04 ~ 0x09
    */
    CAN.init_Filt(0, 0, 0x7E8);
    CAN.init_Filt(1, 0, 0x7E8);

    CAN.init_Filt(2, 0, 0x7E8);
    CAN.init_Filt(3, 0, 0x7E8);
    CAN.init_Filt(4, 0, 0x7E8);
    CAN.init_Filt(5, 0, 0x7E8);
}

void sendPid(unsigned char __pid) {
    unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0};
    SeeedGrayOled.setTextXY(0,0);
    SeeedGrayOled.putString("SEND PID: 0x");  
    
    Serial.println(__pid, HEX);
    
    SeeedGrayOled.putNumber(__pid);
    CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);
}

void setup() {
    Serial.begin(115200);
      Wire.begin();
     SeeedGrayOled.init(SH1107G);  //initialize SEEED Gray OLED display
    SeeedGrayOled.setContrastLevel(100);
    SeeedGrayOled.clearDisplay();           //clear the screen and set start position to top left corner
    SeeedGrayOled.setNormalDisplay();       //Set display to Normal mode
    SeeedGrayOled.setVerticalMode();        // Set to vertical mode for displaying text
    SeeedGrayOled.setTextXY(0,0);
    while (CAN_OK != CAN.begin(CAN_500KBPS)) {            // init can bus : baudrate = 500k
       SeeedGrayOled.putString("CAN BUS Shield init fail");
       SeeedGrayOled.putString(" Init CAN BUS Shield again");
        delay(100);
    }
   SeeedGrayOled.putString("CAN BUS Shield init ok!");
   delay(3000);
   SeeedGrayOled.clearDisplay();
}



void loop() {
    taskCanRecv();
    taskDbg();

    if (getPid) {       // GET A PID
        getPid = 0;
        sendPid(PID_VEHICLE_SPEED);
        PID_INPUT = 0;
    }
}

void taskCanRecv() {
    unsigned char len = 0;
    unsigned char buf[8];

    if (CAN_MSGAVAIL == CAN.checkReceive()) {                // check if get data
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
        SeeedGrayOled.clearDisplay();
       SeeedGrayOled.putString("\r\n------------------------------------------------------------------");
        SeeedGrayOled.putString("Get Data From id: 0x");
        Serial.println(CAN.getCanId(), HEX);
        for (int i = 0; i < len; i++) { // print the data
            
            Serial.print(buf[i], DEC);
            SeeedGrayOled.putString("\t");
            vSpeed = buf[i] / 0.621371; //convert kph to mph
            SeeedGrayOled.setTextXY(6,0);
            SeeedGrayOled.putString("Speed: ");
            SeeedGrayOled.putNumber(vSpeed);
            SeeedGrayOled.putString("mph");
        }
        Serial.println();
    }
}

void taskDbg() {
    while (Serial.available()) {
        char c = Serial.read();

        if (c >= '0' && c <= '9') {
            PID_INPUT *= 0x10;
            PID_INPUT += c - '0';

        } else if (c >= 'A' && c <= 'F') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'A';
        } else if (c >= 'a' && c <= 'f') {
            PID_INPUT *= 0x10;
            PID_INPUT += 10 + c - 'a';
        } else if (c == '\n') { // END
            getPid = 1;
        }
    }
}
// END FILE