Serial.read timing

I'm sending a 10bit binary number from a Android app (written in MIT AI2) to a Nano via a HC05 Bluetooth transceiver, connected to the Tx/Rx pins of the Nano.

My understanding is that each time Serial.read() is performed, the first available byte in the serial input buffer is read and removed, and the subsequent bytes are shifted along. So the following ought to read the incoming data into two respective variables.

Except sometimes the bytes are read the wrong way round, sometimes I get the value -1 for one of the variables, and sometimes it works as i expect.

I assume its something to do with the timing, but i can't figure out how to get consistent results.

void loop()
{
  static int data_lsb = 0;
  static int data_msb = 0;

  if (Serial.available() >0)
  {
    data_lsb = Serial.read();
    data_msb = Serial.read();
    
    lcdDisplay.clear();
    lcdDisplay.setCursor(0, 0);
    lcdDisplay.print(data_lsb); 
    lcdDisplay.setCursor(0, 1);
    lcdDisplay.print(data_msb);
     
    delay(2000);
  }
}

you test if you have at least 1 byte available but you read 2.... may be the second one is not there yet...

you could hack this with

  if (Serial.available() >= 2)

but I would suggest to study Serial Input Basics to handle this

2 Likes

I've read that tutorial and, considering I know I'm always looking for 10bits, Example 4 (for reading multi byte numbers) seemed unnecessarily complicated.

Will try >=2

if you don't have an end (or start) marker, if for some reason a byte goes missing you have no way of sync-ing the communication... that's the challenge with crude binary transmissions.

another way is to send the 10 bit value in ASCII followed by a line feed. it's 5 byte max instead of 2 - so whilst it's somewhat slower but very easy to debug and get in sync.

Probably the simplest in many respects would be to break your 10-bit binary value into 2 5-bit values, and merge each with three high bits, '011'. Done that way, both bytes will fall into the high end of the ASCII 7-bit range (all printable values). Precede those characters with a preamble of, for example, 0x0D, and you have a guaranteed primitive packet to look for at the Arduino end, because your payload characters are guaranteed to be distinct from the preamble, and data order is obvious.

Nice idea

It took me a while to get my head round that, but thanks.

You're welcome. Ya, it's a little complex to explain, but it's only a few bit-shifts and masks in code. Sometimes the easy solutions are hard to describe.

UART Port of your NANO expects asynchronous (async) frame of 10-bit wide consisting of: STARTBit(1), CharacterBits(8), STOPBit(1).

Your Android's Bluetooth Interface must be sending frame similar to above to the HC05 BT either in ASCII or BIN mode.

You are saying 10-bit number by which you really mean a 10-bit binary number like 1010101011 (for example) and not the 10-bit of an async frame?

If you are saying that the given 10-bit value is a binary number, then your Android application is/should be able to break it into two bytes (00000010 and 10101011) automatically and send them to BT over two async frames. After that you follow the trick of post #2 to receive the two bytes and merge them to create 10-bit original data.

I think what OP was saying is that he has a value between 0 and 1023 to send over. It's likely stored in a uint16_t for example

And could also originate from a 10-bit analog conversion, for example. Which is where my idea once came from, transmitting the result of an analog read on one Arduino to another Arduino for processing.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.