CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum by 3S-Smart Software Solutions GmbH | A member of the CODESYS Group
Deutsche Version English version russian version 
It is currently Wed Sep 18, 2019 3:53 am

All times are UTC+01:00




Post new topic  Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Mon May 02, 2016 7:34 am 
Offline

Joined: Fri Apr 29, 2016 7:07 am
Posts: 7
Good morning,
I'm a newby to codesys (V3.5.7), I'm currently reading the 'input variable' by modbus by using the slave modbus/Channel slave modbus/Read Holding Registers and declaring them in global variable.
I can write on this node as well by using 'Write Multiple Register' but I need to write the value only when I change it, not cyclically.
To better explain, I have a net in which the same value should be written from local (plc on the machine) or remote (plc controlled by codesys). I have to maintain the last value written (from local or from remote, same importance). I'm sure it should be done quickly but I can't find the solutions. Any suggestions?


Top
   
PostPosted: Mon May 02, 2016 2:18 pm 
Offline

Joined: Fri Aug 07, 2015 9:59 pm
Posts: 57
Hi
i think you should be able to do it with the 'Rising Edge'. You just Need a variable that would be triggered when the Value changes and this could be mapped to the 'Rising Edge' variable.


You do not have the required permissions to view the files attached to this post.


Top
   
PostPosted: Mon May 02, 2016 3:47 pm 
Offline

Joined: Fri Apr 29, 2016 7:07 am
Posts: 7
Thankyou very much for the respons.

I made something like this:

2 writing, one is for the trigger variable and the other for the value I want to change.
1 reading, that is pointed to the same value of the second reading.

I was espected that if I put one on the trigger variable (which come to true), the value on the writing should pass to the reading as well. But no way to connect the trigger variable to the action that identify the changing of the value on the plc?

Thank you very much.


Top
   
PostPosted: Mon Feb 11, 2019 5:37 pm 
Offline

Joined: Wed Jul 11, 2018 10:44 am
Posts: 24
Hello,
I would like to do smt simmilar.. I want to save value everytime it changes and cyclicly every 15 min for ex.. How i detect change? Did you succed to write program for it?
Thank you.


Top
   
PostPosted: Tue Feb 12, 2019 2:36 pm 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 151
just read the source variable cyclically to know the value. Then compare with one you previously saved. If values are different, then trigger your write.


Top
   
PostPosted: Fri Feb 15, 2019 8:44 am 
Offline

Joined: Wed Jul 11, 2018 10:44 am
Posts: 24
Well.. I have problem with comparing bytes. With BOOL variable works fine:
IF NOT new = Old THEN
Save := TRUE;
Old := New;
END_IF

With BOOL All good, Save goes TRUE but with BYTE not.. Nothing happens.. Any ideas?

Update: I used memcmp and memcpy. It works now.


Top
   
PostPosted: Thu Feb 21, 2019 4:25 am 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 304
The statement IF NOT xxx = yyy will only work for BOOLs. For other types simply use IF New <> Old. Use memcmp when you have complicated variables like structures or arrays - I am not sure this always works: IF structX = structY... (aka deep compare)

_________________
Scott Cunningham
KEB America, Inc.
www.kebblog.com
www.kebamerica.com


Top
   
PostPosted: Tue Feb 26, 2019 9:05 am 
Offline

Joined: Wed Jul 11, 2018 10:44 am
Posts: 24
Hello,

Yes I used memcmp and memcpy and it worked for comparing it. But.. How do I say I want to know if the difference is more then 5 for ex. MEMCMP has outputs just less, equal or more..

Just comparing:
Code:
IF MEMCMP( pBuf1 := ADR(Byte1) , pBuf2:= ADR(SaveByte1) , n:= 1) <> 0 THEN
      Trig_Byte1 := TRUE;
      MEMCPY(destAddr:= ADR (SaveByte1) , srcAddr:= ADR(Byte1) , n:= 1 );
END_IF


Update:
Smt like that: save input into pointer, save also saved value (new value with thich you compare to the pointer) that compare that..
Code:
VAR
Input_Byte1   AT%IB1    : BYTE; //our read variable
new_Byte1         : BYTE;//variable into which we save it
 
pBUf1   : POINTER TO UDINT; //pointer for our variable
pBuf2   : POINTER TO UDINT;//pointer to variable where we save readed variable
delta      : UDINT := 5;

END_VAR

pBuf1    := Input_Byte1;
pBuf2   :=new_Byte1

CASE nSTEP OF
0:
   MEMCPY(destAddr:=ADR (new_Byte1), srcAddr := ADR(Input_byte1),n:=1);
   nStep :=1;
   
1:
   IF ((pbuf1- pBuf2) > delta) OR ((pBuf1 - pbuf2 < (-delta)) THEN
   MEMCPY(destAddr:=ADR (new_Byte1), srcAddr := ADR(Input_byte1),n:=1); //save if delta
   END_IF
END_CASE
   
   


Top
   
PostPosted: Tue Feb 26, 2019 6:49 pm 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 304
Did you actually test this, because when you do this: pbuf1- pBuf2, you are asking the compiler to subtract pointer positions, not the value inside...

If you have UDINTs to compare:

Code:
Val1 : UDINT;
Val2 : UDINT;

IF ABS(Val2-Val1) > 5 THEN
   ...
END_IF


You need the Absolute value in case Val1 is bigger than Val2. Again, you can do math and less than/greater than/equal compares with any number data type.

_________________
Scott Cunningham
KEB America, Inc.
www.kebblog.com
www.kebamerica.com


Top
   
PostPosted: Wed Mar 06, 2019 4:05 pm 
Offline

Joined: Wed Jul 11, 2018 10:44 am
Posts: 24
I tested it with real inputs and looks like that my delta was approx equally big as the position difference. I look it one more time now a bit longer and yes you have right. THANK YOU!


Top
   
PostPosted: Wed May 01, 2019 9:50 am 
Offline

Joined: Wed Aug 05, 2015 1:26 pm
Posts: 17
I have the same issue with Modbus Master and writing to coils.
The GVL.CoilIn variable is mapped to a reading channel that is polling the server in "Cyclic" mode.
The GVL.CoilOut variable is mapped to the same coil in writing channel in "Rising edge" mode.

The code below is toggling the coil on the Modbus Server every time the variable GVL.Output0 is set to TRUE.
What I want is the Modbus coil to be set to 1 when the GVL.Output0 is TRUE and reset to 0 when then GVL.Output0 is FALSE.
I tried to take the falling edge of the GVL.Output0 to reset the coil to 0 but it doesn't work.

Any suggestions?

Code:
GVL.Input0 := GVL.CoilIn0;
R_TRIG_0(CLK:=GVL.Output0);

IF R_TRIG_0.Q THEN
   IF GVL.CoilIn0 THEN
      GVL.CoilOut0 := FALSE;
   ELSE
      GVL.CoilOut0 := TRUE;
   END_IF
END_IF


Top
   
PostPosted: Wed May 01, 2019 1:09 pm 
Offline

Joined: Wed Aug 05, 2015 1:26 pm
Posts: 17
Made it work for coils and now have to find a way so it works for holding registers as well.

Code:
GVL.Input0 := GVL.CoilIn;

Write := FALSE;

R_TRIG_0(CLK:=GVL.Output0);
F_TRIG_0(CLK:=GVL.Output0);

//Trigger for Modbus coil write
Write := R_TRIG_0.Q OR F_TRIG_0.Q;

IF Write THEN
   IF GVL.Input0 THEN
      GVL.CoilOut := FALSE;
   ELSE
      GVL.CoilOut := TRUE;
   END_IF
   Write := TRUE;
END_IF


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 12 posts ] 

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited