News:

  • August 01, 2026, 07:00:57 AM

Login with username, password and session length

Author Topic: Implementing One-Shot Type Command In Subroutine  (Read 7255 times)

RBPLC

  • Hero Member
  • *****
  • Posts: 586
Implementing One-Shot Type Command In Subroutine
« on: October 18, 2022, 09:24:08 AM »
As title suggests, I would ideally like to implement a one-shot command inside of a subroutine. Is there any way to implement one-shot type logic within a subroutine?

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3838
    • Host Engineering
Re: Implementing One-Shot Type Command In Subroutine
« Reply #1 on: October 18, 2022, 10:47:14 AM »
The concept of a previous-scan-this-scan edge detection is not applicable in a Subroutine code block.  A subroutine is basically like a math function call, where you CALL that logic in-line with the code.

So a subroutine is meant for re-use, where you have 3 different places where you CALL the subroutine DoABC

// some rungs
CALL DoABC 123 =>V100

// some more rungs
CALL DoABC 456 =>V100

// some other rungs
CALL DoABC 789 => V100

If you want edge detection within DoABC, you would need to manually pass in the two bits representing that specific call's previous scan's bit state and the current scan's bit state.

In the above example, say C0/C1 represent previous/current for the first CALL, C2/C3 previous/current for the 2nd CALL, C4/C5 previous/current for the 3rd call:

// ABC now has 3 parameters, a numeric, the previous scan's bit state, the current scan's bit state; the subroutine instance parameters for those are V100, C100, and C101, respectively

CALL DoABC 123 =>V100, C0 => C100, C1 =>C101
// update previous scan's bit state with current scan's bit state for NEXT scan
STR C1
OUT C0

// similar w/2nd DoABC CALL instance
CALL DoABC 456 => V100 C2 => C100, C3 => C101
// update previous scan's bit state with current scan's bit state for NEXT scan
STR C3
OUT C2

// similar w 3rd DoABC CALL instance
CALL DoABC 789 => V100, C4 => C100, C5 => C101
// update previous scan's bit state with current scan's bit state for NEXT scan
STR C5
OUT C4

Then inside DoABC code block logic, the common logic utilizes V100, C100 and C101 that are "passed by value" by the CALL, where C100 is the "previous scan" state, and C101 is the "current scan" state.

The "edge detection" logic inside DoABC is simply a NC C100 (previous scan state was OFF) and NO C101 (current scan state is ON)

Code: [Select]
C100  C101
-]/[---] [-----------------output boxes to do on edge event

Not sure what you want to do in the Output Boxes, but those may need to be parameterized also???

Another way to do parameterization is to use Array of a UDT.

For example, name UDT struct for ABC subroutine ABCStruct and name the block of 100 ABCStruct's ABCParms), then just pass in the index to the subroutine (say V100, so CALL 42=>V100.

The logic inside DoABC uses ABCParms[V100].InParmA and ABCParms[V100].OutParmZ.

So you could do 100 CALL's inside a FOR/NEXT V100 loop that is iterating V100 and one CALL DoABC w/no parmeters:
FOR V100 0 99
CALL DoABC
NEXT

Then DoABC has logic w/array references any/all the fields within its code, e.g. ABCParms[V100].whateverfieldyouneed

Two of those ABCStruct fields could be PrevScanBit and CurrentScanBit, so then tweak the FOR/NEXT loop to take care of that:

FOR V100 0 99

CALL DoABC
// update @V100's .PrevScanBit with .CurrentScanBit state for the "next" PLC LOGIC scan
STR ABCParms[V100].CurrentScanBit
OUT ABCParms[V100].PrevScanBit

NEXT

Then inside DoABC you detect the edge condition with this simple rung:
Code: [Select]
// increment .EventCounter member whenever we detect the edge
 ABCParms[V100].PrevScanBit  ABCParms[V100].CurrentScanBit
-------------]/[-------------------------] [---------------------------------------INC ABCParms[V100].EventCounter

This way you literally have 100 instances of INDEPENDENT edge detection!

Make sure the CALLer's .TimeSlice is 65535 (never yield) to iterate all 100 steps of the FOR/NEXT loop in a SINGLE PLC scan.  For true scan-to-scan edge detection to work, you don't want the CALLer's code block to "task out".

RBPLC

  • Hero Member
  • *****
  • Posts: 586
Re: Implementing One-Shot Type Command In Subroutine
« Reply #2 on: October 19, 2022, 09:50:47 AM »
I had the general idea but for some reason I couldn't come up with:

C100  C101
-]/[---] [-----------------output boxes to do on edge event

I'm using an UDT array to store status bits as suggested later in the post. Thanks for the help, seems to be up and running now.

franji1

  • Bit Weenie
  • Host Moderator
  • Hero Member
  • *****
  • Posts: 3838
    • Host Engineering
Re: Implementing One-Shot Type Command In Subroutine
« Reply #3 on: October 19, 2022, 10:18:35 AM »
I'm using an UDT array to store status bits as suggested later in the post. Thanks for the help, seems to be up and running now.

You know what they say, like minds think alike  ;-)