Reading long int from serial

I'm trying to send ints ranging from one to four digits long from one arduino to another via the serial connection.

I can send the ints from one arduino using Serial.println but reassembling them at the other end is proving hard as Serial.read only reads one digit at a time.
Is there some quick and simple way to put the individual digits that come out at the receiving serial end back together again?
I was imagining it would be best to take each digit, put it in a variable and multiply it by ten before adding the next digit that comes through and so on only to end the process once a new line was detected (so I assume look for "\n") but how i'd make that work is definitely beyond me at the moment!

Any help much appreciated

Seeing your programs would help considerably as without them we are working in the dark. How exactly are you sending the ints, for example ?

My sending code is simply the below.

int x = 100;
int y = 200;
// ########################################################initialize
void setup() {
Serial.begin(9600);
}
 
//######################################################## program loop
void loop()
{
Serial.println(x);
delay(5000);
Serial.println(y);
delay(5000);
}

However this is just to experiment with; on the other end I want to basically reassemble the ints that get send over serial so they can be turned into ints for a delay function for the blink example.

On the receiver arduino I've tried to put together the below code but it doesn't seem to be working :frowning:

const int ledPin = 13; // pin number of the LED
int x = 500;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Serial.setTimeout(10);
}
 

void loop()
{
  while(Serial.available()==0){
  digitalWrite(ledPin,HIGH); 
  delay(x);
  digitalWrite(ledPin,LOW); 
  delay(x);
  }
  
  x = Serial.parseInt();
 
  Serial.println(x);
}

The problem with that code is that as soon as the first byte is available you go straight to reading. Serial data arrives very slowly. You had the right idea in the first post. Just hold a variable and with each arriving digit multiply by ten and and the new digit.

//Somewhere at global scope:
int myNumber = 0;


//Somewhere in loop:

if(Serial.available){
   char c = Serial.read();
   if(c == '\n'){
      // Number is complete, go do whatever you want with it.
   }
   else {
      myNumber = myNumber * 10;
      myNumber = myNumber + (c - '0');  // Subtract '0' to adjust from ascii back to real numbers
   }
}

Instead of sending the number as characters, and then receive characters and convert back to a number… why not just send and receive a number ?

Send:

int x = 100;
Serial.write( (uint8_t *) &x, sizeof( x ) );

Receive:

int x = Serial.read() | ( Serial.read() << 8 );

[quote author=guix link=msg=2382930
Receive:

int x = Serial.read() | ( Serial.read() << 8 );

[/quote]
The calls to Serial.read() are made in an implementation-defined order. The first or the second may be done first. It’s better to call it twice in two separate statements and then combine the two values together. It will be as fast as a single statement and will also work as expected.

There is a lovely way to ship any data type over serial without taking it apart or reassembling it. Here’s an example for sending 4 floats
.

Define a structure called a union, as follows

union
{
byte buf[16];
float val[4];
}FloatToChar;

This is actually one array of 16 bytes which can be interpreted either as floats or characters. So to send four floats over a serial link, do the following;

FloatToChar.val[0] = float1;
FloatToChar.val[1] = float2;
FloatToChar.val[3] = float3;
FloatToChar.val[3] = float4;

serial.write(FloatToChar.buf, 16);

That sends the 16 bytes to the receiver, which using an identically defined union, proceeds as follows

if (serial.available() >= 16)
for{i = 0; i < 16; i++)
{
c = serial.read();
FloatToChar.buf = c;
}
float1 = FloatToChar.val[1], etc.
Make life very simple, eh?

jrdoner:
Make life very simple, eh?

Without [code][/code] tags, it makes life very difficult.

The examples in Serial Input Basics
may be useful whether you are sending the data as binary or ascii values. There is also a parse example to show how to convert ascii data to numbers.

Personally I like the idea of using a Union as @jrdoner has suggested. But sending ascii data makes the debugging much easier.

...R

No need for a union, especially one with hardcoded sizes. Just cast your array of floats to a pointer to byte:

Serial.write((const byte *)float_array, sizeof float_array);

Couldn't be much easier than that.

Interesting. The OP says:

I’m trying to send ints…

but we’re talking about sending floats. Why not just send them in a packet, with something that marks the end of a packet. For example, if the packet marker is ‘@’, then, if you want to send the values 1, 23, 456, 7890 to the other board, something like:

   char buff[10];
   int values[] = {1, 23, 456, 7890};
   int i;

   for (i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
      itoa(values[i], buff, 10);     // convert to ASCII
      strcat(buff, '@');             // Add the packet marker...
      Serial.print(buff);
      while (Serial.available() == 0)        // Wait for acknowledgement...
         ;
   }

Then on the other end, something like:

char msg[10];
int charsRead;

if (Serial1.available() > 0) {
   charsRead = Serial1.readBytesUntil('@', msg, sizeof(msg) - 1);  // Look for packet marker...
   msg[charsRead] = '\0';     // Now it's a string

   valuesToUse[index++] = atoi(msg);  // store it in an array or "consume" it
   Serial1.print("ACK");         // Tell the other board you got it.
}

I can try this, but something like this should work.