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!
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
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
}
}
[/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;
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?
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.
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.