Modbus floating point conversion

Dear all,

here is code for measuring string current using modbus protocol; I have used the standard modbus library to interface modbus protocol. Now i have sensor output in float value & buffer it stores in int value. how can i save data directly in float here. i have totally 25 current parameter ; 1 voltage ; 1 temprature sensor ; All the values are in float only.

How could i convert & read in modbus protocol.
i have attached complete code here. Since i am new to modbus programming let me know how to resolve this??

i have doubt in below part of conversion; this code work on integer value;

In main_c

uint16_t au16data[30];

in loop function

 state = slave.poll( au16data,30 );

declare here

void Modbus_call()
{

/*reading of coil where i can succefully read value*/
  au16data[1]=(int)(100*Current_Value1[0]);
  au16data[2]=(int)(100*Current_Value1[1]);
  au16data[3]=(int)(100*Current_Value1[3]);
  au16data[4]=(int)(100*Current_Value1[4]);
  au16data[5]=(int)(100*Current_Value1[5]);
  au16data[6]=(int)(100*Current_Value1[6]);
  au16data[7]=(int)(100*Current_Value1[7]);
  au16data[8]=(int)(100*Current_Value1[8]); 
  au16data[9]=(int)(100*Current_Value2[0]);
  au16data[10]=(int)(100*Current_Value2[1]);  
  au16data[11]=(int)(100*Current_Value2[2]);
  au16data[12]=(int)(100*Current_Value2[3]);
  au16data[16]=(int)(100*Current_Value2[4]);
   au16data[17]=(int)(100*Current_Value2[5]);
   au16data[18]=(int)(100*Current_Value2[6]);
   au16data[19]=(int)(100*Current_Value2[7]);
  uint16_t calcCRC( au16data[15]);
     au16data[13] = slave.getInCnt();
  au16data[14] = slave.getOutCnt();
  au16data[15] = slave.getErrCnt(); 
  
 }

modbus_CS2.zip (7.4 KB)

how can i save data directly in float here

How about making au16data an array of floats, or have I misunderstood the problem ?

I think you might have to use the long data type as i remember from when i dis a modbus arduino project rather than uint16. floats on modbus will be 4 bytes not 2

EVP:
I think you might have to use the long data type as i remember from when i dis a modbus arduino project rather than uint16. floats on modbus will be 4 bytes not 2

How can use this in above code. I also like to know can use my own memory address. Here default address start with 0 if wanna start with 4000H how could i map it.

Is this in any way related to your other thread: modbus compile error?

These are two different code. Please check for reference.

One thread where code is working fine but need information how can convert floating value.

another thread is other library need infomation how to compile code. Since declration of header file totally different.

  au16data[1]=(int)(100*Current_Value1[0]);

au16data[2]=(int)(100Current_Value1[1]);
  au16data[3]=(int)(100
Current_Value1[3]);
  au16data[4]=(int)(100Current_Value1[4]);
  au16data[5]=(int)(100
Current_Value1[5]);
  au16data[6]=(int)(100Current_Value1[6]);
  au16data[7]=(int)(100
Current_Value1[7]);
  au16data[8]=(int)(100*Current_Value1[8]);

Can I suggest you read up on how loops work? This is just clutter. Also you seem to be skipping "2" on the right-hand side, which wouldn't happen if you wrote a proper loop.

I need answer for how to store floating value directly instead of integer,

I know that code has lots of glitter, I have put example code i tried which worked for me. Where i cant data in integer format .

I need answer for how to store floating value directly instead of integer,

Where do you want to store it ?

In above code i pasted the data being stored in address 0000H . while checking on Qmodbus.

These values beings stored in integer format. But i wanted to stored in floating value directly.

Question need to be answer:

  1. how can i store sensor values which are floating values directly here
  2. how can i change default address 0 to predefined address say 4000H??

These values beings stored in integer format.

I am sorry, but I am still not getting it. Can you please point out a line in the program that stores a value as an int that you would like to change to a float.

check my code once. you will understand what i am trying here.

for example. Sensor output is 13.10 A i am storing in au16data[1] has 1310 value in address of 0000H .

I want to store the value as 13.10 as it is in databuffer. How can store this??

How can change default address of memory mapping.

Also refer the library link attached where explain properly about detail

here simple code to read temprature sensor data lm 35

#include <avr/wdt.h>
#include"glob.h"

float temp;
int tempPin = 5;



int8_t state = 0;
Modbus slave(Device_ID, 0, 0);
unsigned long tempus;
// data array for modbus network sharing
uint16_t au16data[30];


void setup()
{
  wdt_enable(WDTO_8S);
  slave.begin( 9600 );
  tempus = millis() + 100;
  pinMode(A5,INPUT);
 Serial.begin(9600);
}


void loop()
{

state = slave.poll( au16data,30 );
  if (state > 4) {
    tempus = millis() + 50;
    digitalWrite(13, HIGH);
  }
  if (millis() > tempus) digitalWrite(13, LOW );
 
 TakeReading();
 delay(500);

}

void TakeReading()
{
   temp = analogRead(tempPin);
    temp = temp * 0.48828125;
   au16data[1]=(int)(100*temp);
  au16data[13] = slave.getInCnt();
  au16data[14] = slave.getOutCnt();
  au16data[15] = slave.getErrCnt(); 
}

Here temp is value float, i wanted to read temp value as it is in address of buffer during MODBUS read coil function.

In below code

au16data[1]=(int)(100*temp); convert to integer format & strore. question how can store as float??

how can change start address here.

void TakeReading()
{
   temp = analogRead(tempPin);
    temp = temp * 0.48828125;
  [b] au16data[1]=(int)(100*temp);[/b]
  au16data[13] = slave.getInCnt();
  au16data[14] = slave.getOutCnt();
  au16data[15] = slave.getErrCnt(); 
}
uint16_t au16data[30];

As I suggested before, au16data is currently an array of ints. If you want to put floats in it then why not make it an array of floats.

I still don't understand your reference to the base address of the data being 0000H, particularly as au16data[1] is not the first position in the array anyway.

In general you have no control over the address of where variables, including arrays, are stored.

ok. how can store as array _float instead of array of int??

can you explain why if say adress 0000H in qmodbus or any modbus protocol software if i give start address as 0 or 0000h why data being recorded there
if i wanna store the value in other memory map address how can i store it.

how can store as array _float instead of array of int??

Change

uint16_t au16data[30];

to

float au16data[30];

can you explain why if say adress 0000H in qmodbus or any modbus protocol software if i give start address as 0 or 0000h why data being recorded there

No, I can't explain this because I know nothing of the modbus protocol. However, if you tell it to use address 0000 it should not surprise you to find that it uses it.

Where exactly in your code are you specifying address 0000. Please do not tell me to read your code to find out, just tell me. Where is the memory that the data is being stored to ?

Current_Value1[row]=  (Mux1_array[row]*35.1428571429)-87.6571428571;

Just how accurate are you trying to be ? 10 decimal places ? Some chance.

As i told i am just beginner in MODBUS. I have written code PLC where you assign address & port directly.

The code i have written its taken from link, which mentioned in thread 1.

So thats reason i dont know how it store address to 0000H. In PLC you can assign start address & end address that reason i am asking How it stored by default.

First, just to let you know;
AMPS-N wrote:

if i wanna store the value in other memory map address how can i store it.

The word 'wanna' is not correct use of the English language.
The word you mean to use is 'want to', just in case you did not know.
I noticed you used 'wanna' twice in this thread, so maybe English is not your first language and you may have picked up this bad use from someone else.

I am finding this thread confusing, but what I think you are wanting to know is how to get a data register holding a float value transferred using Modbus protocol using holding registers, is this correct?

If so, then, you will know that holding registers are 16 bit words, and that you can use two of them to represent the float of 32 bits wide.

If the float is 32 bits wide, then you need two contiguous 16 bit holding registers to store this.
The data wil be transferred as normal 16 bit data to the other side, where you will then need to re-interpret this data as a 32 bit floating point value.

Just set up your Modbus register array using 16 bit words, but where you define the location of the floating point value or values, have your code store the 32 bit floats there.

Then, as I mentioned, have the Modbus master interpret those holding registers as 32 bit floating point values.

Is this what you are wishing to do?


Paul

Thanks for reply. can you give example for above code . How can store it

First, just to be clear about data types.
AMPS-N wrote:

ok. how can store as array _float instead of array of int??

For Modbus, you can not use floats directly with holding registers as these registers are only 16 bit but unspecified data type, and you can not hold a float in 16 bits. But by using two 16 bit words, we can hold the float. But the Modbus protocol need know nothing about this, as we will have code that will store the float at a register address using two locations, and then have the destination end use those same two registers to re-compile the data into a float data type.

UKHeliBob wrote:

No, I can't explain this because I know nothing of the modbus protocol

Thus to advise using an array of floats will be the cause of great grief as Modbus will not interpret this data as floats.

Like I detailed in my post above, first I need the OP to confirm my question directly, is what I think you wish to do in fact what you do wish to do?

Answer this first, so I know I understand you, and that you also understand my suggestion, before going deeper into providing any example code.


Paul