How to send and receive struct data packet over serial

It is absolutely not. I'm not sure why you quoted “the standard”, C and C++ have internationally agreed upon ISO standards. They specify exactly what is a valid C or C++ program and what is not, and they specify how compilers should interpret your source code. Of course GCC is aware of the standard.

I have a hard time believing that. I've shown you multiple real-world scenarios where GCC actually produces invalid code because of such violations.

You seem to misunderstand the definition of Undefined Behavior: It doesn't just mean that the behavior is not defined by the standard (that would be unspecified or implementation-defined behavior), undefined behavior means that your compiler isn't required to produce any useful output, and the generated code could do anything.
You absolutely do not want this in your code. You can do everything else right, have correctness proofs for every algorithm in your code base, have all your unit tests pass, if you invoke undefined behavior in your code, all bets are off and the entire program is fundamentally broken.

If you don't care about any of that, that's your decision, but please don't teach these practices to others.

Can someone give me example code for both transmitter and receiver for Arduino board to board UART communication? I tried different different methods but I couldn't find a solution.

Make sure that the baud rate is correct and that you've connected the two Arduinos correctly (TX to RX and RX to TX, using the Serial1 pins).

Hardware side is correct. Also I can send array via UART. But the only part that doesn't work is sending struct via UART.

there was some code in the thread, read above..

1 Like

Can you specify in what form (an array of integers or something else) do you store data about 32 relay states in the transmitter?
In what type of data do you need them in the receiver in the end (before sending to the pins)?

struct Packet
    int arr[];
   int sizeArr;


this is the data struct I want to transmit and receive

I doubt that the library supports flexible array members. And shouldn't the flexible member be at the end?

It could work fine. Might just be transferring an array of size 0.

Of course, the size of the data must be the first member.

What is the source of the data that you want to transmit ?

It's hard to understand you. Obviously, you don't really want help. No one should write code for you.
Do you need to pass data or do you need a structure?
Before sending, you can transform your structure into any convenient form, transfer, receive, and then return it back to your structure.
Actually, the data about the state of 32 relays can be packed into one integer number, transfer only one number, and then return it back to the array. Simple and fast.

the code i've posted compiles and works (i.e. tested). i don't believe it is bad practice.

i can't say i disagree with you, because i don't understand the point you're trying to make.

He's saying: it may work today, but:

  • It may not work when the next version of the compiler comes out.

  • It may not work if you make a seemingly minor and unrelated change in the code.

  • It may not work if you change the compiler's optimization parameters.

Why? Because the language standard does not say that it must work. Therefore, the object code that the compiler creates with your invalid source code is not required to work to your expectations or, in fact, do anything at all.

Why do you find that so difficult to understand?

you're describing what undefined behavior means. i'm not advocating ignoring it.

i'm describing a very specific case with very restricted use of the pointer value i don't believe casting is undefined, but how the use of the re-casted pointer value is undefined. of course it is. the compiler doesn't know how the code will use it. but it can be used properly.

based on my experience, recasting pointers in this way is fairly conventional.

btw: has anyone provided an alternative version of the code i presented reply #7? it doesn't matter that the code is incomplete, it demonstrates the use of casting to match the processing function interfaces.

It allows you to utilize the same fixed memory locations for different purposes. Memory utilization was more important in the days of 4k * 12 bit total RAM.

I'm transmitting relay ids (Pin numbers connected to Arduino mega). The relays are switching according to the relay array IDs)

It is very difficult to get information from you.
In the first post, you wrote that you need to transfer data between two ESP32s to control 32 relays. I may be wrong, but it seems to me that the ESP32 does not have 32 pins for output.
Now you write that you need to transfer the pin numbers for the Arduino Mega.

  • How many numbers do you need to transfer? Is it always 32 or could it be a different number? Are these numbers in the range 0 to 31, or could there be a different range?
  • Are these numbers in order, or can be an arbitrary order?
  • Do you always need to transmit all 32 numbers, or is it enough to transmit one pin number that needs to be changed at a given time?

This means that you must create a protocol for transferring data. It should be simple and trasmit the minimum required information.
It's strange why you don't want to use the approach from Example 5 of Serial Input Basics - updated?

despite the discussion of more advanced data formats ...

why don't you just send a string with pairs of #s indicating relay-id and state that can be separated using strtok().
"relays 1:0, 2:1, 3:1, ..."

along the lines of what you originally suggested, you could send a binary packet. the code below produced the following output

   03 01 00 02 01 03 01 00
   00 00 00 00 00 00 00 00
   00 00 00 00 00
#include    <stdio.h>

typedef unsigned char   byte;

#define MAX_RELAY   10

struct Pkt_s {
    byte     size;
    struct RelayIdState {
        byte    id;
        byte    state;
    } idState [MAX_RELAY];

void dump (
    byte   *buf,
    int     nByte )
    printf ("%s:", __func__);

    for (unsigned n = 0; n < nByte; n++)  {
        if (! (n % 8))
            printf ("\n  ");
        printf (" %02x", buf [n]);
    printf ("\n");

main ()
    Pkt_s  pkt = {};

    pkt.idState [0].id    = 1;
    pkt.idState [0].state = 0;

    pkt.idState [1].id    = 2;
    pkt.idState [1].state = 1;

    pkt.idState [2].id    = 3;
    pkt.idState [2].state = 1;

    pkt.size              = 3;

    dump ((byte*) &pkt, sizeof(pkt));
    return 0;
1 Like

Thank you for your replies. The problem was solved by using serial stream char buffer.