Delay OFF on 400 inputs (or more)

lauwerstim

Member
Join Date
Apr 2006
Location
Kontich
Posts
93
I have a rather dificult problem. I have a PLC with 400 inputs (maybe more later on), now I need every input to have an OFF delay (if its on for only 20ms, I need to need to see for a sec or so).
I've been trying to get this done with a function I've written but I'm doing something wrong. This is what I got so far:

Code:
FUNCTION_BLOCK FB 50
TITLE =
VERSION : 0.1


VAR_INPUT
  Puls_100ms : BOOL ;    
  DB_Inputs : POINTER ;    
  DB_Inputs_pulse : POINTER ;    
  Aantal_bits : INT ;    
END_VAR
VAR
  C_PF_100ms : BOOL ;    //Kopie voor flankdetectie 100ms puls
  PF_100ms : BOOL ;    //Flankdetectie 100ms
  I_Bit : DWORD ;    //Start adres voor inputs in DB
  Q_Bit : DWORD ;    //Start adres voor verlengde inputs in DB (waarnaartoe geschreven gaat worden)
  C_PF_I_bit : DWORD ;    //Adres voor kopiebits nodig voor flankdetectie van de inputs
  C_PF_I : ARRAY  [1 .. 400 ] OF //Flankdetectie van de inputs
  BOOL ;    
  T_bit : DWORD ;    //Adres voor timer
  T_pulse : ARRAY  [1 .. 400 ] OF //Timer
  INT ;    
END_VAR
VAR_TEMP
  I_DBNR : INT ;    //Db nummer voor de inputs
  Q_DBNR : INT ;    //DB nummer voor de verlengde inputs (waarnaartoe geschreven gaat worden)
  TBo : BOOL ;    
  TBo2 : BOOL ;    
  TBo3 : BOOL ;    
  TWo : WORD ;    
  TInt : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =Positieve flank 100ms puls



      A     #Puls_100ms; 
      FP    #C_PF_100ms; 
      =     #PF_100ms; 
NETWORK
TITLE =

      LAR1  P##DB_Inputs; 
      L     W [AR1,P#0.0]; 
      T     #I_DBNR; 
      L     D [AR1,P#2.0]; 
      T     #I_Bit; //Bit locatie van inputs in DB

      LAR1  P##DB_Inputs_pulse; 
      L     W [AR1,P#0.0]; 
      T     #Q_DBNR; 
      L     D [AR1,P#2.0]; 
      T     #Q_Bit; //Bit locatie van de inputs puls in DB

      LAR1  P#L 30.0; 
      T     #C_PF_I_bit; //Opslaan van de ingangen zodat ze lokaal gebruikt kunnen worden

      LAR1  P#L 84.0; 
      T     #T_bit; //Locatie van timer geheugen


      L     #Aantal_bits; 
NEXT: T     MW    20; 
      OPN   DB [#I_DBNR]; 
      L     #I_Bit; 
      LAR1  ; 
      A      [AR1,P#0.0]; 
      =     #TBo; //Binnen lezen van input


      L     #C_PF_I_bit; 
      LAR1  ; 
      A     #TBo; 
      FP     [AR1,P#0.0]; 
      =     #TBo3; //Positieve flank van Input (om timer te starten)



      L     #T_bit; 
      LAR1  ; 
      L     W [AR1,P#0.0]; 
      T     #TInt; 

      A     #TBo3; 
      JCN   INIT; 
      L     10; 
      T     #TInt; 
INIT: NOP   0; //Wanneer er een positieve flank is van de Input, wordt de teller geĂŻnitiallisseerd


      A(    ; 
      L     #TInt; 
      L     0; 
      >I    ; 
      )     ; 
      O     #TBo; 
      =     #TBo2; //Teller groter dan 0 of Inputs is hoog => verlengde puls hoog

      A     #PF_100ms; 
      JCN   TEL; 
      L     #TInt; 
      L     1; 
      -I    ; 
      T     #TInt; 
TEL:  NOP   0; //Wanneer er flank op de 100ms is, wordt er 1 van de teller afgetrokken

      L     #TInt; 
      L     0; 
      <=I   ; 
      JCN   SKIP; 
      L     0; 
      T     #TInt; //Teller kleiner of gelijk aan 0, vast op 0 zetten om geen negatieve getallen te krijgen
SKIP: NOP   0; 

      L     #T_bit; 
      LAR1  ; 
      L     #TInt; 
      T     W [AR1,P#0.0]; 




      OPN   DB [#Q_DBNR]; 
      L     #Q_Bit; 
      LAR1  ; 

      A     #TBo2; 
      =      [AR1,P#0.0]; 





NETWORK
TITLE =

      L     #I_Bit; 
      L     W#16#1; 
      +D    ; 
      T     #I_Bit; 

      L     #Q_Bit; 
      L     W#16#1; 
      +D    ; 
      T     #Q_Bit; 

      L     #C_PF_I_bit; 
      L     W#16#1; 
      +D    ; 
      T     #C_PF_I_bit; 

      L     #T_bit; 
      L     W#16#F; 
      +D    ; 
//      T     #T_bit


      L     MW    20; 
      LOOP  NEXT; 


END_FUNCTION_BLOCK
A already have every input copied to a DB (for use in the rest of the program) so I use that DB as input to my block and want to copy the pulse output to another DB (also an input on my block)

I have tested it, if I leave out the counter part, it works (it just copies over the inputs), but in the counter there's something wrong. I think I adress the integer for the timer wrong. The timer starts but not in de instance DB of the block, but in de DB with the inputs.

Really hope someone can help.
 
Corrected block below. I'll leave you to check the differences. Use the temp area for storing dword area pointers - you can then load them directly into AR1

Code:
FUNCTION_BLOCK FB 50
TITLE =
VERSION : 0.1

VAR_INPUT
  Puls_100ms : BOOL ; 
  DB_Inputs : POINTER ; 
  DB_Inputs_pulse : POINTER ; 
  Aantal_bits : INT ; 
END_VAR
VAR
  C_PF_100ms : BOOL ; //Kopie voor flankdetectie 100ms puls
  PF_100ms : BOOL ; //Flankdetectie 100ms
  C_PF_I : ARRAY  [1 .. 400 ] OF //Flankdetectie van de inputs
  BOOL ; 
  T_pulse : ARRAY  [1 .. 400 ] OF //Timer
  INT ; 
END_VAR
VAR_TEMP
  I_DBNR : INT ; //Db nummer voor de inputs
  Q_DBNR : INT ; //DB nummer voor de verlengde inputs (waarnaartoe geschreven gaat worden)
  TBo : BOOL ; 
  TBo2 : BOOL ; 
  TBo3 : BOOL ; 
  TWo : WORD ; 
  TInt : INT ; 
  I_Bit : DWORD ; //Start adres voor inputs in DB
  Q_Bit : DWORD ; //Start adres voor verlengde inputs in DB (waarnaartoe geschreven gaat worden)
  C_PF_I_bit : DWORD ; //Adres voor kopiebits nodig voor flankdetectie van de inputs
  T_bit : DWORD ; //Adres voor timer
END_VAR
BEGIN
NETWORK
TITLE =Positieve flank 100ms puls
      A     #Puls_100ms; 
      FP    #C_PF_100ms; 
      =     #PF_100ms; 
NETWORK
TITLE =
      LAR1  P##DB_Inputs; 
      L     W [AR1,P#0.0]; 
      T     #I_DBNR; 
      L     D [AR1,P#2.0]; 
      T     #I_Bit; //Bit locatie van inputs in DB
      LAR1  P##DB_Inputs_pulse; 
      L     W [AR1,P#0.0]; 
      T     #Q_DBNR; 
      L     D [AR1,P#2.0]; 
      T     #Q_Bit; //Bit locatie van de inputs puls in DB
      L     P##C_PF_I; 
      T     #C_PF_I_bit; //Opslaan van de ingangen zodat ze lokaal gebruikt kunnen worden
      L     P##T_pulse; 
      T     #T_bit; //Locatie van timer geheugen

      L     #Aantal_bits; 
NEXT: T     MW    20; 
      OPN   DB [#I_DBNR]; 
      LAR1  #I_Bit; 
      A      [AR1,P#0.0]; 
      =     #TBo; //Binnen lezen van input

      LAR1  #C_PF_I_bit; 
      A     #TBo; 
      FP     [AR1,P#0.0]; 
      =     #TBo3; //Positieve flank van Input (om timer te starten)
 
      LAR1  #T_bit; 
      L     W [AR1,P#0.0]; 
      T     #TInt; 
      A     #TBo3; 
      JCN   INIT; 
      L     10; 
      T     #TInt; 
INIT: NOP   0; //Wanneer er een positieve flank is van de Input, wordt de teller geĂŻnitiallisseerd

      A(    ; 
      L     #TInt; 
      L     0; 
      >I    ; 
      )     ; 
      O     #TBo; 
      =     #TBo2; //Teller groter dan 0 of Inputs is hoog => verlengde puls hoog
      A     #PF_100ms; 
      JCN   TEL; 
      L     #TInt; 
      L     1; 
      -I    ; 
      T     #TInt; 
TEL:  NOP   0; //Wanneer er flank op de 100ms is, wordt er 1 van de teller afgetrokken
      L     #TInt; 
      L     0; 
      <=I   ; 
      JCN   SKIP; 
      L     0; 
      T     #TInt; //Teller kleiner of gelijk aan 0, vast op 0 zetten om geen negatieve getallen te krijgen
SKIP: NOP   0; 
      LAR1  #T_bit; 
      L     #TInt; 
      T     W [AR1,P#0.0]; 
      OPN   DB [#Q_DBNR]; 
      LAR1  #Q_Bit; 
      A     #TBo2; 
      =      [AR1,P#0.0]; 
NETWORK
TITLE =
      LAR1  #I_Bit; 
      +AR1  P#0.1; 
      TAR1  #I_Bit; 
      LAR1  #Q_Bit; 
      +AR1  P#0.1; 
      TAR1  #Q_Bit; 
      LAR1  #C_PF_I_bit; 
      +AR1  P#0.1; 
      TAR1  #C_PF_I_bit; 
      LAR1  #T_bit; 
      +AR1  P#2.0; 
      TAR1  #T_bit; 
      L     MW    20; 
      LOOP  NEXT; 
END_FUNCTION_BLOCK
 
Last edited:
I assume the reason for doing this has to do with the scan time of the scada system that you are using.

Yep, exactly. Alarms come in fine (alarm_s, so gets processed by the plc) but the client wants to see a little green thing on the screen, he'll never need it because no one will be watching the screen non stop, but during testing it came up 🔨

Corrected block below. I'll leave you to check the differences. Use the temp area for storing dword area pointers - you can then load them directly into AR1

Code:
...

Thanks man, works like a charm.

Now I would like to understand it :oops:

Everything is clear (with a bit of use from the help), only thing I don't understand is :

Code:
  LAR1  P##DB_Inputs_pulse
      L     W [AR1,P#0.0]
      T     #Q_DBNR
      L     D [AR1,P#2.0]
      T     #Q_Bit                      //Bit locatie van de inputs puls in DB


      L     P##C_PF_I
      T     #C_PF_I_bit                 //Opslaan van de ingangen zodat ze lokaal gebruikt kunnen worden
Why once LAR1 P## and then L P## (and why a double # and not a single)

I normally never use indirect adressing because its a bit difficult to find errors (left click, go to is easy as hell) and its not as flexible. We have one big client where there are 10 people who have the right to change things and they never want the same, so we need to change the program a lot (bad contract, I know, not my resposability, else it would be different)
 
Before answering your questions, which CPU are you using ?

LAR1 P##DB_Inputs_pulse is used because the following instructions use AR1 to fetch the DB number and the area address.

L P##C_PF_I is used because I forgot/didn't need to change it after I put CF_PF_I in the temp area because the area pointer is simply being stored for use later.

The extra # is inserted by the editor to indicate it is a variable.
 
Last edited:
I'm using a 315-2DP/PN for this one (wich is a bit small and will be replaced by a 317-2DP/PN in the next project)

edit: OK, thanks. It's beginning to make sense to me :)
 
Last edited:

Similar Topics

Hey guys, Our Powerflex VFD table is really close to the keyence light curtain. We are using AB PLC it isnt a safety PLC. Our VFD is hardwired...
Replies
5
Views
2,294
Hello guys, I am currently looking through some examples of how timers work, but this ladder logic diagram gets me really confused. Once I:1/0 is...
Replies
2
Views
1,849
Can anyone help with this in Automation Direct Directsoft 6. I am trying to use an input X1 as a busy signal. When X1 comes on I want to have a...
Replies
5
Views
1,793
I browsed the forums a bit but couldn't find an exact response to this issue. In most cases people seemed to recommend using TON timers instead...
Replies
9
Views
3,007
I am an aspiring control systems engineer. I have a lab right now that we use plcs and programs to control what motors do. I am racking my brain...
Replies
16
Views
4,635
Back
Top Bottom