Serial.readBytes and Serial.write data types compiling error.

Hello,

I've new to Arduino development, so I'm just trying out various things. When I try to get Serial.readBytes into an array of 8 bytes, with data type byte, I get a compilation error. If I change the data type to char instead of byte, it works fine. From the reference, it said I can use either char or byte data type. I'm wondering what I did wrong. Also, If I want to send the 8 bytes back, it expects data type byte instead of char. So, I'm totally confused. I tried searching the forum first, but I did not find what I was looking for.

byte receiveSerial[8];      // Byte array for receiving 8 bytes of unsign data

void setup()
{
  // initialize the serial communication:
  Serial.begin(9600);
}

void loop() {
  // check to see if the host sends data to the board (expects 8 bytes from host)
  if (Serial.available() > 0) {
    Serial.readBytes(receiveSerial, 8);  // get 8 bytes
    Serial.write(receiveSerial, 8);  // loop it back to host
  }
}

Error for compiling
sketch_aug28a.ino: In function 'void loop()':
sketch_aug28a:12: error: invalid conversion from 'byte*' to 'char*'
sketch_aug28a:12: error: initializing argument 1 of 'size_t Stream::readBytes(char*, size_t)'

From the reference, it said I can use either char or byte data type. I'm wondering what I did wrong.

The class definition doesn't say that, though. The reference page is not entirely correct. You can use either type array, but one needs a cast.

Also, If I want to send the 8 bytes back, it expects data type byte instead of char.

Code is written by people. People are not consistent.

Thanks for the explanation Paul. Casting the data type works fine and I can work with that, but it kinda defeat the read byte/ write byte function.

but it kinda defeat the read byte/ write byte function.

How? The compiler has the issue. Lying to the compiler doesn't necessarily affect the resulting code.

A cast is telling the compiler that it can treat one type as another type. Sometimes that is true (byte and char are the same size, though with different ranges of values). Sometimes it isn't (a float and a long are the same size, but the data representation is completely different).

Hi both - I bumped into exactly the same problem - but unfortunately I'm new to Arduino and C.
I get the concepts but don't know all the terminology - what is 'cast'?

There are a couple of nice Stream functions that I'd like to use (like Serial.readBytes) but I am communicating in Bytes, not char's and I get the same error.

Could you paste some code that would work - e.g. Using 'Serial.readBytes' on an incoming stream of Bytes, and storing the results in an array of Bytes? Thanks so much!!

A cast is more of a conversion. If you cast a float to a long, you don't get the literal bit representation of the float, you get the closest the compiler can generate.

Thanks KeithRB!

so are we talking about putting a byte() in front of any array-name[ i ] ? That doesn't sound so great.

Is 'Serial.read' the only function that can read straight into bytes? that would be a shame. I like the Serial.readBytesUntil but despite what it says in the reference it seems to only work with char arrays.

This is what the reference says:


Syntax

stream.readBytesUntil(character, buffer, length)

Parameters

stream : an instance of a class that inherits from Stream.
character : the character to search for (char)
buffer: the buffer to store the bytes in (char[] or byte[])
length : the number of bytes to read (int)

If you have a function that accepts only bytes, like:

void byteMe(byte *someBytes);

and you have a character array:

char tastyStuff[20];

you can use tastyStuff in the call to byteMe(), like so:

byteMe((byte *)tastyStuff);

The (byte *) before the variable name is a cast. It tells the compiler to treat the variable tastyStuff as though it was of type byte *, rather than char *. Since byte and char are the same size, there is no problem, as long as the values in the array are legal as both byte and char. (char is signed; byte is unsigned - values of -64 or 189 will cause problems, depending on which way you are casting).

I like the Serial.readBytesUntil but despite what it says in the reference it seems to only work with char arrays.

Not strictly true. It only works with char arrays without the need to cast. With a cast, it will work with byte arrays.

Thank you PaulS! that is super helpful. I would want the array to be a 'byte' array - if I do any conversion at all between byte and char I'd rather do it as I receive the data from the serial interface, and have it stored as bytes (which is what I'll need inside the Arduino) rather than store it as char (which seems the preferred datatype for serial communication??) and convert it to byte everytime I use the data inside the Arduino.

In terms of conversion..... sounds like I should avoid any conversion between Char and byte if I want to make sure all data from 0 to 255 arrives intact..

Back to the code:
I'm sending bytes down, I want to use the full range 0-255, but I use '255' as a start byte and '254' as a stop byte

I can capture the bytes using

a declaration:
byte InByte = 0;

and the function:
InByte = (Serial.read);

in a loop to fill up the array.

If I now change to:

define an array
byte InByte[64]

and I want to fill using the function Serial.readBytesUntil
how do I do it? Like this:

Serial.readBytesUntil(254,(char *)InByte,64);

Thanks again!

sounds like I should avoid any conversion between Char and byte if I want to make sure all data from 0 to 255 arrives intact..

The Serial.read() method, called in the readBytes() method actually returns ints. The readBytes() method makes sure that there is data to read, so it knows that it is safe to discard the high order byte. So, it is only concerned with bytes. The range of values that a byte can store is 0 to 255.

A character, being the same size, but signed, can store values in the range -128 to 127. There are no ASCII codes for -128 to -1. So, the only values that the serial port will receive are in the range o to 255. Some of them will fit in char variables/arrays. Some will not.

Whether you need to do any conversion depends on what kind of data you are sending to the Arduino. Is it binary (bytes) or text (chars)?

If it's chars, what are you doing with them later that needs bytes? Enough tap dancing, already.

:smiley:

I"m storing 'state' descriptions of a system of LEDs - for the moment 24 RGB LEDs, each with a 1 byte value of intensity so I'm looking to store arrays of 23x3=69 bytes

The idea is to be able to do quick changes between states: I'd like to store a couple of 69 byte arrays stored on the Arduino, and switch between them with just sending one command to the Arduino.

I'd like both transmission over serial and storage on the Arduino to be as efficient as possible so even though it might be much easier to send ascii characters I'd rather send the value '250' as one byte rather than '2' '5' '0'

I'm sending from Max/MSP - I'm not 100% sure how it sends the values. But when I send one value '254' and read it with serial.Read into an integer it arrives as one '250'. So I suppose that means it's sending binary and not chars?

So I suppose that means it's sending binary and not chars?

Yes, it does.

Excellent - so would you know what I need to do to use the lovely
format of:

Serial.readBytesUntil(254, Array_Name,64);

but where Array_Name is an array of Bytes, not of Char's ?

thanks for all your help!

The readBytesUntil() method expects the 2nd argument to be an array of chars. If you want to use an array of bytes, instead of an array of chars, you can use a cast:

byte goodStuff[64];

Serial.readBytesUntil(254, (char *)goodStuff, sizeof(goodStuff));

Fantastic - my problem is solved, and my sketch is working. Thanks so much!