The way Arduino serial reads

Hi everyone!!

I’m trying to communicate with a Engine control unit (ECU) using an Arduino Uno. I have logged the data that the ECU is sending using a computer. However when I connect the ECU to the arduino using a software serial port and try to read the incoming data, I get some nonsense data. Consider this: 800100C817181BDC 8281800100C817181BDC 8281800100C817181BDC 8281800100C817181BDC 8281800100C817181BDC.
There is a notepad full of the repeating blocks above.
I hope you can spot the repeating data blocks. However when I use the following code:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
char buf [20];

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

Serial.println(“Goodnight moon!”);

// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
mySerial.println(“Hello, world?”);

}

void loop() // run over and over
{
if (mySerial.available()>0){
Serial.println(mySerial.readBytes(buf,20));
Serial.write(buf);
}
}

This is a portion of what I get in the serial port monitor:
Goodnight moon!
20
oÑÏÉGûúþúÿoÑÏÉGûúþúÿ>oÑÏÉGûúþúÿoÑÏÉGûúþúÿoÑÏÉGûúþú20
oÑÏÉGûúþúÿoÑÏÉGûúþúÿ>G

And there is a lot more where that came from.

I am not really sure how and why is arduino interpreting the data like this.
I appreciate any help.

Code tags please. Including around the output.

Read this before posting a programming question

How to use this forum

  mySerial.begin(9600);
  mySerial.println("Hello, world?");

What happens wen you print to the serial port of the ECU? Is this really what oyu wanted to do?

   if (mySerial.available()>0){
  Serial.println(mySerial.readBytes(buf,20));
  Serial.write(buf);

There is no readBytes method in SoftwareSerial. You are printing buf to your PC before you have put anything it it, and before it is NULL terminated.

Read the docs on Serial.write() to make sure you really want to send binary data after sending buf once already.

While I'm at it, I should tell you that just because .available is > 0, you cannot assume that it has all the data you want.

Serial.write(buf);

In addition to the problems lar3ry points out, realized that Serial.write() sends raw binary. Not everything it sends is printable.

This part doesn't make sense to me:

JimboJohn:

void loop() // run over and over


    if (mySerial.available()>0){
  Serial.println(mySerial.readBytes(buf,20));
  Serial.write(buf);
    }
}

If you want to echo everything you receive from mySerial onto Serial then just read the input characters as they become available and write them individually to the output:

void loop() // run over and over
{  
    if (mySerial.available() > 0)
    {
        Serial.write(mySerial.read());
    }
}

If you want to echo everything you receive from mySerial onto Serial then just read the input characters as they become available and write them individually to the output:

void loop() // run over and over


    if (mySerial.available() > 0)
    {
        Serial.write(mySerial.read());
    }
}

I agree with what all of you guys said. I actually simplified my code to what Peter mentioned and I have quoted above. But even the I do not get what I am supposed to get which are blocks of “8281800100C817181BDC”.
Just to clarify things further I tell you exactly what I did after changing my code to above. I connected Arduino Uno to my computer using USB. I inserted the RS-232 of the ECU in the virtual RX pin whenever I wanted to see the incoming data. This time I used a software called “Realterm 12C” which allows you to monitor anything that is coming through Arduino’s serial port to the computer’s in a variety of formats (i.e. hex, Ascii etc.).
Under no circumstances ( using “Serial.write” and “Serial.print” in the code above), I managed to get the right block of information.
Now, I am willing to attach my results from the Realterm application, but I have a theory and I’m not sure whether it is wrong or not. I believe that when data is transmitted from the ECU to Arduino, the Arduino some how encodes it in a way that I can’t figure it out. Mind you that my baud rate is also synched with the ECU, so it cant be that. Also consider that I get the right block of data when I connect the ECU directly to the computer using a RS-232 to USB and monitor it using Realterm. I am clue less about what is happening and truly appreciate any help.

I inserted the RS-232 of the ECU in the virtual RX

That’s a good way to destroy your Arduino. RS232 uses + and - voltages for off and on bits, not 0 and 5. The + voltage can be as high as 15V. Neither that or the negative voltage is good for the Arduino. And, the meaning of off and on is different in RS232 and TTL.

You need a MAX232 in between to convert RS232 to TTL levels.

Simple thing to check, The arduino is set to 9600 baud in your code. What Baud rate is the ECU using? What baud rate is the serial monitor using?

Also, i dont know what arduino your using, but software serial should not be necessary. then built in serial communication should be all you need.

First things first, I really appreciate that you guys put the time and effort and answered my question. Now:

That's a good way to destroy your Arduino. RS232 uses + and - voltages for off and on bits, not 0 and 5. The + voltage can be as high as 15V. Neither that or the negative voltage is good for the Arduino. And, the meaning of off and on is different in RS232 and TTL.

I measured the voltage output of ECU's RS-232, it was 5V, so I don't think that should cause any issues for the Arduino.

Simple thing to check, The arduino is set to 9600 baud in your code. What Baud rate is the ECU using? What baud rate is the serial monitor using?

Also, i dont know what arduino your using, but software serial should not be necessary. then built in serial communication should be all you need.

I think I have clarified that I am using an Arduino Uno.

Just to clarify things further I tell you exactly what I did after changing my code to above. I connected Arduino Uno to my computer using USB. I inserted the RS-232 of the ECU in the virtual RX pin whenever I wanted to see the incoming data.

I always made sure that the ECU is set to the same baud rate as the Arduino serial and software serial. Nonetheless, I changed all the baud rates to 19200 as that was the suggested baud rate in the ECU manager software. Later in my testing I actually connected the ECU directly to the RX pin of the Arudino instead of the virtual one. I got the same result as you saw in the pictures. I am sure of it. Just let me sum it up: I had the baud rates right and same between ECU and Arduino and I know that RS-232 of the ECU out puts maximum 5 V.
Still I dont know why when I connect the ECU to my computer using a RS-232 to USB converter, I get the expected results, but when I connect the ECU through Arduino to my computer I get encoded or irrelevant data.
What Arduino is dong to my data before it reaches the computer is still a mystery to me.

Can you post, inside code tags, the sketch you used to output the hex data you posted above?

And to clarify, you are expecting:

82 81 80 01 00 C8 17 18 1B DC

Is that right?

What Arduino is dong to my data before it reaches the computer is still a mystery to me.

It's not doing anything to your data. I suspect the signal is inverted if it is that far out. With SoftwareSerial you can invert the logic, you might want to try that.

Despite what you say about measuring 5V, I suspect that you need an interface. If it is +/- 5V with idle (zero) being high, then you would in fact expect to measure 5V most of the time. However a one-bit would be -5V which the Arduino both won't like electrically, and will read inverted, leading to rubbish.

So the Arduino is not doing anything to your data, you have not got the correct hardware interface.

As PaulS said further up.

I think someone posted recently a simple RS232 converter circuit (for receive only) that used a simple transistor configured as an inverting buffer.

Something like this:

From: RS-232 vs. TTL Serial Communication - SparkFun Electronics

The bottom half: TXRS232 to RX-TTL.

Here's my stab at something similar:

(Subject to the electronics experts saying I haven't done a major blunder).

Here's another similar one I found:

A bit of testing indicates that my circuit above, minus R1, seems to work OK:

Test:

Note that the input voltage is ±5V, but the output is 0V to 5V inverted. (Actually it goes to 5.44V but that is within spec for an input pin).

Tested at 115200 Hz, the waveforms look OK. Blue is input, yellow is output.

Hi jimbojohn,

I had a same problem as yours when trying to communicate with mitsubishi ecu. Luckily i have logic analyzer to trace it out and solve the problem. For your info, some of serial signal are inverted and i hope you can double check it. Another thing is, my ecu communicate in multiplexing and it will generate an echo signal.

For further reading you can read my blog at http://mitsuduino.blogspot.com/

Can you post, inside code tags, the sketch you used to output the hex data you posted above?

And to clarify, you are expecting:

Code:

82 81 80 01 00 C8 17 18 1B DC

Is that right?

Here’s my code after I changed to normal serial port instead of the virtual one which obtained the results that I attached in form of pictures previously:

#include <SoftwareSerial.h>
#include "ST7565.h"
#include "stdlib.h"
//#include "stdafx.h"
#include "Arduino.h"

SoftwareSerial mySerial(10, 11); // RX, TX
char buf [10];
char yolo[10];
int i = 0;

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(19200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(19200);
  mySerial.println("Hello, world?");
  

}

void loop() // run over and over
{  if(Serial.available()>0){
  Serial.write(Serial.read());
  Serial.print(" ");
    //if (mySerial.available()>0){
      //Serial.print(mySerial.read(),);
      //CF C9 47 FB FD FE FA FF 6F D1
      //Serial.print(" ");
     /* for (i = 0;i<10;i++){
  buf[i] = mySerial.read();
      }*/
  //Serial.print(buf);
  //sprintf(yolo,"0x%u",buf);
  //Serial.print(buf);
  //Serial.print(yolo);
  
    }
}

And let me confirm that the result that I expected was blocks of :

82 81 80 01 00 C8 17 18 1B DC

I would like to thank you all for pointing me in the right direction, particularly Nick Gammon for his persistent effort. After talking to another team member, we decided to buy a RS232 Shield. I would like to know your opinion regarding this approach.

That's fine. Do you need to send as well? If not a transistor, a diode, and a couple of resistors seem to me to be a cheap alternative.

I've used the below simple transistor and two resistor inverter setup since 2004 with any issues.

Thanks. We might need to consider sending some data later on, but at the moment just focused on receiving. By the way may I ask what type of transistor and diode did you use?