[Hello, i am trying to interface ELM 327 with arduino. Here is the elm327's datasheet: (https://www.elmelectronics.com/wp-content/uploads/2016/07/ELM327DS.pdf)
Communication is described on page 31. You need to send two hexadecimal numbers (the pid adress) and receive the message sent back from the elm(again in hexadecimal). My question where to look for reference so that i can write a sketch to send and receive hexadecimal numbers through a serial connection. Basically i need to make something like a serial terminal with arduino. So far i know i will have to use SoftwareSerial library to add another serial port but i could really find some more information.
More info required. If you're just looking to talk, UNO to/from OBD, you can use the built-in serial. But if you also want to display the data on Serial Monitor, or transmit it elsewhere, then yes, you need two serial ports, so use software serial for the second port; but remember, software serial only really works at low baud rates, aka 9600 or lower.
Please provide more information, so that helpers can help. Schematic would also be useful.
There are many Arduino devices that have more then one serial port such as the Mega and the ESP device. Software serial is nice but it is blocking code.
I need 34800 baud rate for the communication with the elm. In the final device the data will be displayed on lcd. A second serial connection will be required for debug only. I haven't included schematic - it's just rx an tx pins from the elm to the arduino.
You can still do it with the UNO, but it will be a pita. You cannot use Serial Monitor for debug, so maybe wire in an LCD display for diagnostics? Frankly, I'd do my development on a Mega in this case, just so I had multiple serial available; as pointed out by @gilshultz there are other solutions.
I have a mega that i can use for the prototype, not a problem and then use an uno or nano for the final device. To start i am confused which function should i use Serial.print() or Serial.write() ? What is the difference?
Let me see. The Arduino Reference for Serial.write() says:
Writes binary data to the serial port. This data is sent as a byte or series of bytes; to send the characters representing the digits of a number use the print() function instead.
The Arduino Reference for Serial.print() says:
Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit. Floats are similarly printed as ASCII digits, defaulting to two decimal places. Bytes are sent as a single character. Characters and strings are sent as is.
So, what do you think?
Try this link, it has a nice example with setup. Serial.begin() - Arduino Reference
Since terminal programs send ASCII characters i should be using Serial.print to send the data to the elm and then Serial.read() to read it back?
I've got to go, but I suspect Gil can help you - please refer to the link he posted, then try something and come back with a sample code and questions.
When people say HEX it is confusing as there are several formats it can be sent in. There is the ascii format where each nibble is converted to an ascii character or where each byte is sent as one binary byte.
Examples: 0X31 is the same as 00110001B is the same as "1" in ascii or "31" as ascii Hex. The System does not care what format you send it in, it is determined at the receiving end. Many times there is some software between the UART and your code that can also put limitations on it. My suggestion is to look up either or both the intel or motorola Hex or S records used for transferring data. You can modify it and remove the address portion. They use checksums so the reliability is fairly good. Here is a link to the S record format: http://www.amelek.gda.pl/avr/uisp/srecord.htm and one for the Hex: Intel HEX - Wikipedia
So i found that code for at terminal with arduino:
#include <SoftwareSerial.h>
#include <string.h>
char incoming_char = 0;
SoftwareSerial cell(2,3);
void setup()
{
// Initialize serial ports for communication.
Serial.begin(38400);
// Reset
Serial.println("Start Reset");
pinMode(7, OUTPUT);
digitalWrite(7, HIGH);
delay(1000);
digitalWrite(7, LOW);
delay(1000);
Serial.println("End Reset");
cell.begin(38400);
Serial.println("Enter your AT commands (with CR & NL)...");
}
void loop()
{
if(cell.available() > 0)
{
incoming_char = cell.read();
if((incoming_char >= ' ') && (incoming_char<='z'))
Serial.print(incoming_char);
else
{
//Serial.print("%");
Serial.print((int) incoming_char);
//Serial.print("%");
if(incoming_char == 10)
Serial.println();
}
}
if(Serial.available() > 0)
{
incoming_char = Serial.read();
cell.print(incoming_char);
}
}
and when i enter at z
commnd on the serial monitor the elm resets as expected. Then i tried putting
cell.print("at z");
in the code but the elm doesn't reset. So there must a problem with the encoding. What data tyoe should i use so that i can send at z
the same way the serial monitor send is?
The ELM 27 data sheet suggests using a simple terminal program as a test.
Like CoolTerm or PuTTy.
All comms appear to be within the printable ASCII printable range.
HEX in this case is human readable characters '0' through '9' and 'A' through 'F'.
At this point you shoukd thank the creators. I wish all comms hewed more to this kind of easily testable and usable interface.
a7
Well, i seem to have a problem with the Serial.Print() function. When i send only one character, for example Serial.print("a")
it gets printed ok. But when i try Serial.print("at z")
in the serial monitor i get a bunch of numbers like this
cell.print("at z");
Try
cell.println("at z")
Or
cell.print("at z\r\n");
Please do not spam the forum with screen shots, you may not realize it but they're a huge waste of space and bandwidth, and are rarely legible unless they're so large they're unmanageable. Instead, simply cut and paste from your screen into your forum message.
Huge thank you! Adding \r\n
worked!
It's never too soon to start using manufacturers' datasheets. In the ELM27 data sheet you might have seen
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.
Depending on settings, the responses will be terminated with a carriage return and maybe a line feed character.
Datasheets can be a slog - read them like you know what is being said, you'll get better and better and finding stuff like this.
a7
I read the datasheet but its my first time i stuble across carriage return character, thats why i got into that problem. Now i have another problem. The elm is giving some random numbers on the command 01 05
it should return something 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. Instead i am getting that:
a3-2-63-1-55-110-59-2-43-1?1313>-59-2-63kE10U-86-882-126-86j?1313>-123-2-63kSTOPPED1313>-59-125-25*2120TCLLM-61STOPE13>10-1STOPPED1313>-117-2-63STO0STPST-96-117-75-76Q-87TO-59STO-59E-115-123STOQ=A-1231E-115-59-117S-98AX=A-117STO-59STO-59U-88Q)TOSTPSTO-117STO-117STO-59STOSTO-59STO-117STO-59STO-117**(STASTO-60STO-118E-115-59STO-117STPSTO-117STO-5921-43*-59STO-59STO-59Q=A-59STO-59*2120STP21-4310-115*-4310-118STO-59STO-59UTQSTO-59STPSTO-117STO-59S=ASTOSTO-117STO-59STO-59"-115-123STOSTO-117STO-117STO-59SO-96STPSTO-117STO-117STO-118Q=A-123STO-117STPSTO-59SOPSTO-59STO-117-87TOSTO-59STO-59S>ASTO-117STPSTO-123STO-127-94-115-117STO-63**20**(STPSTO-117STO-59U-108QSTO-59S-98ASTO-117STO-11821-43*-59STO-59STO-117-118-4321-59STO-117STO-117STO-59ST-96S
I see there is some pattern but absolutely no useful data. The datasheet doesn't give me hint as well. That's the code i use to read the data:
void loop()
{
if(cell.available() > 0)
{
incoming_char = cell.read();
if((incoming_char >= ' ') && (incoming_char<='z'))
Serial.print(incoming_char);
else
{
//Serial.print("%");
Serial.print((int) incoming_char);
//Serial.print("%");
}
}
cell.print("01 05\r\n"); //ect
delay(100);
//cell.print("01 0B\r\n"); // intake manifold press
// cell.print("01 0F\r\n"); // iat
// cell.print("01 10\r\n"); // maf
}
What might be wrong?
Stop sending the request until you have gathered a complete response!
I think you are confusing the device.
You can use standard techniques for getting an entire packet, made simple by the consistent end marker (carriage return + maybe linefeed).
Oh - that delay() isn't helping and won't be necessary if you do gather a complete response.
a7