Go Down

Topic: Can't send integers correctly over Serial (Read 30338 times) previous topic - next topic

Electricaero87

Hello All,

Okay I'm trying to send some integers between two Arduino's of mine. At the moment I'm trying to send 300 from to the other. I know that on the other end I have to do two separate Serial.read()'s since two bytes are being send over. I should read them as 1 and 44 but instead I get 224 and 134. Here is the code I am using :

To Send
Code: [Select]


void setup()
{
 Serial.begin(9600);
}

void loop()
{
 int s;
 s=300;
 Serial.write(s);
 delay(1000);
}


To Receive
Code: [Select]

void setup()
{
 Serial.begin(9600);
}

void loop()
{  
 int r;
 int r2;
   while(Serial.available()<2)
 {
   //do nothing
 }
 r=Serial.read();
 r2=Serial.read();
 Serial.println(r);
 Serial.println(r2);
 delay(1000);
 Serial.flush();
}



I know that the serial sends numbers as ASCII's but I can't seem to get the atoi() function to work. I'm also not sure if I need to implement this in both codes.

If anyone can help me get this working I would greatly appreciate it!! Thank you!

pluggy

#1
Aug 15, 2010, 07:41 am Last Edit: Aug 15, 2010, 07:43 am by stephen_t Reason: 1
Don't send it as an integer, break it down in code to a high order byte and a low order byte, send and receive it as two seperate bytes and then reassemble it at the far end.

A snippit of code from one of my sketches, the purists will advocate bit mangling but this is easier to understand.
livedata is an array of type  byte, lite is an integer.

Code: [Select]

livedata[6] = lite / 256;
livedata[7] = lite % 256;  


at the other end :

Code: [Select]
rxlite = livedata[6] * 256 + livedata[7];

Electricaero87

First off thanks pluggy! But I'm not quite sure how to implement what you gave me. Could you possibly explain it a little bit more detail? I'm still new to whole coding scene. I understand what livedata[6], livedata[7] and rxlite do. But I'm not sure how to use livedata. Any suggestions would helpful. Thank you again!!!

PaulS

On the sender, you need to break the 16 bit int into 2 8 bit bytes, and send each byte. Pluggy's code shows how to do that, where the resulting bytes are stored in an array.

Just change that to write them, instead:
Code: [Select]
Serial.write(s / 256);
Serial.write(s % 256);


On the receiver, you need to read 2 bytes, and combine them in an int.
Code: [Select]
byte b1 = Serial.read();
byte b2 = Serial.read();

int val = b1 * 256 + b2;

mpeuser

Serial.write(&s, 2);   //will also do the trick

Electricaero87

Okay, I tried putting that in my code but b1 and b2 were be being read as 6 and 224 respectively (in DEC form). They should be 1(00000001) and 44 (00101100). Although I would like to say thanks to PaulS and pluggy I just realized what dividing and finding the remainder do! It breaks it up into the two individual bytes that when combined make the whole number (i.e. 300 or 00000001 00101100).

I also tried the Serial.write($s,2); but I got an error saying that there was no function supporting Serial.write(*int, int). So do I need a special library or something? Anyway here is the modified code, I'm not sure what is going wrong in the Serial Port. Any ideas???

Send:
Code: [Select]
void setup()
{
 Serial.begin(9600);
}

void loop()
{
 int s;
 s=300;
 Serial.write(s/256);
 Serial.write(s%256);
 delay(1000);
}


Receive:
Code: [Select]
void setup()
{
 Serial.begin(9600);
}

void loop()
{  
 while(Serial.available()<2)
 {
   //do nothing
 }
 int rec;
 byte b1=Serial.read();
 byte b2=Serial.read();
 rec=b1*256+b2;
 Serial.println(b1, DEC);
 Serial.println(b2, DEC);
 Serial.println(rec);
 delay(1000);
 Serial.flush();
}


pluggy

#6
Aug 15, 2010, 06:21 pm Last Edit: Aug 15, 2010, 06:33 pm by stephen_t Reason: 1
I'd take the delay out of the receiving end, you have the main loop waiting with the while loop until it gets two bytes so it will only continue once a second.  The delay and the serial flush could be data destructive with the wrong timing between the two boards.

You're likely to have problems with the receiving board, if you're using the same interface to read from the other board and using it with the serial monitor at the same time.  

Electricaero87

Hey pluggy, do you have any idea why I could be receiving the bytes incorrectly? I know they are being sent correctly, but they keep coming out wrong.

robtillaart

#8
Aug 15, 2010, 07:02 pm Last Edit: Aug 15, 2010, 07:02 pm by robtillaart Reason: 1
Your serial port may be broken. If you send single char's over the serial line (abc etc) do they receive correctly?

I would add casting to the code to make the type of the parameter explicit.
// sending site
Serial.write((byte) s / 256);
Serial.write((byte) s % 256);

// receiving site
int rec;
byte b1  = Serial.Read();
byte b2 =  Serial.Read();
rec = ((int)b1) * 256 + b2;

// or use the receiving int immediatelly
int rec = Serial.Read() * 256 + Serial.Read();
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

AWOL

Code: [Select]
// receiving site
int rec;
byte b1  = Serial.Read();
byte b2 =  Serial.Read();
rec = ((int)b1) * 256 + b2;

Best to make sure you've got (at least) two bytes available before you read them.

Electricaero87

Hmmm...interesting, apparently the Serial Port on my Arduino Duemianove isn't working right. I hooked up my other Arduino (a mega) to my Razor IMU 9DoF (which is why I'm trying to send data Serially; so I can send the readings from my Razor to my mega) and it seems to send one byte numbers just fine. However when I try to send a byte number it gets a little messed up.

It receives b1 as 1 and b2 as 13 (this should be 44). Looking at the bit pattern they are similar (13 = 00001101 and 44 = 00101100)  :-?. So I'm not sure what could be causing this, I'll try messing around with it. If anyone knows why this could be happening please let me know! Thanks for the help!!

Electricaero87

Okay, I got it too work!!!!!!!!! Finally :D. I was able to fix the incorrect bits being received but then they switched order every time (i.e. b1=2, b2=44, and then b1=44 and b2=1). So I just did a couple of if statements to take of this. So here is the receiving code:

Code: [Select]
void setup()
{
 Serial.begin(9600);
}

void loop()
{  
 while(Serial.available()<2)
 {
   //do nothing
 }
 int rec;
 byte b1=Serial.read();
 byte b2=Serial.read();
 if(b2>b1)
 {
   rec=((int)b1)*256+b2;
   Serial.println(b1, DEC);
   Serial.println(b2, DEC);
   Serial.println(rec);
   //delay(1000);
   Serial.flush();
 }
 if(b1>b2)
 {
   rec=((int)b2)*256+b1;
   Serial.println(b1, DEC);
   Serial.println(b2, DEC);
   Serial.println(rec);
   //delay(1000);
   Serial.flush();
 }
}


Any comments or improvements to my code are welcomed. Now I'm going to try to send long int's through to see how it works, hopefully it will. Thank you so much to everyone for your help and suggestions. I REALLY appreciate it!!! More to come later.


PaulS

Quote
So I just did a couple of if statements to take of this.

This is a really, really bad idea. If you are sending two bytes, high order byte and low order byte, and one gets lost, you can't just tack the next byte onto the end of the previous one, swapping things around if the result doesn't look right.

You really need to re-think this idea.

As you try sending longs, things will only get worse.

zoomkat

How are the integers developed? Perhaps transfering the integers as ascii characters then reconverting when ready for use might be easier.
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

Go Up