ODB II ELM 327

Capture

L’interface On Board Diagnostic équipe pratiquement tous les véhicules depuis 2004. La puce ELM327 est une interface permettant de dialoguer avec le module ODB de la voiture via une interface série de type RS232 et des commandes AT de type modem.

La documentation est ici.

Installation :

1°) raccordez le module ELM sur la prise ODB du véhicule,

2°) mettre le contact du véhicule sur ON, les leds de l’ELM vont s’allumer successivement,

3°) raccordez soit via bluetooth soit par cable le module ELM au PC ou smartphone

4°) lancez le logiciel de communication ou utilisez un terminal série (hyperterminal ou autre…)

5°) paramétrez le logiciel pour qu’il reconnaisse l’ELM (port, vitesse,…)

Logiciels :

http://elmelectronics.com/obdsoftware.html à tester pour windows wODB pour Android Torque

http://www.obd2help.co.uk/elm327_free_software.htm

Principe des commandes de l’ELM :

First, ensure that your software is set to use the proper ‘COM’ port, and that you have chosen the proper data rate – this will be either 9600 baud (if pin 6=0V at power up), or 38400 baud (if PP 0C has not been changed). If you select the wrong “COM” port, you will not be able to send or receive any data. If you select the wrong data rate, the information that you send and receive will be all garbled, and unreadable by you or the ELM327. Don’t forget to also set your connection for 8 data bits, no parity bits, and 1 stop bit, and to set it for the proper “line end” mode. All of the responses from the ELM327 are terminated with a single carriage return character and, optionally, a linefeed character (depending on your settings).

Properly connected and powered, the ELM327 will energize the four LED outputs in sequence (as a lamp test) and will then send the message:  ELM327 v1.3a

In addition to identifying the version of this IC, receiving this string is a good way to confirm that the computer connections and terminal software settings are correct (however, at this point no communications have taken place with the vehicle, so the state of that connection is still unknown).

The ‘>’ character that is shown on the second line is the ELM327’s prompt character. It indicates that the device is in the idle state, ready to receive characters on the RS232 port. If you did not see the identification string, you might try resetting the IC again with the ATZ (reset) command. Simply type the letters A T and Z (spaces are optional), then press the return key:

>AT Z

That should cause the leds to flash again, and the identification string to be printed. If you see strange looking characters, then check your baud rate – you have likely set it incorrectly. Characters sent from the computer can either be intended for the ELM327’s internal use, or for reformatting and passing on to the vehicle. The ELM327 can quickly determine where the received characters are to be directed by monitoring the contents of the message. Commands that are intended for the ELM327’s internal use will begin with the characters ‘AT’, while OBD commands for the vehicle are only allowed to contain the ASCII codes for hexadecimal digits (0 to 9 and A to F).

Whether it is an ‘AT’ type internal command or a hex string for the OBD bus, all messages to the ELM327 must be terminated with a carriage return character (hex ‘0D’) before it will be acted upon. The one exception is when an incomplete string is sent and no carriage return appears. In this case, an internal timer will automatically abort the incomplete message after about 20 seconds, and the ELM327 will print a single question mark (‘?’) to show that the input was not understood (and was not acted upon).

One other feature of the ELM327 is the ability to repeat any command (AT or OBD) when only a single carriage return character is received. If you have sent a command (for example, 01 0C to obtain the rpm), you do not have to resend the entire command in order to resend the request to the vehicle – simply send a carriage return character, and the ELM327 will repeat the command for you. The memory buffer only remembers one command though, and there is no provision in the current ELM327 to provide storage for any more.

Finally, it should be noted that the ELM327 is not case-sensitive, so the commands ‘ATZ’, ‘atz’, and ‘AtZ’ are all exactly the same to the ELM327.

En résumé :

Le port de communication utilisé par l’interface ELM doit être paramétré en 9600 bauds ou 38400 bauds, 8 data bits, no parity bits, and 1 stop bit, et le caractère de fin de ligne doit être \r carriage return code hexadécimal 0D (zéro D).

Pour paramétrer l’ODB il faut envoyer des commandes AT, pour donner des ordres à l’ODB des commandes hexadécimales, chaque commande doit être terminée par un carriage return. L’envoi d’un carriage return seul répète la dernière commande.

Les nombres contenus dans les commandes sont toujours exprimés en hexadecimal et la commande ON a la valeur 1 OFF 0.

Communication ODB avec la voiture :

The standards require that each OBD command or request that is sent to the vehicle must adhere to a set format. The first byte sent (known as the ‘mode’) describes the type of data being requested, while the second byte (and possibly a third or more) specifies the actual information that is required. The bytes which follow after the mode byte are known as the ‘parameter identification’ or PID number bytes. The modes and PIDs are described in detail in documents such as the SAE J1979, or ISO 15031-5 standards, and may also be defined by the vehicle manufacturers.
The SAE J1979 standard currently defines ten possible diagnostic test modes, which are:
01 – show current data
02 – show freeze frame data
03 – show diagnostic trouble codes
04 – clear trouble codes and stored values
05 – test results, oxygen sensors
06 – test results, non-continuously monitored
07 – show ‘pending’ trouble codes
08 – special control mode
09 – request vehicle information
0A – request permanent trouble codes
Vehicles are not required to support all of the modes, and within modes, they are not required to support all possible PIDs (some of the first OBDII vehicles only supported a very small number of them). Within each mode, PID 00 is reserved to show which PIDs are supported by that mode. Mode 01, PID 00 must be supported by all vehicles, and can be accessed as follows…
Ensure that your ELM327 interface is properly connected to the vehicle, and powered. Most vehicles will not respond without the ignition key in the ON position, so turn the ignition to on, but do not start the engine. If you have been experimenting, the state of your interface may be unknown, so reset it by sending :
>AT Z
You will see the interface leds flash, and then the IC should respond with ‘ELM327 v2.1’, followed by a prompt character. Now, you may choose a protocol that the ELM327 should connect with, but it is usually easier to simply select protocol ‘0’ which tells the IC to search for one:
>AT SP 0
That’s all that you need to do to prepare the ELM327 for communicating with a vehicle.

At the prompt, issue the mode 01 PID 00 command:
>01 00
The ELM327 should say that it is ‘SEARCHING…’ for a protocol, then it should print a series of numbers, similar to these:
41 00 BE 1F B8 10
The 41 in the above signifies a response from a mode 01 request (01 + 40 = 41), while the second number (00) repeats the PID number requested. A mode 02, request is answered with a 42, a mode 03 with a 43, etc. The next four bytes (BE, 1F, B8, and 10) represent the requested data, in this case a bit pattern showing the PIDs that are supported by this mode (1=supported, 0=not). Although this information
is not very useful for the casual user, it does prove that the connection is working.

Another example requests the current engine coolant temperature (ECT). Coolant temperature is PID 05 of mode 01, and can be requested as follows:

>01 05
The response will be of the form:
41 05 7B
The 41 05 shows that this is a response to a mode 1 request for PID 05, while the 7B is the desired data. Converting the hexadecimal 7B to decimal, one gets 7 x 16 + 11 = 123. This represents the current temperature in degrees Celsius, but with the zero offset to allow for subzero temperatures. To convert to the actual coolant temperature, you need to subtract 40 from the value obtained. In this case, then, the
coolant temperature is 123 – 40 or 83°C.
A final example shows a request for the engine rpm. This is PID 0C of mode 01, so at the prompt type:
>01 0C
If the engine is running, the response might be:
41 0C 1A F8
The returned value (1A F8) is actually a two byte hex number that must be converted to a decimal value to be useful. Converting it, we get a value of 6904, which seems like a very high value for engine rpm. That is because rpm is sent in increments of 1/4 rpm ! To convert to the actual engine speed, we need to divide the 6904 by 4. A value of 1726 rpm is much more reasonable.

Liens :

http://www.obdtester.com/elm-usb-commands

liste des codes : http://en.wikipedia.org/wiki/OBD-II_PIDs

analyse des codes renault : http://x0r.fr/blog

https://learn.sparkfun.com/tutorials/obd-ii-uart-hookup-guide/connecting-to-an-arduino

http://www.obdsol.com/knowledgebase/obd-software-development/reading-real-time-data/

http://www.ebay.com/itm/Vehicle-OBD-II-Digital-Gauge-DIY-Kit-Arduino-Nano-OLED-OBD-II-Adapter-/251669926173?pt=AU_Car_Parts_Accessories&hash=item3a98b2511d&vxp=mtr

Arduino Pin Serial LCD Pin OBD-II-UART Pin
GND GND GND
5V 5V None
D3 Rx None
D0(Rx) None Tx-O
D1(Tx) None Rx-I

 

L’ELM327 est un adaptateur entre les protocoles standardisés automobile et un classique port RS232.

La communication PC s’établie à 9600 ou 38400 bd, 8 data bit, no parity, 1 stop bit.

Toutes les demandes/reponses se termine par un CR (0x0D) et eventuellement un LF si paramétré

Le “>” (0x3E) est le caractère de prompt.

Get Vehicle Speed

Speed’s PID is 0D:

>010D       <---- Envoi de la commande
41 0D FF    <---- Réponse ELM (rappel de la commande 0D et valeur FF)

To get the speed, simply convert the value to decimal:

0xFF = 255 km/h

 

 

QUand on commence à demander quelque chose à l’ELM, ce dernier attend 20s avant eventuellement d’envoyer un ”?”, afin d’indiquer qu’il n’a pas compris ce qu’on demandais et de fait rien executé.

L’ELM est insensible à la casse, aux espaces, et aux tabulations. Dans le decodage des reponses, il faut ignorer le caractère NULL (0x00).

Lors de l’établissement de la com, la première chose à faire est d’envoyer un CR. L’ELM va alors repondre par un ”?>” indiquant qu’on peut commencer le dialogue

La séquence d’initialisation, est à effectuer juste après l’établissement de la COM. Elle permet d’indiquer à l’ELM la façon dont il doit communiquer avec le PC. Voici les commandes usuelles à utiliser:

  • <CR>: Permet de repeter la meme commande que la precedente
  • AL: permet d’autoriser les message long à l’envoi vers l’ELM (8 octets) et illimité vers le PC. A off par defaut. A UTILISER
  • AT0, AT1, AT2: permet de parametrer plus finement le temps de reponse. Par defaut, l’ELM les regle.
  • ATRV: Permet de lire la tension batterie (pont diviseur R1=47K, R2=10K), precision 2%, 28V max
  • ATE0: Desactive(0) ou non l’echo (si activé, l’ELM renvoie alors les caractères reçu pour verif eventuelle)
  • ATL0: Desactive (0) ou non l’utilisation du <LF> apres le <cr>
  • ATS0: Affiche ou non les espaces (l’ECU repond en separant d’un espaces des paquets de 3 octets pour plus de lisibilité, au detriment de la vitesse)
  • ATSP0: Permet de parametrer le protocole à utiliser (0=mode auto)
  • ATH1: Affiche (1) ou non les entetes (pour debug principalement? affiche des messages en sus)
  • ATDPN: permet de recuperer le numero du protocole utilisé, précédé de A en mode auto
  • ATR0: desactive ou non le renvoi direct des messages du calculateur (utile?)

envoyer la première commande OBD2 (pas AT) (qui doit etre 0x0100), l’elm repondra un “searching…” puis enverra des nombres (voir p30 doc V2)

 

Understanding the Sketch

This example sketch is very simple. The Arduino simply communicates with the OBD-II board and then sends the information received to the LCD screen. You will need to include the SoftwareSerial library in order to communicate with the LCD screen. Set the LCD TX/RX lines to pins 2 and 3 on the Arduino, and initialize the rest of your variables.

#include <SoftwareSerial.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.

SoftwareSerial lcd(2,3);

//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;

In the set up loop, the serial port for the LCD as well as the serial port for talking to the OBD-II board are both initialized at 9600 bps. The screen is then cleared, and the variable names of Speed and RPM are printed on the first and second rows respectively. As we did before, the OBD-II board is then reset.

void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  lcd.begin(9600);
  Serial.begin(9600);

  //Clear the old data from the LCD.
  lcd.write(254);
  lcd.write(1);  

  //Put the speed header on the first row.
  lcd.print("Speed: ");
  lcd.write(254);
  //Put the RPM header on the second row.
  lcd.write(128+64);
  lcd.print("RPM: ");

  //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();
}

The main loop of the code simply sets the cursor locations, clears out any old data on the LCD screen, receives the data from the OBD-II board, tranlates it to an integer and prints the vehicle speed and RPM to the screen.

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.write(254);
  lcd.write(128+8);
  //Clear out the old speed data, and reset the cursor position.
  lcd.print("        ");
  lcd.write(254);
  lcd.write(128+8);
  //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
  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.write(254);
  lcd.write(128 + 69);
  //Clear the old RPM data, and then move the cursor position back.
  lcd.print("          ");
  lcd.write(254);
  lcd.write(128+69);

  //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
  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 final section of code simply defines the functions to communicate with the OBD-II board. This saves any incoming characters to the serial buffer until a carriage return is received.The buffer index is set to 0 and the board then waits for the next string to come in.

COPY CODE
/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]='';
        //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;
      }
    }
  }
}

 

 

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.

Articles récents
Commentaires récents
fatima dans Bienvenue !
AdminDroid dans Bienvenue !
fatima dans Bienvenue !
Archives
Catégories
%d blogueurs aiment cette page :