New OBD2 code with Arduino is now available on xsim!!
Let built our dasboard using the OBD2 communication feature in Xsim3!!
Below on Youtube a video (use HD Quality) with the last code and an example on a lcd 1602 !!
it works ... and that works really great !!!
Sirnoname just finished programing the code for Arduino to use the OBD2 feature with Xsim3.
He programmed the base code for catching the data we need to display 3 infos : gear , rpm , speed (km/h).
I finished the code to display first to check the functionality with a usual lcd 16x2 lcd . With his base code and the commentaries you can choose yourself on which display you want to have informations. My goal is after to make the code to display data on tm1638 digit display like Thanos made.
Below the original code without output display.
- Code: Select all
// X-Sim Sample code for receiving OBD2 values from the extractor without using the converter
// OBD2 is industry standard, X-Sim will additionally expand the OBD2 PID with gear and other values
//
// Usage:
// Arduino has to be connected to a free USB port on the computer where the extractor is running
// Open the extractor and open the settings menu, there you have to select the OBD2 menu
// Add now your arduino comport to the OBD2 list.
// After closing the dialog you will see the arduino LED will be enabled which represents receiving data.
// After closing the extractor application the LED will switch off.
// Use this code to insert your own display code at the fitting positions
// Copyright 2013 Martin Wiedenbauer, X-Sim.de
//
// References:
// http://en.wikipedia.org/wiki/OBD-II_PIDs
// http://elmelectronics.com/DSheets/ELM327DS.pdf
// http://www.x-sim.de
bool extractordetected=false; //Will get updated from last positive or negative receive
int receivebuffer[20]={0}; //Receive buffer
void setup()
{
pinMode(13, OUTPUT); //Arduino UNO LED off
digitalWrite(13, LOW);
Serial.begin(9600);
//Do here stuff to init display and zero to default
}
int HexToInt(int c)
{
if (c >= '0' && c <= '9')
{
return c - '0';
}
else if (c >= 'a' && c <= 'f')
{
return c - 'a' + 10;
}
else if (c >= 'A' && c <= 'F')
{
return c - 'A' + 10;
}
else
{
return -1; // getting here is bad: it means the character was invalid
}
}
int ParseReceiveBuffer(int commandhighbyte, int commandlowbyte, int receivelength)
{
//First character is removed of the receivebuffer string and must not be verified again
if( receivebuffer[0]=='1' && receivebuffer[2]==commandhighbyte && receivebuffer[3]==commandlowbyte )
{
//Parse 2 byte values on position 5 and 6 in the buffer string
if(receivelength==7)
{
int highresult=HexToInt(receivebuffer[5]);
int lowresult =HexToInt(receivebuffer[6]);
if(highresult==-1 || lowresult==-1){return -1;}
return ((16*highresult) + lowresult);
}
//Parse 4 byte values on position 5,6,8 and 9 in the buffer string
if(receivelength==10)
{
int tophighresult=HexToInt(receivebuffer[5]);
int toplowresult =HexToInt(receivebuffer[6]);
int highresult=HexToInt(receivebuffer[8]);
int lowresult =HexToInt(receivebuffer[9]);
if(tophighresult==-1 || toplowresult==-1 || highresult==-1 || lowresult==-1){return -1;}
return ((4096*tophighresult) + (256*toplowresult) + (16*highresult) + lowresult);
}
}
return -1; //Something is wrong with the returned OBD2 echo command byte
}
//This function will wait for the first character in receivetrigger and will parse the result
int ReceiveValueWithTimeout(int receivetrigger, int commandhighbyte, int commandlowbyte, int receivelength)
{
int arduinoserialbuffer=0;
int buffercount=-1;
for(int z=0; z < 1500; z++) //1500ms timeout should be enough
{
while(Serial.available())
{
if(buffercount==-1)
{
arduinoserialbuffer = Serial.read();
if(arduinoserialbuffer != receivetrigger) //Wait until the trigger is reached, ignore echo, first character is not in the buffer
{
buffercount=-1;
}
else
{
buffercount=0;
}
}
else
{
arduinoserialbuffer = Serial.read();
receivebuffer[buffercount]=arduinoserialbuffer;
buffercount++;
if(buffercount > receivelength) //buffer has now waitlen character length
{
return ParseReceiveBuffer(commandhighbyte, commandlowbyte, receivelength);
buffercount=-1;
}
}
}
delay(1);
}
return -1;
}
void ClearReceiveBuffer()
{
while(Serial.available())
{
Serial.read();
}
}
void SendEchoDisabled() //not used here and a part of the OBD2 ELM327 specifications, as INFO
{
//ATE0 Echo disabled
Serial.write('A');
Serial.write('T');
Serial.write('E');
Serial.write('0');
Serial.write('\r');
}
//010c Request RPM, remember: OBD2 RPM is ((A*256)+B)/4
int GetOBD2RpmValue()
{
//010c
ClearReceiveBuffer();
Serial.write('0');
Serial.write('1');
Serial.write('0');
Serial.write('c');
Serial.write('\r');
return ReceiveValueWithTimeout('4','0','C',10);
}
//010d Request speed in kmh
int GetOBD2SpeedValue()
{
//010d
ClearReceiveBuffer();
Serial.write('0');
Serial.write('1');
Serial.write('0');
Serial.write('d');
Serial.write('\r');
return ReceiveValueWithTimeout('4','0','D',7);
}
//01e0 Request gear number
int GetOBD2GearValue()
{
//01e0
ClearReceiveBuffer();
Serial.write('0');
Serial.write('1');
Serial.write('e');
Serial.write('0');
Serial.write('\r');
return ReceiveValueWithTimeout('4','E','0',7);
}
void loop()
{
int speed=0;
int rpm=0;
int gear=GetOBD2GearValue();
while(gear >= 0)
{
if(extractordetected==false)
{
SendEchoDisabled(); //Will cause a OK\r as answer from the extractor, ignored in this code
extractordetected=true;
}
//Read all values
gear = GetOBD2GearValue(); //Notice: offset +1 because of reverse gear
speed= GetOBD2SpeedValue();
rpm = GetOBD2RpmValue();
rpm=rpm/4 ; //remember OBD2 RPM is ((A*256)+B)/4
if(gear!=-1 && speed!=-1 && rpm!=-1)
{
digitalWrite(13, HIGH); //We have connection and all values are ok, turn on the LED
//Do here your LCD or display stuff
}
}
extractordetected=false;
digitalWrite(13, LOW); //No connection, turn off the LED
//Do here stuff to set display to zero or default
delay(2000); //No serial connection, poll serial port all two seconds + readtimeout until a running extractor is detected
}
The file zipped.
You will find attached the code with added code to display data on lcd 16x2.
This is the arduino and lcd wiring schematic ( just mising the pin13 to check the data ON with the led and I connected the lcd backlight GND and 5 volts to the 2 left pin available on lcd 16x2)
EDIT 15/07/2013
Below data compiled for the dashboard showed post below with tm1638 for speed-rpm-rpmleds ,big 7 segments display for gear ,arduino nano v3
1- the components , wiring diagram are in the Thanos post ,link below:
http://www.x-sim.de/forum/viewtopic.php?f=40&t=155&start=30#p5726
Don't use the arduino code in the zip file because it 's valid for uso parser communication not obd2.
2-the code for arduino is here , post below :
http://www.x-sim.de/forum/viewtopic.php?f=40&t=1083#p9052
3-the result with this code is post below :
http://www.x-sim.de/forum/viewtopic.php?f=40&t=1083#p9022
EDIT 16/07/2013
You can find attached a new code with the avaibility to setup correctly the rpm max to fit correctly the rpmleds flashing at gear shift.
How to do this :
the rightmost button increase the rpm with 200 rpm pitch[/s]
the for for rightmost button decrease the rpm with 200 rpm pitch
edit 6/10/2013 : I changed the code with Mreiner code.When the car still at neutral pusch the throttle to the max when pushing in the same time the right most button.The new rpmmax is stored and the gear shift change blinks at rpmmax-300 rpm (you can change this value )
Edit 29/04/2014 , I updated the code to display the speed up to 255 km/h . The pid not elm complient is E9.Below the code updated
The video is processing to upload on Youtube.Coming soon!
Many thanks to Sirnoname to program the code and share it to the whole xsim community.
Enjoy using it !!!