Reputation: 99
I have this code from a slave device
byte buf[] = {125, 126, 127, 2000, 5000};
void setup() {
// initialize serial:
Serial.begin(9600);
}
void loop() {
int i = Serial.write(buf, sizeof(buf));
Serial.println(i);
delay(5000);
}
and I have this code from a listening device.
char protocol[5];
void setup() {
Serial.begin(9600);
memset(protocol, '\0', sizeof(protocol));
}
void loop() {
if(Serial.available()) {
Serial.readBytes(protocol, 5);
Serial.println(protocol);
for(int i = 0; i < sizeof(protocol); i ++ ) {
Serial.println((int)protocol[i], BIN);
}
}
else{
Serial.println("None available");
delay(500);
}
}
I understand that Arduino uses 2's compliment, however the problem I am getting is that the print out is this
1111101
1111110
1111111
11111111111111111111111111010000
11111111111111111111111110001000
and because of the 2's complement, all zeros are being added to finish the char because the left most bit read in as a 1. Anyways, the 4th and 5th numbers are not 2000 and 5000 but numbers much different than that. How do I get the the appended 1's to go away so I read 2000 and 5000? thanks
Upvotes: 0
Views: 522
Reputation: 4435
The issue here is that you are storing and transmitting each number as an 8-bit value, which is not large enough to store the numbers 2000 or 5000.
To fix this, you'll want to change the types of your buffer arrays to int[
]. Here's how:
In the slave, you'll need to change the line where you declare your buffer:
int buf[] = {125, 126, 127, 2000, 5000};
And now that the type is different, you'll have to add a type cast, since Serial.write
expects a char
or byte
array.
int i = Serial.write((char *) buf, sizeof(buf));
Then, you'll have to make similar changes in the listener device. Declare your protocol
array like so:
int protocol[5];
Then, Serial.readBytes
also expects a byte array, so you'll need another cast (and sizeof
to get the correct number of bytes to read):
Serial.readBytes((byte *) protocol, sizeof(protocol));
Edit: To explain how the (char *)
cast in the slave works and why it's necessary, remember that this is C++, so (like in C) an array is pretty much a pointer internally. So, when you create the array of five int
s, what's really going on is you've reserved 10 bytes of memory (enough for five 16-bit int
s) and received a pointer to the start of it. Now, unless told otherwise, C++ will treat that memory like it's five int
s. However, it's perfectly happy to treat it as 10 char
s if you tell it to. This is pretty convenient, since Serial.write
will only take an array of char
s (which, as you recall, is like a char
pointer, hence char *
). And this will work fine, since it'll send the 10 bytes across the line as char
s, where the listener will put the same 10 bytes into the protocol
array. Then, with an exact copy of the 10-byte block of memory, the protocol
array will have the same int
s as the buf
array did in the slave.
One last comment: You may want to have your listener wait until there are actually sizeof(protocol)
bytes available before trying to read. Otherwise, if only part of the data is ready, it will go ahead and try to read, but Serial.readBytes
usually only waits a short time for the remaining data before giving up and leaving the buffer unfilled. You would fix that by adding >= sizeof(protocol)
to the appropriate line:
if(Serial.available() >= sizeof(protocol)) {
Upvotes: 1