logo elektroda
logo elektroda
X
logo elektroda

How to send float values between Arduino over UART?

omnixcrs 3042 52
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 18208876
    omnixcrs
    Level 11  
    Hello Ladies and Gentlemen,
    I need to send a value of e.g. 22.5 which is a float between two Arduino's over the UART. While I can use the following codes to send int data, I don't know how to do it as a float.
    The sending arduino uses these instructions:
    
    void setup() {
      Serial.begin(9600);
    }
    
    void loop()
     {
      Serial.write(45);
    }
    
    .
    Whereas in the receiving arduino :
    
    int incomingByte = 0; 
    
    void setup() {
      Serial.begin(9600); 
    }
    
    void loop() {
      
      if (Serial.available() > 0) {
     
        incomingByte = Serial.read();
        Serial.println(incomingByte, DEC);
      }
    }
    .
  • ADVERTISEMENT
  • #2 18208944
    krisRaba
    Level 31  
    I don't know if there will be any nifty functions for this in Arduino, but in general a float like this is a 32bit variable, so you can dismember it and send it piece by piece, and glue it back together on the other side.
    This can easily be done by defining a union, which is a creation that points to the same range of data, but is interpreted depending on how you call it. I'm writing from memory, but I think it flew like this

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

    and then u .value behaves like a float, and u .bytes[] like an array. And the whole beauty of union is that you type something into a float and then access it byte by byte in an array, e.g.

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

    and on the other hand you glue it together analogously, i.e. you push the received bytes one by one into u.bytes[i], and then you use yourself u.value as a float....

    Of course, there will be a problem if your communication goes awry and the bytes move, because then the glued value will be nonsense ;)

    Ps. I don't know if this will go in Arduino, but I think it will work in C++ what is written in C ;) .
  • #3 18209021
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • Helpful post
    #4 18209031
    krisRaba
    Level 31  
    Oh see, even better solution :) I thought this write() only ingests byte by by byte, hence the idea of an extra loop etc. :lol:
  • #5 18210991
    omnixcrs
    Level 11  
    Welcome,

    I have used your instructions khoam:
    broadcasting:
    Code: C / C++
    Log in, to see the code
    .
    Receiving:
    Code: C / C++
    Log in, to see the code
    .
    Unfortunately I have 0.00 in the serial, of course in the setup in one and the other device I have float value =0 set;
  • #6 18211014
    Anonymous
    Level 1  
  • #7 18213403
    omnixcrs
    Level 11  
    Hi khoam,
    sory for misleading the arduino does however send the float value correctly, but I don't know why it only works for some time around 3-5min. I wrote a test program to display the transmitted temp value on lcd2x16. After running it displays tamp 22,5 and 27,5 but for literally 3-5min then it is already 00,0. Why is this happening. I am pasting the codes:
    Broadcasting:
    Code: C / C++
    Log in, to see the code
    .

    Receiving
    Code: C / C++
    Log in, to see the code
    .
  • #8 18213440
    Anonymous
    Level 1  
  • #9 18213493
    omnixcrs
    Level 11  
    Ok I will try it and let you know, and tell me if identical commands I can use for int ?
  • #10 18213498
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #11 18214001
    omnixcrs
    Level 11  
    Hello, well unfortunately it didn't work. The reason for the problem is rather my receiving code because when I reset the arduino with the display(receiving) then for a while temp_pump has a value and then again 0.00. Actually my code is a bit more elaborate but I didn't want to upload the whole thing to avoid clutter. This time I am uploading the whole pickup maybe I have something wrong:
    Code: C / C++
    Log in, to see the code
    .
  • #12 18214161
    Anonymous
    Level 1  
  • Helpful post
    #13 18214198
    krisRaba
    Level 31  
    Try in the transmit module to reduce the frequency of transmitting the measurement data since you display it every 30s, or receive the data and update the variable in the interrupt, or when receiving, read from the buffer everything you have available to free up space. Because if you transmit every 2 or 4 seconds and read every 30, it's no wonder it clogs up after a while.... By the way, in such a system you display the old data, because you sent one measurement, displayed, after two seconds another one... but it will wait another 28s to read from the buffer and display. After another 2 seconds you send another one, but it will display after 26+30=56s, the fourth one sent after another 2 seconds will only display after 24+30+30=84s etc. And the queue gets clogged up....

    All in all, it's good to send more often so you always have up-to-date info when you miss a carousel of screens, but you have to pull it from the buffer in time and display the latest one....


    Ps. Are you specifically delaying the start of the controller to display the startup caption to yourself? Is there actually something starting up in the background there? ;-)
    And why do you write Startup so many times with extra dots, when you only need to write once and then just position the cursor accordingly and add a dot? ;-)
  • Helpful post
    #14 18214225
    Anonymous
    Level 1  
  • #15 18214226
    omnixcrs
    Level 11  
    The start-up delay is intentional because additional peripherals start up during this time.
    As for Serial I am unfortunately not strong in this. Would using millis instead of dealy help. I ask because I don't know if I can handle interrupts.
  • Helpful post
    #16 18214229
    Anonymous
    Level 1  
  • #17 18232315
    omnixcrs
    Level 11  
    Hello Gentlemen,
    It took me a while because I was struggling with this program in all sorts of ways, but no luck.
    So yes: following your advice khoam, I gave up on delay() altogether and used SimpleTimer to split the program. Your suggestion with TaskScheduler is also interesting, but maybe I didn't have time to recognise it this time. SimpleTimer also has a similar action only less advanced, but to the point. I divided the program into sections. In Loop() I basically only have timer.run() the rest executes in time intervals. Now, here's the thing: in the beginning, when I tried it with one variable, receiving on the UART seemed to work, but I need to send and receive data (two-way communication) from several variables between two esp and it actually works and doesn't work. I don't think I fully understand how Serial works. I have tried different send and receive times (always intervals of more than 10s) and have tried sending and receiving at the same time, i.e. one esp sending every 20s and the other receiving every 20s. I have also tried receiving more often, e.g. every 10s, and transmitting less often, e.g. every 30s, and I also get 0.00. I have a maximum of 10 variables to transmit. I don't want to put in a whole lot of code, so here are the most important functions I have used:
    ESP1
    Code: C / C++
    Log in, to see the code
    .

    And on ESP2:

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

    And now yes: from the above codes the result is that e.g. ESP2 should send the value on_pump to esp1, unfortunately it doesn't. I have a 2x16 LCD connected to esp1 via I2C (so as not to use Serial.print) initially after applying power to the display I have on_pump = 35 but after the first UART send/receive I already have a value of 0.00. Why?
  • ADVERTISEMENT
  • Helpful post
    #18 18232366
    Anonymous
    Level 1  
  • #19 18235028
    omnixcrs
    Level 11  
    Hello,
    I have applied your idea khoam and as far as the UART is concerned it indeed works and rather works. But of course I encountered another problem. Generally this device of mine is a combination of 3 pcs ESP and 2x16 LCD over i2c + 2x PCF8574 expander. Well I think there is a problem on the i2C bus. All ESPs are connected to each other via UART and of course share the SDA and SCL lines, also the LCD is connected to these lines. Theoretically everything works but for a short time, i.e. after powering up for some time one of the esp displays on the lcd what is to be displayed the other one nicely manages the expander but after some time e.g. after 3-5 min on the LCD "bushes" appear or the esp from the LCD hangs up. I don't know if I'm getting it right, but I suspect this may be due to some conflict on the i2c line. E.g. when one esp is trying to display something on the LCD via i2c and the other esp is reading some status from the expander via i2c, is this possible?
  • #20 18235038
    krisRaba
    Level 31  
    Well you have made a multimaster ;-) The question is whether the soft supports this. Because in most cases you have one master and multiple slaves that only respond as you ask them.
    With multiple masters you still have to have arbitration of access to the I2C line so that when one starts transmission, the others wait politely....
    Electrically there is no problem because you have pullup and open-collector outputs, but the soft and preferably hardware must support arbitration. You can always split the I2C, and push the data between the MCU and the one that has the display will handle it ;-) .
  • #21 18235407
    Anonymous
    Level 1  
  • #22 18235525
    omnixcrs
    Level 11  
    Ok, I understand and thanks for the tips, but in my case the problem might be a bit different because in sum I can disconnect the two esp from the one esp but still at this point this one esp has to handle the lcd over i2c and the pcf8574 expander which is used for the buttons and I suspect this is where I have a problem. I have a timed program so every so often data is displayed on the lcd with a fixed time interval(5s) and the expander pin reading is done every 1s. Can this generate problems ? For pcf I use pcf8574_esp.h library and for lcd LiquidCristal_I2C
  • #23 18235581
    Anonymous
    Level 1  
  • #24 18235706
    omnixcrs
    Level 11  
    khoam wrote:
    I also assume that one esp supports both I2C devices.
    .
    You are making a good assumption, as I wrote above:
    omnixcrs wrote:
    one esp must support LCD over i2c and expander pcf8574
    .
    And I am just explaining that the program in this esp supports both LCD I2C and PCF expander I2C
    I will abbreviate the code a bit but to me it looks more like this:

    Code: C / C++
    Log in, to see the code
    .
  • #25 18235712
    krisRaba
    Level 31  
    Well, unless there is somehow a cleverly done so-called Gate keeper, which makes one library wait until the other one finishes, it can happen that the soft is hammering on the hardware while the transmission is in progress....
    In my early days with the MCU I inadvertently did this on the SPI, as I would normally talk to the display, and when an interrupt came in from the peripheral I would read data from it. Occasionally such a service would bite into the state when the CS was already in the low state and add its own, meaning two could respond and generally fail ;-) .
    Now on RTOS I do things like this on semaphores etc. But if you have 2 independent libraries configured for the same hardware, one that they may not know about each other and two that they may be written in an authoritarian way that only I'm in charge and I don't even check what state the hardware is in ;-)
  • #26 18235719
    omnixcrs
    Level 11  
    I supply 5VDC
  • #27 18235814
    Anonymous
    Level 1  
  • #28 18236210
    krisRaba
    Level 31  
    Well, if there is no expropriation here, the I2C functions are probably blocking, I2C transmissions are not triggered in interrupts, then theoretically one transmission should not hatch to another inside the ESP (because connecting multiple masters to I2C was not a very good idea ;) )
  • #29 18247068
    omnixcrs
    Level 11  
    Hi guys, I followed your tips and advice. Connecting three MCUs over i2c without prioritization was not the best idea. I have fixed this. Now the issue is that the first esp serves the first expander over i2c the second esp has nothing on i2c and the third esp serves itself the second pcf. Of course the i2c lines are routed separately and do not connect ! So that leaves me with the uart communication between the MCU and here I have some questions about how it works.
    You mentioned khoam that the serial buffer in esp is 128 bytes. Suppose I want to send data from two esp (2 and 3) to the first esp. If I send esp 2 a float variable named e.g. temperature to esp 1, it will take up 4 of the 128 bytes in the serial buffer of esp1. Then esp 3 sends a float variable named e.g. temperature2, it will take another 4 bytes out of the 124 remaining in the esp1 buffer. Well, and now I don't quite understand what the readout looks like. I.e. if I call for example:
    Code: C / C++
    Log in, to see the code
    .

    then I read the variable temperature or temperature1 ?? I mean, does this command give the ability to recognise data by name or only by byte size ? I hope I haven't messed up too much.
  • #30 18247088
    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.
Summary generated by the language model.
ADVERTISEMENT