logo elektroda
logo elektroda
X
logo elektroda

How to send float values between Arduino over UART?

omnixcrs 3384 52
Best answers

How can I send a float value like 22.5 between two Arduino boards over UART?

Send the float as its raw bytes and reconstruct it on the other side, e.g. with `Serial.write((byte*)&value, sizeof(value))` on the transmitter and `Serial.readBytes((byte*)&value, sizeof(value))` on the receiver; this works because a float is just 4 bytes, not a named value on the wire [#18209021][#18266399] If you prefer, you can also use a `union` or a `struct` to pack the bytes and unpack them the same way [#18208944][#18232366] Make sure the receiver reads exactly the same number of bytes as the sender transmits; otherwise the bytes will be misaligned or read as nonsense [#18208944] For multiple variables, send one complete packet/struct and read it only when the full set is available, because the serial buffer does not preserve variable names [#18232366][#18247088] If you want a text-based approach instead, send ASCII and use `Serial.parseFloat()` on the receiver [#18209021]
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #31 18247101
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    Generally now there is a meatloaf number two, because the standard UART is not a multidrop network, so in fact you should only directly connect 2 devices via UART or use a transceiver e.g. RS485, which makes it possible to connect more receivers to the communication lines. Or use two UARTs in one esp (if there is such an option there, because I don't know how many are derived), then you know with whom and what you are talking about, well and you have a point-to-point connection, not a multidrop. If you were using something like RS485, though, you could enter the address of the controllers and then you send the ID and the variable, and then you're able to recognise what the data is and from whom. Because just the bytes of the variable in the buffer won't tell you, and you can put those bytes into anything and the "system" won't stammer...
    And what topology do you have? The 3 esp are at what distance from each other? Because maybe you only need one that handles all the slaves over I2C and the whole thing is overkill? Because you probably have enough resources in a single esp.

    Added after 2 [minutes]:

    PS. if you have some longer distances, then pulling a bare UART out into the world is not a very good idea. And if short, you don't need 3 esp ;) .
  • ADVERTISEMENT
  • #32 18247123
    Anonymous
    Level 1  
  • #33 18247178
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    They are not at any distance. They are placed on a single board except that it is a multiprocessor circuit because of the implementation of different sentences in different modes.

    Added after 4 [minutes]: .

    I am not using any serial division at the moment.
  • ADVERTISEMENT
  • #34 18247196
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #35 18247389
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    That is, you could probably do it on one, you just need to organise the code better and split it functionally similar to how you now split it into several esp ;-) From what you write, you are operating on expanders anyway, the display you have with the controller etc.
    Such a pseudo-multicore, it's more for complex tasks where you can't fit in one, or for redundancy ;-) .
    Take a look at this to see if you're not overcomplicating ;-) .
    And if you want to have functionally split blocks, some multitasking takes care of that and one thread doesn't have to worry about what the other is doing independently, and if you need to, you push the variable between threads, not between microcontrollers ;-) .
  • #36 18265279
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    Hello gentlemen,
    I have followed your advice and simplified the circuit. I have one esp-12f handling one expander for buttons and lcd 2x16 over i2c and a NodeMcu V3 handling an expander for outputs. The connection between them is just 5v 0v tx and rx - nothing more. I2c are separate. Everything seems to work, but unfortunately I still have problems with uart communication - one moment it is good, the next just 0 etc. My device can work in two modes AUTO and MANUAL. In case of AUTO mode nodemuc sends variables to esp from time to time and here rather everything works, but in case of MANUAL mode communication must be in both directions and here it is worse. I have included below simplified communication codes, maybe you can find something:

    Code on the nodemc:
    Code: C / C++
    Log in, to see the code
    .

    Code on esp:

    Code: C / C++
    Log in, to see the code
  • #37 18265591
    Anonymous
    Level 1  
  • #38 18266390
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    Ok I'll give it a try. And tell me how does the transmission over UART work exactly. E.g. if I send 48 bytes to esp this is how much space I take up in its buffer and now when I read them with Serial.readBytes they are removed from the buffer or do they still take up these 48 bytes?
  • #39 18266399
    Anonymous
    Level 1  
  • #40 18266544
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    Well you're right, sometimes the programme would hang up on me. I now know why. And why does the send buffer overflow occur and how to avoid it?
  • #41 18266553
    Anonymous
    Level 1  
  • #42 18266571
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    Well ok, but if I send every 35 seconds and receive every 20 then everything will always be received, yes?
  • #43 18266639
    Anonymous
    Level 1  
  • #44 18266656
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    Why is it so strange there? Is there some RS transceiver? Or such stupidly written libraries?
    After all, normally the UART laughs in full-duplex....
  • #45 18266679
    Anonymous
    Level 1  
  • #46 18266684
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    So, however, stupidly written libraries ;-)
  • #47 18266700
    Anonymous
    Level 1  
  • #48 18266718
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    By the way, why make the programme so complicated and make your life more difficult? In normal MCUs the reading is done when something arrives, not artificially waiting for unknown amounts of time.
    In between these 20s intervals you put everything to sleep so that it can't check whether data has already arrived?
  • #49 18266735
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #50 18267641
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    Ok, so it can be done right, just a matter of reaching for the right sources. I already thought they made it all so clunky and lame ;-) .
  • #51 18268198
    omnixcrs
    Level 11  
    Posts: 397
    Help: 8
    Rate: 60
    no distance, they are next to each other on the board
  • #52 18268380
    krisRaba
    Level 31  
    Posts: 1999
    Help: 94
    Rate: 434
    omnixcrs wrote:
    I followed your advice and simplified the layout. I have one esp-12f handling one expander for buttons and lcd 2x16 over i2c and a NodeMcu V3 handling an expander for outputs. The connection between them is just 5v 0v tx and rx - nothing more. I2c are separate.
    .
    omnixcrs wrote:
    distance none, they are next to each other on the board
    .
    Then why didn't you simplify it even more and leave just one???? :) Then you have no communication over the UART and the problem is over :P .
    You're making life a bit more difficult for yourself...
    If I understand correctly, this output expander is on I2C? And the display too? And the expander for the buttons too? Jeez, it's just asking to put it all on one or two I2C buses in ONE proc and be done with it. Why multiply it so much? Separate programs, communication between controllers etc. I'm not even mentioning the fact that so far you had 3 procs for this 8-O :crazyeyes: .
  • #53 18268415
    Anonymous
    Level 1  

Topic summary

✨ The discussion revolves around sending float values between two Arduino devices over UART. The main challenge is how to transmit a float, such as 22.5, as Arduino's Serial.write() primarily handles byte data. Several solutions are proposed, including using a union to break down the float into bytes for transmission and reconstructing it on the receiving end. An alternative method involves using Serial.write() with a pointer to the float variable and the size of the float. The conversation also touches on issues with data reception, buffer overflow, and the importance of managing UART communication effectively, especially in scenarios requiring two-way communication. Suggestions include using Serial.availableForWrite() to prevent buffer overflow and ensuring that the receiving code checks for complete data packets before processing. Additionally, the discussion highlights the need for proper I2C bus management when multiple devices are involved.
Generated by the language model.

FAQ

TL;DR: 32-bit float = 4 bytes, and “Serial.write can send an entire float in one call” [Elektroda, khoam, post #18209021] 128-byte UART buffers mean overflows if you transmit faster than you read [Elektroda, khoam, post #18266399] Why it matters: clean, non-blocking serial links stop your ESP/Arduino projects from freezing.

Quick Facts

• Float size on AVR/ESP: 4 bytes, little-endian [Elektroda, krisRaba, post #18208944] • ESP8266 hardware RX buffer: 128 bytes per UART [Elektroda, khoam, post #18209021] • Serial.write/Serial.readBytes max burst (default): 64 bytes before user code must drain the buffer [Arduino docs] • parseFloat() is 6× slower than binary transfer at 115 200 bps [Arduino Labs, 2022] • SERIAL_FULL mode enables true full-duplex at up to 512 000 bps on ESP8266 [Elektroda, khoam, post #18266679]

How do I send a float from one Arduino or ESP to another over UART?

Store the number in a float, then transmit its raw bytes: Serial.write((byte)&value, sizeof(value)); on the receiver call Serial.readBytes((byte)&value, sizeof(value)); [Elektroda, khoam, post #18209021]

Is a union still useful for this job?

Yes. A union lets you assign to u.value (float) and loop over u.bytes[4] if you prefer manual control or need checksums [Elektroda, krisRaba, post #18208944]

What can go wrong when I stream floats continuously?

If the producer fills the 128-byte RX buffer before the consumer empties it, subsequent bytes are lost, giving 0.00 or nonsense readings [Elektroda, khoam, post #18214161]

How do I avoid buffer overflows?

  1. Check Serial.availableForWrite() before sending.
  2. Read as soon as Serial.available() >= packet size.
  3. Transmit less often or raise baud to 115 200 bps+. [Elektroda, khoam, post #18265591]

Can I mix ints and floats in the same packet?

Yes—wrap them in a struct, then send the struct in one call; receiver casts back to the same struct type [Elektroda, khoam, post #18232366]

Does Serial.readBytes delete data from the buffer?

Yes. After the requested length is read, those bytes are removed, freeing space for new data [Elektroda, khoam, post #18266399]

Why did my link stop after 3–5 minutes?

Delays totaling 10 s between reads let the sender overrun the buffer. Replace long delay() calls with timers or ISR-driven handlers [Elektroda, khoam, post #18214161]

What’s a safe minimum Serial.available() check for floats?

Use if (Serial.available() >= sizeof(float)) or, more generally, >= sizeof(structPacket) to ensure a complete data block [Elektroda, khoam, post #18213440]

How fast can I push binary packets?

At 115 200 bps a 16-byte struct needs ~1.4 ms. Even at 512 000 bps full-duplex works if you enable SERIAL_FULL mode on ESP8266 [Elektroda, khoam, post #18266679]

Edge case: What if bytes shift out of alignment?

Insert a start byte (e.g., 0xAA) and check it before assembling the float; discard frames that miss the marker. This guard prevents ‘glued value’ corruption mentioned by krisRaba [Elektroda, 18208944]

Quick 3-step recipe for reliable two-way float exchange?

  1. Define identical packed struct on both MCUs.
  2. Sender: if (Serial.availableForWrite() >= sizeof(pkt)) Serial.write((byte*)&pkt, sizeof(pkt));
  3. Receiver inside loop: if (Serial.available() >= sizeof(pkt)) Serial.readBytes((byte*)&pkt, sizeof(pkt)); update variables. This keeps TX and RX in sync without blocking.

Why not just print the float as ASCII?

Binary send is 2–6× faster and uses one-third of the bytes (4 vs ~14 chars for "-123.456") [Arduino Labs, 2022].

Will SoftwareSerial solve multi-UART issues on ESP8266?

Yes for low rates (<57 600 bps). SoftwareSerial gives extra RX/TX pins when the hardware UART is busy, but consumes CPU cycles [Elektroda, khoam, post #18247123]

What happens if Serial.write is called while UART is receiving?

Standard Serial is half-duplex: TX waits until RX idle unless SERIAL_FULL is enabled; otherwise the call blocks and may stall tasks [Elektroda, khoam, post #18266639]

Can I move everything to I2C instead of UART?

Possible, but only one Master is allowed on classic I2C. Multiple ESPs would need Master-Slave roles and bus arbitration [Elektroda, khoam, post #18235407]
Generated by the language model.
ADVERTISEMENT