Serial.Read() and incorrect values

Hello guys,

I am kinda new to Arduino but experienced in C#/C++.

I am trying to build a project that will read from a serial device and display the data on an LCD screen using an I2C interface.

My problem is that I'm getting incorrect values when reading from the device. First of all what the device does is it is broadcasting 14 bytes answer continiously (you don't have to query it, it just sends the data over and over). I am using hterm as an auxiliary tool to see what the device does and it seems that it sends more than 1200bytes/second which sounds correct as if you divide 9600/8bits it equals to 1200 bytes. The bytes are 8 bit values, not 16.

So to determine the start of the message it sends 3 characters, 0-1-2 and then 11 bytes of data. When I use hterm and check the dec checkbox I can see correct values of the data. Same when I was testing using C# and read the data as Bytes (using ReadByte() in VS2012).

When reading the data from my Arduino I send them on my lcd screen and I get wrong values. I read the data using Serial.Read() and store them in a byte variable, then lcd.print them.

I am never able to see the start bytes 0-1-2 and it seems like the data is being repeated but it looks like they are 10(?) instead of 14.

So I have the following questions:

  1. Does anyone has a clue why I get different values than those on hterm? And never see the header bytes 0-1-2?
  2. I understand that 1200 bytes/sec are a lot for the Arduino to handle but I don't care if it discards some of them as I can determine correct full sets of bytes using the header bytes (IF they decide to appear) :zipper_mouth_face: Is the size of the Serial buffer 128 bytes indeed? What about the rest on the serial bus?
  3. Arduino's Serial.Read() reads the last arrived byte or the oldest in its Serial buffer?
  4. Is it possible to receive a corrupted byte or once I have managed to received a byte it must be correct?
  5. For being able to see the data I use a delay of 300-500ms. Is this affecting the reading of the serial stream? What is the Arduino doing during the delay? The device is still broadcasting data. Is it discarding them?

Thank you all in advance!

  1. nothing. However the buffer is only 64 bytes so you will overrun the buffer if you put a delay so big in the code.
    It is hard to say much without seeing your code.

  2. the buffer is a first in first out buffer.

Also how is it wired? RS232 needs to be converted into TTL for the arduino.

  1. Probably the voltage levels, as Mike said.

  2. 1200 baud is hardly a lot. I talk to mine at 115200 baud.

  3. Naturally Serial.read gives you the bytes in the order in which they were received. It would be pretty useless otherwise.

  4. What do you mean by "receive a corrupted byte"? If there is an electrical problem you might.

For being able to see the data I use a delay of 300-500ms.

I don't see how a half-second delay helps you "see the data". Do you mean, as a human?

I assume he means that the communication with the LCD takes half a second.

I think the Blink without Delay exhrtation belongs here.

@Mike What do you mean the values have to be converted into TTL? What I'm doing right now is to get the tx cable from the device and put it in the rx pin on the arduino. Then ground to arduino's ground. Won't that work?

@Nick. So if you talk at 115200 baud, how does your incoming buffer cope with that? Is it ok? Should be discarding a lot of bytes right? When I'm saying 500ms delay yes I mean human.. The lcd refreshes so fast below 200 that is very difficult to read, plus you have to make sense of what you see. Can I log someway so I can see the values later?

What kind of tests should I perform to find the problem?

In my case incoming data (from me to the Arduino) is generally fairly low-quantity. So yes, the buffer handles it. Outgoing (eg. a lot of information about sensors) it can spit out quite fast.

Here's an example I did a while ago decoding MIDI:

That example also reads serial input at 31,250 baud (the MIDI input) whilst simultaneously decoding what it means and printing it.

Should be discarding a lot of bytes right?

Well, average it, sum it, calculate min/max. That sort of thing.

which sounds correct as if you divide 9600/8 bits it equals to 1200 bytes.

you must count 10.5 bits per byte on average as the 9600 baud includes start and stop bits and "between the bytes" time.
so 9600 baud results in about 900 bytes per second on full throttle. 115.200 baud => ~10KByte/sec (extreme max)

clubman:
... hterm and check the dec checkbox ...
... on my lcd screen and I get wrong values.

Try checking the "dec checkbox" on the LCD.

@Mike What do you mean the values have to be converted into TTL? What I'm doing right now is to get the tx cable from the device and put it in the rx pin on the arduino. Then ground to arduino's ground. Won't that work?

That will only work if the device sends data with TTL voltages. If your device is sending RS232 voltages they need to be converted into TTL voltages before putting them into the arduino.

clubman:
@Mike What do you mean the values have to be converted into TTL? What I'm doing right now is to get the tx cable from the device and put it in the rx pin on the arduino. Then ground to arduino's ground. Won't that work?

I am trying to build a project that will read from a serial device ...

What device?

A RS232 device will send (roughly) -12V as a "1" bit and +12V as a "0" bit. TTL levels are +5V for a "1" bit and 0V for a "0" bit.

For one thing, -12V is way out of range for the Arduino input, and for another it is inverted logic.

RS-232 is an old communications interface standard. Among other things, it describes the voltage levels at which devices transmit. For an RS-232 interface, a low voltage is something between -3 volts and -25 volts, relative to the signal ground. A high voltage is between +3 volts and +25 volts, relative to the signal ground. In RS-232, a zero is a high voltage, and a one is a low voltage.

The Arduino uses a different voltage standard. It uses the logic levels that the rest of the Arduino uses - a zero is a logic low level, close to 0 volts. A one is a logic high level, close to 5 volts. The Arduino doesn't do well with signals that are lower than 0 volts, or higher than 5 volts. If you connect a bona fide RS-232 signal directly to the Arduino, you could damage the Arduino.

We don't know yet whether your "device" transmits an RS-232 signal, or a logic level signal. You mention that you use "hterm," suggesting that you're connecting the device to a computer of some sort. We don't know yet whether you connect to an RS-232 connector on that computer, or to a USB port, or some other kind of interface. We can't tell whether it's safe to connect the device directly to the Arduino. I'll advise against connecting to the Arduino any further until that gets sorted out.

If the device uses RS-232, you'll need some kind of circuit that can accept an RS-232 signal - a signal that goes both positive and negative - and delivers a logic level signal - something close to 0 volts or 5 volts. That circuit also needs to reverse the sense of the incoming signal. It needs to deliver a logic high voltage - 5 volts or so - to the Arduino when it receives an RS-232 low voltage from the device, and vice versa. Those circuits are often integrated circuits, called "line receivers." They operate from 0 volts and 5 volts DC, so they're fairly easy to hook up.

But, before you go hunting for a line receiver, tell us more about the device. If you have a manual, look up the communication interface. If you don't have a manual, maybe you have a manufacturer and model number. And, tell us how you're connecting to hterm. If it's not a connector that you can readily describe, maybe you could post a picture.

Having said all that, here's what I suspect: You're collecting data as characters, and when you try to print to the LCD, you say something like

lcd.print(x);

I think that print() sends the unmodified value when its only argument is a character. So, when you try to print to the LCD, and the data is, say, a 0, it sends a genuine 0 to the LCD. I don't know what the LCD displays for that character.

What you really want to see is the character, '0'. The ASCII value that corresponds to the character '0' isn't 0, but 0x30, or 48 decimal. I'll suggest that to make this work, you want to say

lcd.print(x,DEC);

I believe that instructs serial to send the ASCII representation of the value 0, which is the character '0'.

I deduce all that from this sentence:

When I use hterm and check the dec checkbox I can see correct values of the data.

That tells me that you have to ask hterm to show you the decimal values of the characters that it receives, rather than the characters themselves. If you send the same data to the LCD, you need to tell print() to send the ASCII representation of the characters' decimal values in order to see decimal readings on the screen. To test that theory, what do you see in hterm when the "dec checkbox" isn't checked?

Don't try it yet, though. It's possible that you have an RS-232 device, and you're connecting to the RS-232 interface on a computer to use hterm. If you connect that directly to the Arduino, you could fry the pins. It's also possible that earlier connections you made didn't damage them, so you don't want to stress the pins further. Let's get that figured out first.

That's a very helpful post tmd3, thank you very much!

So what I do when reading is to do inByte=Serial.Read() and store that in a byte variable (inByte). Then I do some kind of calculation, for example, calc=inByte/2 and lcd.print(calc). Don't have the code right now but will come back with it. I don't use any character read, tried that but of course didn't work.

I don't know if it is TTL logic or RS232. But what I do when connecting to hterm is to connect via and FTDI RS232-USB converter. So the pc probably gets TTL values, right?

I also do have a device like this one:
http://www.ebay.com/itm/1x-USB-to-RS232-TTL-PL2303HX-Auto-Converter-Module-Converter-Adapter-/181174462419?pt=AU_Car_Parts_Accessories&hash=item2a2ed6e7d3&vxp=mtr

May I try to connect that module's RX and GND to the device's GND and TX and then get the GND and TX of the module's USB to the arduino's RX and GND? Then I will have TTL logic values to the Arduino and if that's the case it should work, right?

I don't know if it is TTL logic or RS232.

OK

But what I do when connecting to hterm is to connect via and FTDI RS232-USB converter. So the pc probably gets TTL values, right?

That tells you your device is sending RS232 data. Do not connect it directly to the arduino.

May I try to connect that module's RX and GND to the device's GND and TX and then get the GND and TX of the module's USB to the arduino's RX and GND? Then I will have TTL logic values to the Arduino and if that's the case it should work, right?

I don't understand those words it sounds garbled to me.
However, no amount of monkeying around with the connections into a RS232-USB converter will allow you to get at TTL values. You ether need to break into the module and fish out the TTL levels from inside it, which given you asking the question in the first place I suspect you are not up to doing. Or you get a RS232 to TTL converter circuit, either a chip or some transistors and resistors.

Until this issue is sorted there is nothing you can do with the software.

Confirmed that it sends RS232 data. So I need an RS232-TTL module.

What I said about the connections is that in simple words I will put the RS232-TTL module in between the device and the arduino so that it translates the data from RS232 to TTL.. Device's TX goes to module RX, makes the translation and then module's TX goes to Arduino's RX.

I will put the RS232-TTL module in between the device and the arduino so that it translates the data from RS232 to TTL.

OK that is fine.

Device's TX goes to module RX, makes the translation and then module's TX goes to Arduino's RX.

That all depends on how the device is classed.
There are two classes of serial equipment DTE Data terminal equipment - Wikipedia
and DCE Data circuit-terminating equipment - Wikipedia
Each has a different way of defining whether RX is an input or an output and the same goes for TX.
Make sure you always connect an input to an output. This might mean connecting two TX lines together or it might mean connecting a TX to an RX.
When in doubt always check with a meter or a scope which is an input and which an output.

How can I check with a meter what is the output? You mean by connecting it to a hyperterm program and send something etc?

Yes that is one way. You could also connect an LED and resistor and see if it flickers when you send stuff.

Cool.. One of these days I'll try the ttl thingy and will let you know guys, thank you again!

Guys I have a question, do I have to write code for the ttl-rs232 converter or is it supposed to do its magic just by connecting it inbetween the arduino and the device correctly?

No code it is just hardware.