Reading Floats

Asked by tkvoice

Is there a function for reading 2 registers and returning IEEE float?

If not does anyone have a coad example showing how to combine 2 integers and convert to float?

Thanks

peter

Question information

Language:
English Edit question
Status:
Solved
For:
libmodbus Edit question
Assignee:
No assignee Edit question
Solved by:
Stéphane Raimbault
Solved:
Last query:
Last reply:
Revision history for this message
Stéphane Raimbault (sra) said :
#1

I replied the following by email sometimes ago but I didn't receive any answer:

  I don't know how float are encoded may be you can just cast the
  received integer into a float with

  (float)(tab_rp_registers[1] << 16 + tab_rp_registers[0])

  Send me the received message (with debug flag enabled in mb_param) and
  information about the float number stored at the requested address if
  you want I have a look at your problem.

  Please share your result if your are successful on Launchpad Answers.

Could you test it?

Revision history for this message
tkvoice (petercheryl) said :
#2

Okay I added this to my code:

---------------------------------------
        int shift;
        int total;
        float real;

        shift = tab_rp_registers[1] << 16;
        printf("shift= %x\n",shift);
        total = shift + tab_rp_registers[0];
        printf("Total= %x\n",total);
        real = total;
        printf("Float= %f\n", real);
------------------------------------------------

Here is the output:

Register 3000= 8858 decimal
Register 3000= 229a Hex
Register 3001= 17509 decimal
Register 3001= 4465 Hex

shift= 44650000
Total= 4465229a
Float= 1147478656.000000

------------------------------

The float I was expecting to see is 916.540649

Thanks

peter

Revision history for this message
Best Stéphane Raimbault (sra) said :
#3

Your total is correct but replace your conversion by this:

real = *((float *)&total);
printf("Float= %f\n", real);

Revision history for this message
tkvoice (petercheryl) said :
#4

Yes !!!! The float is now reading correct!

Thank you

Revision history for this message
tkvoice (petercheryl) said :
#5

Thanks Stéphane Raimbault, that solved my question.

Revision history for this message
tkvoice (petercheryl) said :
#6

Okay I thought I would add a some more to this thread to show how to convert an IEEE float into two(2) 16bit words.
Used to write a float to a Modbus slave:
---------------------------------------------------------------

float real; /* floating number to send to modbus slave */
int IEEE; /* IEEE 754 32bit float data */
int LSW; /* Least Significant Word 16bit of IEEE */
int MSW; /* Most Significant Word 16bit of IEEE */

IEEE = *((int *)&real);
LSW = IEEE << 16;
LSW = LSW >> 16;
MSW = IEEE >> 16;

---------------------------------------------------------------
Then use preset_single/multiple_registers to write LSW & MSW to contiguous register addresses in slave.

Revision history for this message
Andrea Mazzeo (3-admin-smallunix-net) said :
#7

tkvoice ha scritto:
> Question #72329 on libmodbus changed:
> https://answers.launchpad.net/libmodbus/+question/72329
>
> tkvoice posted a new comment:
> Okay I thought I would add a some more to this thread to show how to convert an IEEE float into two(2) 16bit words.
> Used to write a float to a Modbus slave:
>
Hi,
i use this function to convert IEEE to int decimal number:

union my_uf_t {
    char c[4];
    float f;
};

float inline convert(uint16_t hex)
{
    union my_uf_t uf;

    uf.c[3] = hex >> 8;
    uf.c[2] = hex & 255;
    uf.c[1] = 0;
    uf.c[0] = 0;

    return uf.f;
}

bye

--
Andrea Mazzeo
SmallUnix.Net
http://www.smallunix.net
<email address hidden>

Tel. (+39) 02/ 45070804
Mobile (+39)340/33.79.920