Problem in Sending Modbus (Command) Float32 data

Forum Home Forums Communicating with Devices Modbus Problem in Sending Modbus (Command) Float32 data

Tagged: ,

This topic contains 16 replies, has 3 voices, and was last updated by Mikhail Mikhail 2 years, 4 months ago.

Viewing 15 posts - 1 through 15 (of 17 total)
  • Author
    Posts
  • #2234
    Avatar
    raazsi
    Participant

    Hi Rapid Scada Team,

    Thanks for making such an amazing open source project !

    I am trying to simulate a Modbus command wherein I am sending Float data (IEEE 754) to a Modbus Simulator ModSim_RS. I can see the data correctly when I select data format in ModSim_RS to decimal or word 16 but I can’t see data when I change the format to float32 Which led me to conclude that Modbus command we are sending from RapidScada is 16-bit data.

    I tried to convert it into floating point using formula but it’s not working Then I opened source code for KpModbus and I made change of data type from ushort to float for below code

    {
    modbusCmd.Value = modbusCmd.TableType == Modbus.TableTypes.HoldingRegisters ?
    (float)cmd.CmdVal :
    cmd.CmdVal > 0 ? (float)1 : (float)0;
    }
    All done and said but then I couldn’t save this change as kpModbus.dll So I am kind of stuck with this. Kindly bail me out, please !!!

    #2236
    Mikhail
    Mikhail
    Moderator

    Hello,

    then I couldn’t save this change as kpModbus.dll

    Please explain what do mean? How do you do this?

    I think, it’s possible to solve your issue without changing KpModbus.dll. I can tell how to configure it if you provide more information: what value should be sent by an operator and what data (in hex format) should be sent to the device?

    Update: usually the command 0x10 (Write Multiple Registers) is used for sending float data to a device. In this case you can tick the Multiple command checkbox in Communicator and send any data.

    • This reply was modified 2 years, 5 months ago by Mikhail Mikhail.
    #2240
    Avatar
    raazsi
    Participant

    Hello Mikhail,

    I intend to communicate with Bristol Babcock Make RTU (PLC). I have already successfully communicated with it for reading its holding register values into RAPIDSCADA. For that, I had to assign data type as Float32 and byte order as {2301 5687 } in the communicator.

    So I presumed that in order to write values to that PLC from RAPIDSCADA communicator I need to have my data type as Float32 and likewise I might have to tweak with byte order also.

    Before actually writing values into PLC, I tried simulating it with mod_RS SIM.

    I started with configuring my device template for COMMAND. Checked on Multiple command checkbox. Assigned My starting address as 40 and element count as 2. Then I went into command tab of the device in communicator and started giving the value of 14. Command type is Standard.

    In the Communicator log, I got sent bytes as

    Sent(17) : 00 00 00 00 00 0B 01 10 00 27 02 04 00 00 00 00(Hex OE for 14 not sent)
    Receive (12) 00 00 00 00 00 06 01 10 00 27 00 02

    In the mod_RS SIM communication traffic, I got,

    Write multiple Registers from 39 for 2 Registers.
    RX : 00 00 00 00 00 06 01 10 00 27 00 02 (only 12 bytes Received)
    TX: 00 00 00 00 00 06 01 03 00 09 00 0A

    Then I thought ok, lets test if for a single write, In that case in Communicator log i got sent bytes as:

    Send (12) 00 00 00 00 00 06 01 06 06 00 27 00 0E (OE for value 14 is present)
    Receive (7/7) 00 00 00 00 00 06 01
    Receive (5/5) 06 00 27 00 0E

    Similarly, in the mod_RS SIM communication traffic, I got,

    Write Single Register 39.
    RX : 00 00 00 00 00 06 01 06 00 27 00 0E
    TX : 00 00 00 00 00 06 01 06 03 09 00 0A

    #2242
    Mikhail
    Mikhail
    Moderator

    I validated the packages by http://modbus.rapidscada.net/ They are wrong. Communicator never sends wrong requests.
    Could you provide screenshots?

    If you need to send float, you need at least 4 bytes to store it. So you can’t use Write Single Register command which sends 2 bytes.

    #2244
    Avatar
    raazsi
    Participant

    Hi,

    I am sharing with you a document wherein I have shared screenshots and the configurations which I used to send data.

    https://drive.google.com/file/d/0B16F1h3WZUUxYmVKM0k1U1RoaGc/view?usp=sharing

    • This reply was modified 2 years, 5 months ago by Avatar raazsi.
    • This reply was modified 2 years, 5 months ago by Avatar raazsi.
    #2249
    Mikhail
    Mikhail
    Moderator

    Hi,

    Thank you for the details.
    You should understand how the data are encoded when you send the command 0x10 (Write Multiple Registers):
    You can choose either:
    1. Binary command. Using this option you can explicitly specify the bytes which are sent. Let’s try it.

    2. or Standard command. See these lines:

    modbusCmd.Data = cmd.CmdTypeID == BaseValues.CmdTypes.Standard ? 
    BitConverter.GetBytes(cmd.CmdVal) : cmd.CmdData;
    

    The value 14 is 0x402C000000000000 when converted into a double (see this). Then you send the 4 bytes from the right that are zeros.

    You can create formulas in the configuration database to convert data entered by a human to the format described above.

    #2269
    Avatar
    raazsi
    Participant

    Hi …

    Thanks for your help.. Finally I could get my job done. I used binary command. This is how i did it.

    I wanted to send numbers like 110, 120 etc. The device to which i am sending is configured for float data type. So in order to send decimal 110. I converted it into hexadecimal equivalent of ieeefloats

    110 = 0x 42 DC 00 00

    0x42 = 66
    0xDC = 220

    Then I used formula
    new byte[4]{0,0,66,220}

    #2272
    Mikhail
    Mikhail
    Moderator

    Hi,

    You can also use BitConverter.GetBytes as a formula of an output channel to convert a number into array of bytes:

    BitConverter.GetBytes((float)Cmd)
    
    #2275
    Avatar
    raazsi
    Participant

    Thanks for your valuable info 🙂
    Is there any way of sending a trigger pulse ??? Like i want to give reset command

    #2281
    Mikhail
    Mikhail
    Moderator

    Please explain the task

    #2283
    Avatar
    raazsi
    Participant

    I want to reset a timer in PLC from SCADA appication. I have a reset bit which when asserted high make timer again to zero.

    SO i have put a command button in schematic With that i am sending discrete value 1. Is there any way to make it like a reset bit i.e. when i give command it is asserted high only for 1 cycle and hence after it gets back to zero again….

    #2284
    Avatar
    manjey73
    Participant

    https://s30.postimg.org/9etq90vmp/RStrig_Reset.png

    Base formulas
    ————————————————
    ResetCnl
    ————————————————
    double ResetCnl(double val, int InCnl)
    {
    bool q = val > 0;
    if (q)
    {
    q = !q;
    CnlValSet(InCnl, 0);
    }
    return Convert.ToDouble(q);
    }
    ————————————————-
    RStrig
    ————————————————-
    double RStrig (double set, double res)
    {
    bool s = set > 0;
    bool r = res > 0;
    bool q = r ? q = false : Val(CnlNum) > 0 || s;
    return Convert.ToDouble(q) ;
    }
    —————————————————
    Ton
    —————————————————
    int[] TonNum = new int[1];
    long[] TonST = new long[1];
    bool[] TonFlag = new bool[1];
    public double Ton(double TonIn, long TonPT)
    {
    long ET = 0L;
    bool q = Val(CnlNum) > 0;
    bool ton_in = TonIn > 0;

    int res = Array.IndexOf(TonNum, CnlNum);
    if (res == -1)
    {
    res = TonNum.Length;
    Array.Resize(ref TonNum, res+1);
    Array.Resize(ref TonST, res+1);
    Array.Resize(ref TonFlag, res+1);
    TonNum[res] = CnlNum;
    }

    if (!ton_in)
    {
    q = false;
    TonFlag[res] = false;
    TonST[res] = 0L;
    }
    else
    {
    if (!TonFlag[res])
    {
    TonFlag[res] = true;
    TonST[res] = Ticks();
    }
    else
    {
    if (!q) ET = Ticks() – TonST[res];
    }
    if (ET >= TonPT) q = true;
    }
    return Convert.ToDouble(q);
    }
    ———————————————————

    I use formulas and module of automatic control to re-send the command
    May still need to make the formula entry a bit to the desired value, if necessary.

    Sorry for my English, is machine translation

    #2286
    Avatar
    manjey73
    Participant

    Ticks
    ————————————
    public static long Ticks()
    {
    DateTime now = DateTime.Now;
    long time = now.Ticks/10000;
    return time;
    }
    ———————————–

    You want to work Ton

    • This reply was modified 2 years, 4 months ago by Avatar manjey73.
    #2288
    Mikhail
    Mikhail
    Moderator

    A command value doesn’t stored somewhere in SCADA. It is just sent to PLC. I’m not really understand the task of changing a command from 1 to 0.
    You can change a value of an input channel programmatically.

    • This reply was modified 2 years, 4 months ago by Mikhail Mikhail.
    #2290
    Mikhail
    Mikhail
    Moderator

    If you need to send 2 commands one by one, you can do it with Automatic Control Module. In this case, an operator sends one command via UI, then the module reacts on it and sends two commands.

Viewing 15 posts - 1 through 15 (of 17 total)

You must be logged in to reply to this topic.