Do you want to transmit binairy data ? Then you might need some kind of protocol. You need to know which 4 bytes belong to the same 'float' variable. I prefer a start byte, a stop byte, and maybe a checksum.
You could transmit it as readable text. Then you still need to describe the protocol.
For example: readable ascii, two float numbers, comma seperated (no space), and a carriage return with linefeed at the end, with a timeout of 100ms.
Then you can use Serial.print() to send the 'float' variables and Serial.parseFloat() with Serial.setTimeout() to receive it.
The Serial.parseFloat() is blocking and is far from ideal.
I do agree that it would be easier using PRINT - it's probably how I would do it for myself. However if you use PRINT you must be careful to preserve all the decimals within the float. Using WRITE does that automatically.
If OP is to use write() method, then the directive of your Post#3 is an approach on which the following Solution-2 is based upon. Solution-2: MEGA Sender Codes: using SUART.write() method
#include<SoftwareSerial.h>
SoftwareSerial SUART(10, 11);//DPin-10 = SRX; DPin-11 = STX
float data[2] = {1.1, 0.5};
void setup()
{
Serial.begin(9600); //bit transfer rate (Bd) between PC and UNO
SUART.begin(9600); //Bd (Baud Rate) between UNO and NANO
}
void loop()
{
byte *ptr = (byte*)&data; //pointer will increase by 1-byte position
for (byte i = 0; i < 8; i++, ptr++)
{
byte m = *ptr;
if (m < 0x10)
{
Serial.print('0'); //for debugging
}
Serial.print(m, HEX);
SUART.write(*ptr);
}
Serial.println();
Serial.println("==================");
delay(1000);
}
NANO Receiver Codes:
#include <SoftwareSerial.h>
SoftwareSerial SUART(10, 11); //RX, TX,
byte rxData[10];
union
{
float x;
byte myData[4];
} data[2];
void setup()
{
Serial.begin(9600);
SUART.begin(9600);
}
void loop()
{
byte m = SUART.readBytes(rxData, 8); //built-in code: if(SUART.available()>0)
//--converting binary32 formatted bytes into float using union---
for (byte i = 0; i < 4; i++)
{
data[0].myData[i] = rxData[i];
}
Serial.println(data[0].x, 1);
//-------------------------------------
for (byte i = 4, j=0; i < 8, j<4; i++, j++)
{
data[1].myData[j] = rxData[i];
}
Serial.println(data[1].x, 1);
Serial.println("=======================");
}
Robin2: SUART.write(*ptr) should have the number of bytes to be written as well as the address of the buffer.
That is sending a byte. Just a byte, no pointer.
My main concern is still the synchronization of the data. I think it can only be solved by creating a package of data. So there must be some way to synchronize in the case that only partial data was received.
Koepel:
My main concern is still the synchronization of the data.
I thought of that also - my code in Serial Input Basics uses start- and end-markers but as written it can't deal with all of the possible byte values, and building a system that can send all the byte values between start and end markers is probably a little too complex for the OP at present.
In the case of the OP's question I think there is sufficient time between each message to avoid any synchronization concerns so I did not bother to address the issue.
should have the number of bytes to be written as well as the address of the buffer.
Koepel:
That is sending a byte. Just a byte, no pointer.
A little bit -- 1. In response to this declaration: float data[2 = {1.1, 0.5};, the compiler creates the following 8-byte wide memory space (array) to hold the binary32 formatted bytes for the given float numbers.

Figure-1:
**2.** The value of the 1st byte (content of memory location m0) of Fig-1 can be known by executing the following codes:
**(1)** Get the address of the 1st location of the array of Fig-1 into pointer variable (ptr) and then read the value and then transmit it.
byte ptr = (byte) &data; //we want to increment the pointer variable by 1-bye position
byte x = *ptr; //x receives the content of location m0, which is CD
SUART.write(x); // SUART.write(*ptr); value is being transmitted over soft serial port
ptr++; //now pointer variable is pointing to location m1
x = *ptr; //x hold CC = the content of location m1 of Fig-1
SUART.write(x);
..............
Using for() loop, we have:
byte ptr = (byte)&data; //get base address of array of Fig-1; ptr gets incremented by 1-byte
for(byte i=0; i<8; i++, ptr++)
{
byte x = *ptr;
SUART.write(x); //or SUART.write(*ptr)
}
Koepel:
My main concern is still the synchronization of the data. I think it can only be solved by creating a package of data. So there must be some way to synchronize in the case that only partial data was received.
Synchronization should be there to maintain data transmission/reception quality, and it can be established by sending a preamble code (say: 0x1234) and a checksum to be computed from the preamble and the data bytes.
After one or two frames, the communication link will enter into synchronization (it happens practically) and will remain locked.
MEGA(sender) codes:
#include<SoftwareSerial.h>
SoftwareSerial SUART(10, 11);//DPin-10 = SRX; DPin-11 = STX
float data[2] = {1.1, 0.5};
byte CHKSUM = 0;
void setup()
{
Serial.begin(9600); //bit transfer rate (Bd) between PC and UNO
SUART.begin(9600); //Bd (Baud Rate) between UNO and NANO
}
void loop()
{
SUART.write(0x12); //sync pattern
SUART.write(0x34);
byte *ptr = (byte*)&data;
for (byte i = 0; i < 8; i++, ptr++)
{
byte m = *ptr;
if (m < 0x10)
{
Serial.print('0');
}
Serial.print(m, HEX);
SUART.write(m);
CHKSUM += m;
}
CHKSUM = CHKSUM + 0x12 + 0x34;
SUART.write(CHKSUM);
Serial.println();
Serial.print("CHKSUM: "); Serial.println(CHKSUM, HEX);
CHKSUM = 0;
Serial.println("==================");
delay(1000);
}
NANO (receiver) codes:
#include <SoftwareSerial.h>
SoftwareSerial SUART(10, 11); //RX, TX,
byte rxData[9];
byte syncData[2];
bool flag = false;
byte CHKSUM = 0;
union
{
float x;
byte myData[4];
} data[2];
void setup()
{
Serial.begin(9600);
SUART.begin(9600);
}
void loop()
{
byte n = SUART.available();
if ( n != 0)
{
byte x = SUART.read();
if (flag == false)
{
if ( x == 0x12)
{
syncData[0] = x;
flag = true;
CHKSUM += x;
}
}
else
{
if (x == 0x34)
{
syncData[1];
recvFrame();
CHKSUM += x;
flag = false;
}
}
}
}
void recvFrame()
{
byte m = SUART.readBytes(rxData, 9);
//--converting binary32 formatted bytes into float using union---
for (byte i = 0; i < 4; i++)
{
data[0].myData[i] = rxData[i];
CHKSUM += rxData[i];
}
//Serial.println(data[0].x, 1);
//-------------------------------------
for (byte i = 4, j = 0; i < 8, j < 4; i++, j++)
{
data[1].myData[j] = rxData[i];
CHKSUM += rxData[i];
}
if (CHKSUM == rxData[8])
{
Serial.println("Received frame is OK.");
Serial.println(data[0].x, 1);
Serial.println(data[1].x, 1);
CHKSUM = 0;
Serial.println("=======================");
}
else
{
Serial.println("Transmission Error...!");
CHKSUM = 0;
}
}
Robin2:
Can't you just omit the FOR loop and define the number of bytes in the call to write() ?
Then, how to increment the pointer to point the next location of the data array of Fig-1 of Post#11?
Since write() method deals with byte wise data, we need a pointer for successive accessions to the byte locations of the data array; where, the pointer is to be incremented after each access.
Robin2:
Why would you need to. All it needs is the starting address of the buffer and the number of bytes.
You are right (+) -- the following code (based on the above directive) works.
SUART.write((byte*)&data, sizeof data);
Anyway -- my understanding is this: the above single line code has to be broken down (in the background) to the following equivalent codes in order to access the locations of the buffer as the write() method handles byte wise data.
byte *ptr = (byte*)&x; //passing the base address of the buffer to a pointer variable
for (byte i=0; i<8; i++, ptr++)
{
SUART.write(*ptr);
}
GolamMostafa:
Anyway -- my understanding is this: the above single line code has to be broken down (in the background) to the following equivalent codes in order to access the locations of the buffer as the write() method handles byte wise data.
Yes. Some other guy wrote those lines of code (or similar) to save you the trouble.