OBDII UART Only Shows 832RPM-13Kmh

Hi,

I’m not quite sure this is the right section for this component but i couldn’t find related subject for this product, so excuse me if i’m at the wrong place.

I bought OBDII UART module https://www.sparkfun.com/products/9555? … 1598697093 to read my car’s RPM-SPEED-COOLANT TEMPRATURE etc. on runtime,

Followed this instruction ```
https://learn.sparkfun.com/tutorials/obd-ii-uart-hookup-guide?_ga=2.88643035.1319094663.1598697093-1525109370.1598697093


I don't have sparkfun serial lcd so i've changed lcd codes according to my lcd screen, my codes as below;

#include <SoftwareSerial.h>
#include “DFRobot_RGBLCD.h”
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
DFRobot_RGBLCD lcd(16,2); //16 characters and 2 lines of show
char rxData[20];
char rxIndex=0;
int vehicleSpeed=0;
int vehicleRPM=0;
void setup()
{
lcd.init();
lcd.setRGB(colorR, colorG, colorB);
Serial.begin(9600);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Hiz: ");
lcd.setCursor(0,1);
lcd.print("Devir: ");
delay(1500);
Serial.println(“ATZ”);
delay(2000);
Serial.flush();
}

void loop()
{
Serial.println(“010D”);
getResponse();
getResponse();
vehicleSpeed = strtol(&rxData[6],0,16);
lcd.setCursor(4,0);
lcd.print(vehicleSpeed);
lcd.print(" km/h");
delay(100);
Serial.flush();
Serial.println(“010C”);
getResponse();
getResponse();
vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
lcd.setCursor(6,1);
lcd.print(vehicleRPM);
delay(100);
}
void getResponse(void){
char inChar=0;
while(inChar != ‘\r’){
if(Serial.available() > 0){
if(Serial.peek() == ‘\r’){
inChar=Serial.read();
rxData[rxIndex]=‘\0’;
rxIndex=0;
}
else{
inChar = Serial.read();
rxData[rxIndex++]=inChar;
}
}
}
}


My connection between arduino and OBDII board as follow;

OBD TX -> ARDUINO RX

OBD RX-> ARDUINO TX

OBD GND -> ARDUINO GND

I haven't wired OBDII board until arduino programming completed (official instruction page were saying disconnect OBD board's RX connection while programming arduino to avoid any brick situation)

I did connect OBDII board to my car through OBDIItoDB9 cable (which came along with board in the box) and powered up the arduino with my 5v powerbank, so when i trun ignition to battery mode all lights have turn on on the dashboard and OBDII board's leds started flashing, after that i powered up the arduino through powerbank and after 3 seconds LCD showed as follow :

Hiz : 13 Kmh (Hiz means speed in Turkish)

Devir : 832 (Devir means RPM in Turkish)

I thought "ok that values must be the last values recorded by car's computer right before i stop the car and stop the engine", then i started the engine, at this point after car started speed and rpm values should have changed but it didn't.

Even after i started the engine Speed & RPM value stucked at 13-832, please see attached photos.

My car is 2004-Skoda Fabia MK1.

What am i missing here? What am i doing wrong?

![003.jpg|1600x1200](upload://rCih8DW5nfLzoPXKpij0p22Mqbl.jpeg)

![002.jpg|1600x1200](upload://ts4uUznT6dnHspS3J3HPdmGEipO.jpeg)

![001.jpg|1600x1200](upload://kI54OropcW2ZnP3ta6L8Tjn7kE1.jpeg)

Couple minutes ago i did test with usb ftdi, strange thing is i can read RPM-SPEED through USB FTDI, but when i connect my arduino it stuck on 832RPM-13Kmh.

Test pictures as attached.

today i wrote a small script that simply sends command and pirnt output to LCD screen when arduino sends “010C” OBD bus returns STOPPED (it doesn’t matter engine is running or not it returns STOPPED in both cases), what is that mean and how to fix it ?

Unless something is wrong in your code, it could be that your car uses different PIDs for the data you’re trying to poll or it might be sending data the OBD-II UART doesn’t understand.

I’m afraid we’re not familiar with the protocols used on your particular car and can’t help much. You might see if you can find a local mechanic that has better knowledge of how OBD works on your brand car and see if they can give you any pointers.

Hi Chris,

Thanks for your kind reply, i don’t think problem cause by car’s protocols, all ELM327 (bluetooth or cable versions) works just fine with the car, and OBD softwares (which mentioned on your github page) works fine with the Sparkfun OBDII board, also as you can see on my second post it works without any problem through FTDI+Computer connection.

Problem only shows when i use arduino, i receive the OBDII board last thursday and i’m doing tests since then, during this period with obd softwares & terminal it works perfectly but when i start to use arduino it returns STOPPED message for every command except “ATZ”,“0100” & “ATRV”, on the other hand as i mentioned all codes works perfectly on computer connection.

Couple minutes ago i found an comment on your guide page some of the users experienced same problem and they said they solved the problem by adding delay between two getrespond function calls, tomorrow i’ll test, do you think that could be the problem?

That could be the issue, give the delays a try and see if that helps.

If the Arduino is going faster than the car can send data you would get back incorrect results.

ok tomorrow i’ll test and update the topic, thanks for your time.

ok i did some tests, with below code it’s allways returns STOPPED no matter how long is the delay;

/*
* OBD-II-UART Quickstart Sketch
* Written by Ryan Owens for SparkFun Electronics 7/5/2011
* Updates for Arduino 1.0+ by Toni Klopfenstein
*
* Released under the 'beerware' license
* (Do what you want with the code, but if we ever meet then you buy me a beer)
*
* This sketch will grab RPM and Vehicle Speed data from a vehicle with an OBD port
* using the OBD-II-UART board from SparkFun electronics. The data will be displayed
* on a serial 16x2 LCD. See the tutorial at https://www.sparkfun.com/tutorials/294
* to learn how to hook up the hardware:
*
*/
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>



//Create an instance of the new soft serial library to control the serial LCD
//Note, digital pin 3 of the Arduino should be connected to Rx of the serial LCD.

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

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

//Variables to hold the speed and RPM data.
int vehicleSpeed=0;
int vehicleRPM=0;

void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);
  lcd.clear();  
  //Put the speed header on the first row.
  lcd.setCursor(0,0);
  lcd.print("S: ");
  //Put the RPM header on the second row.
  lcd.setCursor(0,1);
  lcd.print("R: ");
  
  //Wait for a little while before sending the reset command to the OBD-II-UART
  delay(1500);
  //Reset the OBD-II-UART
  Serial.println("ATZ");
  //Wait for a bit before starting to send commands after the reset.
  delay(2000);
  
  //Delete any data that may be in the serial port before we begin.
  Serial.flush();
}

void loop(){
  //Delete any data that may be in the serial port before we begin.  
  Serial.flush();
  //Set the cursor in the position where we want the speed data.
lcd.setCursor(7,0);
  //Query the OBD-II-UART for the Vehicle Speed
  Serial.println("010D");
  //Get the response from the OBD-II-UART board. We get two responses
  //because the OBD-II-UART echoes the command that is sent.
  //We want the data in the second response.
  getResponse();
  getResponse();
  Serial.print("S : ");
  Serial.println(rxData[6]);
  //Convert the string data to an integer
  vehicleSpeed = strtol(&rxData[6],0,16);
  //Print the speed data to the lcd
  lcd.print(vehicleSpeed);
  lcd.print(" km/h");
  delay(100);
  //Delete any data that may be left over in the serial port.
  Serial.flush();
  //Move the serial cursor to the position where we want the RPM data.
lcd.setCursor(6,1);
  //Clear the old RPM data, and then move the cursor position back.
  //Query the OBD-II-UART for the Vehicle rpm
  Serial.println("010C");
  //Get the response from the OBD-II-UART board
  getResponse();
  getResponse();
  Serial.print("R : ");
  Serial.println(rxData);
  //Convert the string data to an integer
  //NOTE: RPM data is two bytes long, and delivered in 1/4 RPM from the OBD-II-UART
  vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
  //Print the rpm data to the lcd
  lcd.print(vehicleRPM); 
  //Give the OBD bus a rest
  delay(100);
}

//The getResponse function collects incoming data from the UART into the rxData buffer
// and only exits when a carriage return character is seen. Once the carriage return
// string is detected, the rxData buffer is null terminated (so 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)
{
  char inChar=0;
  //Keep reading characters until we get a carriage return
  while(inChar != '\r'){
    //If a character comes in on the serial port, we need to act on it.
    if(Serial.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(Serial.peek() == '\r'){
        //Clear the Serial buffer
        inChar=Serial.read();
        //Put the end of string character on our data string
        rxData[rxIndex]='\0';
        //Reset the buffer index so that the next character goes back at the beginning of the string.
        rxIndex=0;
      }
      //If we didn't get the end of message character, just add the new character to the string.
      else{
        //Get the new character from the Serial port.
        inChar = Serial.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

With this code it reads RPM without any problem, but it requires 3 secodns delay and it’s dead slow, for example ;

started engine->hold idle for 10 seconds->push throttle to hold rpm arround 2.000->lcd shows 2.000 after like 10 seconds, it shows iddle rpm for 9-10 seconds than shows 2.000 rpm and when you stop hold to throttle it takes like 10 seconds to go back to idle rpm.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
char rxData[20];
char rxIndex=0;

void setup() 
{
lcd.init();
lcd.backlight();
Serial.begin(9600);
lcd.setCursor(0,0);
lcd.print("ATZ->");
Serial.println("ATZ");
getResponse();
getResponse();
lcd.setCursor(0,1);
lcd.print(rxData);
delay(3000);
Serial.flush();
lcd.clear();
//lcd.setCursor(0,1);
//lcd.print("010C->");

}

void loop() 
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("010C->");
Serial.println("010C");
getResponse();
getResponse();
lcd.setCursor(0,1);
lcd.print(((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4);
delay(3000);
lcd.clear();
}

void getResponse(void)
{
  char inChar=0;
  //Keep reading characters until we get a carriage return
  while(inChar != '\r'){
    //If a character comes in on the serial port, we need to act on it.
    if(Serial.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(Serial.peek() == '\r'){
        //Clear the Serial buffer
        inChar=Serial.read();
        //Put the end of string character on our data string
        rxData[rxIndex]='\0';
        //Reset the buffer index so that the next character goes back at the beginning of the string.
        rxIndex=0;
      }
      //If we didn't get the end of message character, just add the new character to the string.
      else{
        //Get the new character from the Serial port.
        inChar = Serial.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

if you shorten the delay (i’ve tried 1000-1500-2000-2500) it returns “STOPPED” no matter what you do.

i also have this ELM327 bluetooth diagnostic tool https://www.ebay.com/c/1038655933 when i connect to OBDII port of my car and open it’s mobile app it shows runtime rpm with much shorter delay like 1 second delay.

On the other hand, i wrote a simple program with delphi to send AT commands through comport via usb tfdi adapter with 1 second delay, when i run the program it reads runtime rpm or other values without any problem (through your obd board), things start to fail when i use arduino and it drives me crazy, i’ve tried 3 different arduino UNO but result was the same, if the problem is car or car’s protocol then how does it work on pc with the same obd board of yours?(i’m not angry, i just don’t understand :slight_smile: )

What could cause this problem and is there any fix for this delay?

most of the buyers who face the similiar problem (“STOPPED”) says this cause because of arduino sends CRLF through serial but car’s system only accepts CR, and when car’s system sees LF it’s terminating the code search and says “STOPPED”, how i can send commands through arduino’s serial with only CR?

after 1 week of try i finally solved it :slight_smile:

I’m sharing solution if someone needs in future, my car is 2004 Skoda Fabia MK1 which uses KWP2000-ISO 14230 so there is nothing wrong with my car’s protocols you just need to use right arduino board.

Thanks to @scott_fx he/she wrote perfect code to fix speed problem here : viewtopic.php?t=38253, during my tests i realised that Arduino NANO, Arduino UNO works with the board but not stable because nano & uno have single UART layer, if you want a stable connection you need a micro controller which have double UART layers, this lead us to Arduino MEGA, mega has 3 UART layers so it means that you can define 1st UART layer for Transmit and 2nd UART layer for Receive.

Connection should be as follow;

OBD RX->MEGA TX1

OBD TX->MEGA RX1

OBD GND->MEGA GND (there are 3 GND on Mega you can connect one of it)

Code should be as follow (i only need RPM & Speed, that’s why i commented out other parameters but allready tested works perfectly);

//Set up ring buffer
char rxData[20];
char rxIndex = 0;
int rpmstored = 0;

    void setup()
    {
      Serial.begin(9600); // prints to serial monitor
      Serial1.begin(9600); //Hardware serial connection to the obdii uart
      OBD_init(); //initiates obd link
      delay(3000);
    }
    
    void loop()
{    
rpmstored = getRPM();
//int mph = (int)((getSPEED() * 10000L + 5) / 16090); //convert to mph
//  Serial.print (mph);
Serial.print("S:");
Serial.print (getSPEED());
Serial.print (",");
Serial.print("R:");
Serial.println (getRPM());
//Serial.print (",");
//Serial.print("W:");
//Serial.print (getWATERTEMP());
//Serial.print (",");
//Serial.print("O:");
//Serial.print (getOILTEMP());
//Serial.print (",");
//Serial.print("F:");
//Serial.print (getFUEL());
//Serial.print (",");
//Serial.print("V:");
//Serial.println (getVOLT());
delay(100);
Serial.flush();
    }
    
    void OBD_init(void)
    {
      //Wait for a little while before sending the reset command to the OBD-II-UART
      delay(2000);
      //Reset the OBD-II-UART
      Serial1.print("ATZ\r");
      //Wait for a bit before starting to send commands after the reset.
      delay(2);
      OBD_read();
      Serial1.print("ATE0\r");
      OBD_read();
      //Serial1.flush();
    }
    
    int getRPM(void)
    {
      //Query the OBD-II-UART for the Vehicle rpm
      Serial1.flush();
      Serial1.print("010C\r");
      OBD_read();

      return ((strtol(&rxData[6], 0, 16) * 256) + strtol(&rxData[9], 0, 16)) / 4;
    }

    int getSPEED(void)
    {
      //Query the OBD-II-UART for the vehicle speed
      Serial1.flush();
      Serial1.print("010D\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getOILTEMP(void)
    {
      //Query the OBD-II-UART for the vehicle speed
      Serial1.flush();
      Serial1.print("015C\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getFUEL(void)
    {
      //Query the OBD-II-UART for the vehicle speed
      Serial1.flush();
      Serial1.print("012F\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getVOLT(void)
    {
      //Query the OBD-II-UART for the vehicle speed
      Serial1.flush();
      Serial1.print("0142\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getWATERTEMP(void)
    {
      //Query the OBD-II-UART for the Engine Coolant Temp
      Serial1.flush();
      Serial1.print("0105\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16) - 40;
    }
    
    
    void OBD_read(void)
    {
      char c;
      do {
        if (Serial1.available() > 0)
        {
          c = Serial1.read();
          if ((c != '>') && (c != '\r') && (c != '\n')) //Keep these out of our buffer
          {
            rxData[rxIndex++] = c; //Add whatever we receive to the buffer
          }
        }
      } while (c != '>'); //The ELM327 ends its response with this char so when we get it we exit out.
      rxData[rxIndex++] = '\0';//Converts the array into a string
      rxIndex = 0; //Set this to 0 so next time we call the read we get a "clean buffer"
    }

If you don’t want to use Arduino MEGA you can simply replace Serial1 to Serial and it will work but it won’t be stable, because as i mentioned before UNO only has 1 UART layer which means,when you send a command you need to wait minimum 3 seconds for respond, only after that you can send another command, if you don’t delay minimum 3 seconds then you’ll get STOPPED error, only stable solution to use Arduino MEGA, with mega you can use with 35ms delay without any problem but 100 is the best.

Today i connected an 16x2 rgb lcd to test on the road and during 5 hours of ride, it never freezed or interrupted communication.