I'm trying to serially read in a 4 byte integer with the following code. However, the value is not what I expect, and I'm wondering if there is a byte order issue. I'm expecting a number in the range of 0 to 1000, but I'm ending up with an enormous negative number.
Will this code work properly to read in a 4 byte integer that is being sent high byte first?
void GetLong(long* Value)
{
Serial->readBytes((char*)Value, 4);
}
Check for yourself= ...
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <limits.h>
#define lowByte(w) ((uint8_t)((w) & 0xff))
#define highByte(w) ((uint8_t)((w) >> 8))
void loop()
{}
void setup()
{
Serial.begin(9600);
// --- IDENTIFY ENDIAN ORDERING
short number = 0x0001L;
Serial.println((1 == ((char*)&number)[sizeof(number) - 1]) ? "Big Endian\n" : "Little Endian\n");
Serial.print("Lo Byte '0xDEAD': \t"); Serial.println(lowByte(0xDEAD), HEX);
Serial.print("Hi Byte '0xDEAD': \t"); Serial.println(highByte(0xDEAD), HEX);
// --- REPORT SIZE AND RANGES OF DATA TYPES
Serial.println("\n\nReporting size, and range, of \'intrinc\' data types -");
Serial.print("\tbool: \t\t"); Serial.println(sizeof(bool));
Serial.print("\tbits per 'char': \t\t"); Serial.println(CHAR_BIT);
Serial.print("\tchar: \t\t"); Serial.println(sizeof(char));
Serial.print("\t'char' minimum: \t\t"); Serial.println(CHAR_MIN);
Serial.print("\t'char' maximum: \t\t"); Serial.println(CHAR_MAX);
Serial.print("\t'signed char' minimum: \t\t"); Serial.println(SCHAR_MIN);
Serial.print("\t'signed char' maximum: \t\t"); Serial.println(SCHAR_MAX);
Serial.print("\t'unsigned char' maximum: \t\t"); Serial.println(UCHAR_MAX);
Serial.print("\tshort: \t\t"); Serial.println(sizeof(short));
Serial.print("\t'signed short' minimum: \t\t"); Serial.println(SHRT_MIN);
Serial.print("\t'signed short' maximum: \t\t"); Serial.println(SHRT_MAX);
Serial.print("\t'unsigned short' maximum: \t\t"); Serial.println(USHRT_MAX);
Serial.print("\tint: \t\t"); Serial.println(sizeof(int));
Serial.print("\t'signed int' minimum: \t\t"); Serial.println(INT_MIN);
Serial.print("\t'signed int' maximum: \t\t"); Serial.println(INT_MAX);
Serial.print("\t'unsigned int' maximum: \t\t"); Serial.println(UINT_MAX);
Serial.print("\tlong: \t\t"); Serial.println(sizeof(long));
Serial.print("\t'signed long' minimum: \t\t"); Serial.println(LONG_MIN);
Serial.print("\t'signed long' maximum: \t\t"); Serial.println(LONG_MAX);
Serial.print("\t'unsigned long' maximum: \t\t"); Serial.println(ULONG_MAX);
Serial.print("\tlong long: \t"); Serial.println(sizeof(long long));
#if 0
Serial.print("\t'signed long long' minimum: \t\t"); Serial.println(LONG_LONG_MIN);
Serial.print("\t'signed long long' maximum: \t\t"); Serial.println(LONG_LONG_MAX);
Serial.print("\t'unsigned long long' maximum: \t\t"); Serial.println(ULONG_LONG_MAX);
#endif
Serial.print("\tfloat: \t\t"); Serial.println(sizeof(float));
Serial.print("\tdouble: \t"); Serial.println(sizeof(double));
Serial.print("\tPointer: \t"); Serial.println(sizeof(void*));
Serial.println("\n\nReporting size of some \'Wiring\' data types -");
Serial.print("\tbyte size: \t"); Serial.println(sizeof(byte));
Serial.print("\tword size: \t"); Serial.println(sizeof(word));
Serial.end();
}
The Arduino processors are little-endian so you'll have to reverse the byte order.
Pete
I have modified my code to the following. Do you think this should work? I'm asking because I'm still getting a huge number. Remember the 4-byte integer is being sent high-byte first.
int ReadLong(long* Value)
{
char Temp[4] = { 0, 0, 0, 0 };
size_t Count = 0;
Count = Serial->readBytes(&(Temp[3]), 1);
Count += Serial->readBytes(&(Temp[2]), 1);
Count += Serial->readBytes(&(Temp[1]), 1);
Count += Serial->readBytes(Temp, 1);
*Value = *((long*)Temp);
return Count;
}
Well, what does it do and what did you expect it to do?
What is Count when you are done?
Regardless of their order, are the four bytes sent the same as the four bytes received?
Thanks for your input. I have no objective way to know what the four bytes are that are being sent. My Arduino is the only way for me to read them and display them. They are coming from a motor controller that does not have an interface to talk directly to the PC.
I'm expecting a number < 1000 but the high bytes are always 0xE0E0, which is the problem.
At the end of the function Count == 4.
So my only question is, does my code look to you like it should reverse the bytes properly?
To read four bytes off Serial into a 32-bit integer, big end first:
long value;
value = 0;
for(int i = 0; i<4; i++) {
while(!Serial.available()); // poll input until we get a byte
value <<= 8; // shift 8 bits
value |= Serial.read(); // OR in one byte.
}
I have no objective way to know what the four bytes are that are being sent.
I don't understand this at all.
How can you expect to receive a number < 1000 if you don't know what bytes are being sent?
Print the bytes out one by one in hex, as they are received. That way at least you know what is coming in. Maybe only two of them carry useful data.
richsolomon:
I'm trying to serially read in a 4 byte integer with the following code. However, the value is not what I expect, and I'm wondering if there is a byte order issue. I'm expecting a number in the range of 0 to 1000, but I'm ending up with an enormous negative number.
Will this code work properly to read in a 4 byte integer that is being sent high byte first?
void GetLong(long* Value)
{
Serial->readBytes((char*)Value, 4);
}
Take closer look at readBytes. It reads 8 bits (character / byte) from incoming serial data , using optional number of characters / bytes (?), into a (8 bit ) buffer.
You are receiving an (32 bits ?) integer - not four individual (ASCII) characters / bytes.
BTW the function description does not distinguish between serial / ASCII characters and plain bytes very well.
Assuming one or the other would not be an option IMHO.
So after readBytes is done your first character / byte received will be in Value[0] and so on.
The function should work but as jremington suggests, while you are testing things, print out all four bytes in the order they are received and follow that with the result from your ReadLong function.
Pete