Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Modbus writing on value change

2024-03-26
2024-04-03
  • duvanmoreno24 - 2024-03-26

    Hi all,

    I want to know if someone has an idea of how I can write on value change in Modbus Codesys. I have a Wago PLC and I was used to work with E-cockpit which it was quite easy to do that without the necessity to trigger any value when there was a change in the variable ( I will put how easy is ). how you can see just changing the trigger in "On value Change" will do that channel writing automatically when It detects a change in those arrays. On the other hand, in Codesys if I enable the rising edge in Codesys It ask me to put a bool variable and if triggers is going to write that value. That is making me that I have to create a function or a logic to detect the change, the problem I have is that doing that is very tedious. I first approach I got it was to create a Function who returns a bool when the value change, but I tried to keep the old value but what is happening is that in Functions all the data is erased every cycle so I can not keep any Old value. so in the Main program the trigger is going to be TRUE all the time due, the old value is cero every cycle. The second approach I got it was using a function Block (POU_1) and it works but I dont want to instance that function for every Channel or value that I want to check if the value change, Basically if I have 200 values to write trhough modbus I have to create 200 instances of that function which I think it is not practicall at all. It should be a better way to implement this as e-Cockpit from Wago Does. However, I haven't been able to know how.

     
  • alexgooi

    alexgooi - 2024-04-02

    Hi Duvan,

    You could make this in 1 single object (FB), Indeed don't use a function for this beacuse you need some memory to keep the old value.

    For i := 0 TO 200 BY 1 DO
        //Check if the value has been changed
        IF Old_Value[i] <> Value[i] THEN
            //Set the trigger to TRUE
            Trigger[i] := TRUE;
            Old_Value[i] := Value[i];
        END_IF
    END_FOR
    

    If you define the Value array as an In_Out and the Trigger as an In_Out you arn't claiming any aditional memory to your system. You ofcourse then need to add some code arround it that does something with the trigger and writes it back to FALSE again.

    If you want more flexability you also could use pointers instead of using the IN_OUT

    FOR i := 0 TO 200 BY 1 DO
        address := address_Input + i * SIZEOF(*Put type here);
        IF Address^ <> Old_Value[i] THEN
            Trigger[i] := TRUE;
            Old_Value[i] := Address^;   
        END_IF
    END_FOR
    
     

    Last edit: alexgooi 2024-04-02
    • duvanmoreno24 - 2024-04-03

      Yes, I tried to do what you put in the first code. However, I have a problem with that and that is that the inputs must be declared with the type. I have many data types running in my code (real, int, uint, bool) and I can't put them in the same function, another thing is that I need to instantiate that function for everything I want to write to the slave. You put a for to 200 but it means that it has to be the same data type and inside the array, but I want to get them individually. I'm struggling to do it in a good and efficient way like wago's E-cockpit does. in the first screenshot you can see, you simply type in value, change the package of things you want to write in value change and it does everything by itself automatically, without comparing any old and new values and even less having the need to activate a bool. , it is perfect.

       
      • alexgooi

        alexgooi - 2024-04-03

        The way I usally tackle this is by syncing only words (then you are able to use the FB above).

        If you then want to write a Boolean simply type it like this.

        Value[1].0 := Bool1;
        Value[1].1 := Bool2;
        Value[1].2 := Bool3;
        

        Uints have the same number of bits than a INT/WORD so these ones will work as well (they are only represented diffrently).

        A Real will work but you will loose some infomration in the conversion.

        If you want to keep the information you can convert 2 words to a float with a function (for example with the IEEE-754 standard) .

        In this way the syncing to the server is very simple and in the Codesys Program you decide what part of the word you want to use.

         

        Related

        Talk.ru: 1


        Last edit: alexgooi 2024-04-03

Log in to post a comment.