Here's my first take on doing what I said above. I added some easy "prints" to the LCD just to see if that part works independantly of the OBDII. Then I added a "print" to the LCD of the response message to the ATZ reset. Hopefully it's much like the one shown in the tutorial and not longer than 16 characters. I'm fuzzy as to the proper way to send that response string to the LCD; whether it should be this ...
lcd.print(rxData);
... or this ...
lcd.print(rxData[]);
... or this ...
lcd.print(rxData, string);
... or something else. It's the first one right now but if the compiler squawks, change it around.
For that matter if you can't find a way to print the actual response string to the LCD, simply send a "Message rcvd" to the LCD. That may be enough to know there's good comm btw the Arduino and ODII. Then if you don't get any data for the speed and RPM, you'll know it's some odd setup or comm problem btw the OBDII and the car. And on that note ... wasn't there someting about commanding an auto setup of the OBDII to detect the proper protocol to use for the car in the tutorial example #1 ? If you don't get any data from the car, that may need to be added/done.
I also added a time out to the getResponse() function and if there's no reponse in 1 sec, the LCD should indicate "No data". So look at the following and make sure I've not missed anything obvious, see if it makes sense to you and then give it a try.
Code: Select all#include <LiquidCrystal.h>
#define LCD_RS 4
#define LCD_ENABLE 5
#define LCD_DATA1 7
#define LCD_DATA2 8
#define LCD_DATA3 12
#define LCD_DATA4 13
LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DATA1, LCD_DATA2, LCD_DATA3, LCD_DATA4);
#define ContrastPin 6
#define BrightnessPin 9
//This is a character buffer that will store the data from the serial port
char rxData[20];
byte 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.
Serial.begin(9600);
//Delete any data that may be in the serial port before we begin.
delay (100);
Serial.flush();
//Init and clear the old data from the LCD.
lcd.begin(16, 2);
lcd.clear();
// Put a Hello World message on the LCD.
lcd.print(" Initializing ");
delay (1000);
lcd.setCursor(0, 1);
lcd.print(" Reseting OBDII ");
delay (1000);
//Reset the OBD-II-UART
Serial.println("ATZ");
// Ignore the echo and use the second true response - if any
getResponse();
getResponse();
// Show what came back.
lcd.clear();
// Now show what are we doing.
lcd.print("Response message");
lcd.setCursor(0, 1);
if(rxIndex)
{
lcd.print(rxData);
}
else
{
lcd.print(" no response");
}
delay (5000); // wait long enough for user to see response
//Hoping the above worked, now put the speed header on the first row.
lcd.clear();
lcd.print("Speed: ");
//Put the RPM header on the second row.
lcd.setCursor(0, 1);
lcd.print("RPM: ");
//Wait for a bit before starting to send commands after the reset.
delay(2000);
}
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);
//Clear out the old speed data, and reset the cursor position.
lcd.print(" "); // need 8 spaces for 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();
//Convert the string data to an integer
if(rxIndex) // test to see if anything was received from OBDII
{
vehicleSpeed = strtol(&rxData[6],0,16);
//Print the speed data to the lcd
lcd.print(vehicleSpeed);
}
else
{
lcd.print("No data");
}
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(5, 1);
//Clear the old RPM data, and then move the cursor position back.
lcd.print(" "); // need 10 spaces for RPM data ?
lcd.setCursor(5, 1);
//Query the OBD-II-UART for the Vehicle rpm
Serial.println("010C");
//Get the response from the OBD-II-UART board
getResponse();
getResponse();
//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
if(rxIndex) // test to see if anything was received from OBDII
{
vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
//Print the rpm data to the lcd
lcd.print(vehicleRPM);
}
else
{
lcd.print("No data");
}
//Give the OBD bus a rest
delay(300);
}
//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;
rxIndex=0;
unsigned long TimeIn = millis();
//Keep reading characters until we get a carriage return or time out
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 (millis() - TimeIn > 1000) // wait 1 sec for some kind of response
{
break;
}
}
}
FWIW I had to delete the "km/hr" after the speed reading as you may not have enough characters in the 16x2 LCD. The tutorial code reserved a (?too?) large set of characters for the data. I have to believe it (and RPM) are really less than the 8-10 spaces but should this work, that can be fixed if desired. Afterall this is just test/debug code, not the end "product". I also changed the rxIndex from a char to a byte as it's used as a counter/index and not really as a character variable (shouldn't make any real difference but ...).