zhaoshentech
Published © CC BY

IoT4Car (2)

ObdiiUartMkrShield is a socket board for Arduino MKR board to talk with vehicles through ODB-II interface.

AdvancedShowcase (no instructions)20 hours12,875
IoT4Car (2)

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
×1
Custom fabricated PCB
OSH Park Custom fabricated PCB
×1
Sparkfun - OBDII to DB9 cable
×1

Software apps and online services

KiCad
KiCad
Arduino IDE
Arduino IDE

Story

Read more

Schematics

ObdiiUartMkrShield

Code

ObdiiUartMkrShield_v13

C/C++
/*
* OBDII-UART-Serial version 11
* This program will talk to vehicle using the OBDII-UART board, 
* and display the results on the LCD, and show the data in the Serial monitor
* 
* Author: Frank Zhao
* Updated: 2018-11-04
* 
* updates:
*   v3: modified the getResponse() function so that the buffer receives the correct response.
*       add the getRPM() to get the engine RPM from the vehicle.
*   v4: add the getSpeed() function to get the speed of the vehicle
*   v5: add the LCD module and display the speed and RPM on the LCD
*   v6: is the wifi version
*   v7: is the non-wifi, non-serial version. Remove serial initialization,
*       so that the board can work without a computer.
*   v8: is the non-wifi, non-serial version. Add fuel level and coolant temperature.
*       rearrange the display location.
*   v9: is the wifi, non-serial version. Upolad speed, RPM, fuel level and coolant temperture
*   v10: is the non-wifi, serial version. Get speed, RPM, fuel level and coolant temperature
*   v11: is the non-wifi, non-LCD, serial version. Get speed, RPM, fuel level and coolant temperature
*   v13: is the non-wifi, non-LCD, serial plotter version. The speed, RPM, fuel level and collant tempareture can be plotted.
*/

// This is a character buffer that will store the data from the serial port:
char rxData[20];
char rxIndex = 0;
char inChar = 0;
String message;

// Variables to hold the speed and the RPM data:
int vSpeed = 0;
int vRPM = 0;
int vFuel = 0;
int vTemp = 0;

void setup() {
  
 // Initialize the serial communications:
  Serial.begin(9600);
  while(!Serial){
    ; // if not ready, wait  
  }
//  Serial.println("Serial Ready");

  // Serial1 is the acutal port to talk to vehicle
  Serial1.begin(9600);
  while(!Serial1){
    ;// if not ready, wait  
  }
//  Serial.println("Serial1 Ready");

  delay(200);
  resetBuffer();
}

void loop() {
  while(Serial){
    getSpeed();
    resetBuffer();
//    getRPM();
//    resetBuffer();
//    getFuel();
//    resetBuffer();
//    getCoolTemp();
//    resetBuffer();
    Serial.println();
  }
}

// getRPM data sends the "010C" command to the Serial1 port
// and call the getResponse() to collect the data. Then it prints
// the RPM data on the Serial Monitor.

void getRPM(void){
  message = "010C";
  Serial1.println(message);
  delay(200);

  //wait reponse
  getResponse();
  // The RPM response divided by 4 gives the correct value.
  vRPM = ((strtol(&rxData[6],0,16)*256) + strtol(&rxData[9],0,16))/4;

  Serial.print(vRPM); // nomarlized by 100
//  Serial.print("rpm");
  Serial.print(" ");
}


void getSpeed(void){
  message = "010D";
  Serial1.println(message);
  delay(200);

  //wait for the response from the car
  getResponse();
  vSpeed = strtol(&rxData[6], 0, 16); // in the unit of km/h
  vSpeed = vSpeed * 0.621371; // in the unit of mph

  Serial.print(vSpeed);
//  Serial.print("mph");
  Serial.print(" ");
}

void getFuel(void){
  message = "012F";
  Serial1.println(message);
  delay(200);
 
  //wait for the response from the car
  getResponse();
  vFuel = strtol(&rxData[6], 0, 16); // in the scale of 255

  vFuel = 1.0* vFuel / 255 *100; // in the scale of 100

  Serial.print(vFuel);
//  Serial.print("%");
  Serial.print(" ");
}

void getCoolTemp(void){
  message = "0105";
  Serial1.println(message);
//  Serial.println(message);
  delay(200);
 
  //wait for the response from the car
  getResponse();
  vTemp = strtol(&rxData[6], 0, 16); // in the unit of C but offset by 40 degrees
  vTemp = vTemp - 40; // offset by 0

  Serial.print(vTemp);
//  Serial.print("C");
  Serial.print(" ");
}

// The getResponse function collects incoming data from the UART into the rxData buffer
// and exits when the response is transferred. Once the carriage return string
// is detected, the rxData buffer is null terminated (so that we can treat it as a string)
// and the rxData index is reset to 0 so that the next string can be copied.


void getResponse(void){
  while(Serial1.available() > 0) {
      // Start by checking if we've received the end of message character ('\r').
      if(Serial1.peek() == '\r'){
        // reach the end of the message, clear the Serial buffer
        inChar = Serial1.read();
        rxData[rxIndex] = '\0';
        // Reset the buffer index so that the next character goes back at the beginning of the string
        rxIndex = 0;  
      }
      // If we didnt get the end of the message character, just add the new character to the string
      else{
        // Get the new character from the Serial port:
        inChar = Serial1.read();
        // add the new character to the string, and increase the index variable:
        rxData[rxIndex++] = inChar;
      }  
  }

}

void resetBuffer(void){
  for (int i = 0; i < 20; i++){
    rxData[i] = 0;  
  }
}

Credits

zhaoshentech

zhaoshentech

6 projects • 60 followers
An enthusiastic for startups!

Comments