View previous topic :: View next topic |
Author |
Message |
borseyogesh1436
Joined: 30 Nov 2017 Posts: 29
|
how to send double with modbus |
Posted: Wed Dec 20, 2017 11:49 pm |
|
|
Hi friends, I want to send double with holding resistor. I am using pic18f46k22 with PCH Version 5.015.
I have successfully sent float and here is code:
Code: |
#include <IEEEFLOAT.C>
float FR;
unsigned int32 intval;
unsigned int16 oohh, mmll ;
intval=f_PICtoIEEE(FR);
oohh = (unsigned int16)(intval >> 16);
mmll = (unsigned int16) intval & 0x0000ffff;
hold_regs[0]=mmll;
hold_regs[1]=oohh;
|
Now i have to send double with holding resistor. How to convert pic to IEEE for double and send that to hold_regs[0] to hold_regs[4] ?
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Dec 21, 2017 2:22 am |
|
|
Since your PIC doesn't support double, you have a problem.....
Where is the double going to come from?.
If you declare a 'double', it is forced to be a float32.
As a comment on your existing code, use a union, rather then the rotations and mask. Fortunately the compiler is smart enough that it'll probably have optimised this, but it is silly to be doing these operations when you could access the values directly:
Code: |
typedef union { unsigned int16 words[2]; unsigned int32 whole; } word16;
float FR;
word16 intval;
intval.whole=f_PICtoIEEE(FR);
hold_regs[0]=intval.words[0]; //LSW
hold_regs[1]=intval.words[1]; //MSW
|
This creates a new 'type', formed by a union, between an unsigned int32, and two unsigned int16 values. You don't have to move the data into temporary values you can just access them directly. Saves RAM, and creates efficient code.
The processors that do support 'double' (PIC24/30/33), also support an int64 type. On these the floats are already in IEEE format as well. |
|
|
borseyogesh1436
Joined: 30 Nov 2017 Posts: 29
|
|
Posted: Thu Dec 21, 2017 2:35 am |
|
|
Thanks for reply Ttelmah
double FR; that i have to send to modbus poll.
Is there any way to send 8 digit decimal value like "99999999.9" to modbus poll with pic18f ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Dec 21, 2017 4:41 am |
|
|
double FR, declares a float32, not an actual double on your chip....
Read the manual. Look at the section on 'type specifiers'. Note the 'N/A' against 'double', in the manual for the PCB/PCM/PCH compiler.
Then if you look at 'type qualifiers':
Quote: |
double is a reserved word but is not a supported data type
|
The declaration is automatically changed to a float32 type, not a float64.
Obviously, yes is is possible to send a double, but you would have to do it all yourself. Declare a structure to contain the 'type', and build your own maths and conversions to do what you need with it. However be prepared to be aghast at just how much memory even the simplest operations on this type would involve. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Dec 21, 2017 6:01 am |
|
|
Before IEEE754 came along in the eighties, the answer was simple: don't send any floats. There were so many different floating point formats that it there was no standard and conversion had to be done on a case by case basis and often a precise conversion was not possible.
Even now there is no standard as to byte ordering when sending IEEE754 float data. Modbus poll apparently has four options for nibble order for float32 (single length float) and four more for float64s (double). This is all on page 18 of the Modbus Poll manual at http://www.modbustools.com/PI_MBUS_300.pdf .
As Ttelmah says, CCS C on PIC18s does not support double length floats.
Arguably it is possible to convert double to single and vice versa fairly easily, but you will lose precision and a lot of exponent range. So it is not suitable for all doubles. It involves quite a bit of bit shuffling but is possible. Probably easier to do it as a double_to_single_IEEE() and then to convert the IEEE single to Microchip format (which is also done by bit shuffling) using the CCS supplied routine. Though it would be possible to do it directly, but do you want to learn the format of IEEE754 singles or that of the more obscure Microchip format?
So, what did we do in the old days? Exactly what us "old timers" suggest for internal PIC use, use scaled integers. You can send your example, 99999999.9, as a 32 bit integer, i.e. 999999999 with one implied decimal place. No, you can't send the full range of doubles or even single length floats this way, the range simply isn't there, but you can send most practical values this way. In my Modbus applications I send amps as milliamps, volts and millivolts and dBs as cBs (centibels, yes that one even foxes most RF engineers!) I do the same in all my apps as I stick to the "old ways" and still never send floats of any format as a matter of principle and good practise. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Dec 21, 2017 12:56 pm |
|
|
I have to also reiterate the point that no sensor has sufficient actual resolution to get even remotely close to needing to use a double.
For example the error on the diameter of the Earth, is less than that in the models (just on 1m), using a float32....
And just to agree totally with RF_Developer, an int32 calculation of the same figure could easily hold this to mm levels. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Dec 21, 2017 2:15 pm |
|
|
re:
centibels is that pronounced 'Santa bells' ?
This floating point thing HAS to be 'generational'. I can't recall EVER needing let alone using FP on a PIC. Then again I still have quartz windowed PIC working here.... |
|
|
borseyogesh1436
Joined: 30 Nov 2017 Posts: 29
|
|
Posted: Sat Dec 23, 2017 3:11 am |
|
|
Thanks for reply friend's.
Working with only int32 with modbus, it's easy and simple.
|
|
|
|