Simple pulser ST Question for beginner

DPIreland

Member
Join Date
Mar 2024
Location
limerick
Posts
3
Hi all,

Writng a FB in ST on Beckhoff TC for a pulser which turns on and off on a cycle, is paused by turning bControlInput to FALSE, but resumes state where it was once unpaused. Given code below does not carry out the resume state function, can anyone give me a hand?

FUNCTION_BLOCK FB_Pulser
VAR_INPUT
bControlInput :BOOL;
tOffTime : TIME;
tOnTime : TIME;
END_VAR
VAR_OUTPUT
bOutput : BOOL;
END_VAR
VAR
fbOffTimer : TON;
fbOnTimer : TON;
f_trig : F_TRIG;
r_trig : R_TRIG;
bOutputPaused : BOOL;

END_VAR


logic:

// Store output state when control input goes off
f_trig(CLK:=bControlInput);
IF f_trig.Q THEN
bOutputPaused := bOutput; ///expect: bOutputPaused true, bOutput false
END_IF


// Resume output state when control input goes on
r_trig(CLK:=bControlInput);
IF r_trig.Q THEN
bOutput := bOutputPaused;
END_IF


// Main control logic
IF bControlInput THEN
IF NOT bOutput THEN
// If output is off, start the off timer
fbOffTimer(IN:=TRUE, PT:=tOffTime);

// When the off timer completes, turn on the output
IF fbOffTimer.Q THEN
fbOffTimer(IN:=FALSE);
bOutput := TRUE;
END_IF
ELSE
// If output is on, start the on timer
fbOnTimer(IN:=TRUE, PT:=tOnTime);

// When the on timer completes, turn off the output
IF fbOnTimer.Q THEN
fbOnTimer(IN:=FALSE);
bOutput := FALSE;
END_IF
END_IF
ELSE
// If control input is off, ensure the output is off
bOutput := FALSE;
END_IF
 
Hi all,

Writng a FB in ST on Beckhoff TC for a pulser which turns on and off on a cycle, is paused by turning bControlInput to FALSE, but resumes state where it was once unpaused. Given code below does not carry out the resume state function, can anyone give me a hand?
Code:
FUNCTION_BLOCK FB_Pulser
VAR_INPUT
    bControlInput :BOOL;
    tOffTime : TIME;
    tOnTime : TIME;
END_VAR
VAR_OUTPUT
    bOutput : BOOL;
END_VAR
VAR
    fbOffTimer : TON;
    fbOnTimer : TON;
    f_trig : F_TRIG;
    r_trig : R_TRIG;
    bOutputPaused : BOOL;
   
END_VAR


logic:

// Store output state when control input goes off
f_trig(CLK:=bControlInput);
IF f_trig.Q THEN
    bOutputPaused := bOutput;  ///expect: bOutputPaused true, bOutput false
END_IF


// Resume output state when control input goes on
r_trig(CLK:=bControlInput);
IF r_trig.Q THEN
    bOutput := bOutputPaused;
END_IF


// Main control logic
IF bControlInput THEN
    IF NOT bOutput THEN
        // If output is off, start the off timer
        fbOffTimer(IN:=TRUE, PT:=tOffTime);
       
        // When the off timer completes, turn on the output
        IF fbOffTimer.Q THEN
            fbOffTimer(IN:=FALSE);
            bOutput := TRUE;
        END_IF
    ELSE
        // If output is on, start the on timer
        fbOnTimer(IN:=TRUE, PT:=tOnTime);
       
        // When the on timer completes, turn off the output
        IF fbOnTimer.Q THEN
            fbOnTimer(IN:=FALSE);
            bOutput := FALSE;
        END_IF
    END_IF
ELSE
    // If control input is off, ensure the output is off
    bOutput := FALSE;
END_IF
Code:
f_trig(CLK:=not bControlInput);

?

Comments
  • Those TONs will not be paused when the value of bCntrolInput is 0 - they will either continue to time, or be reset (it's easier to know in Ladder than ST); have you looked at RTO timers?
  • Speaking of TONs, it is better to have a single call to the TON, not separate calls, one with IN:=True and one with IN:=False. The trick is to use something clever, i.e. a variable or expression, for the TON' sIN parameter
  • having the tOnTime and tOffTime as input parameters seems risky - what happens when a timer's PT parameter's argument is changed while that timer is running? What if that timer is expired.
  • Personally, I would do this with one timer, but since this looks like a homework assignment you are probably expected to use the canonical "flasher" circuit pattern with cascaded timers.
    • Get your code working first, so you know what the problem is (we learn more from mistakes).
    • Then start over here.
      • Yes, that is LAD, but it is neither overly complex, nor an optional skill, to port logic between LAD and ST.
    • Then get that flasher pattern working with TONs in ST but without the pause
    • Then convert to RTO instructions (there need to be explicit RESet instruction)
    • Then add the pause.
    • The end result should be far simpler than what you have at this point.
 
Thanks for your detailed advice, much appreciated.
1)Agree about using tOffTime and tOnTime as inputs, should probably change them to global constants?
2) No built in RTO FB in beckhoff so had to make do with TONs
I have now built the project in LD
1711616581695.png

And it works as required. Any critiquing on how I could make it simpler or better in anyway would be appreciated. Ideally trying to use less TONs.
 
And it works as required. Any critiquing on how I could make it simpler or better in anyway would be appreciated. Ideally trying to use less TONs.
Hi and welcome to the forum.

Perhaps the screenshot below may give you some idea of possible simplification. If you used edge detection, you would not need R_TRIG, which is needed for ST.

1711624462624.png
 
Dunno if this is simpler, but it essentially implements an RTO, which makes assigning the value of bOutput much cleaner.

Caveats
  • This assumes the mean scan cycle time over any on or off duration is more or less consistent
  • It vouldn't hoyt to add some initialization
  • The on and off durations, in ms, can be modified on the fly vidout breaking anyting
  • There is minor roundoff error in using REALs for the calbirate, which could be lessened by using LREALs
  • Even better, running the logic in this MAIN routine in a timed interrupt routine, with a known interval (F8:2) between scans, would eliminate the calibration routine.
00.png

01.png
 
Thanks for all replies and inputs. Managed to complete my own LD version with one timer:
1711707825862.png
And the corresponding (or similar) ST:

1711708160545.png

FUNCTION_BLOCK FB_Pulser
VAR_INPUT
bControlInput :BOOL;
tOffTime : TIME;
tOnTime : TIME;
END_VAR
VAR_OUTPUT
bOutput : BOOL;
END_VAR
VAR
f_trig : F_TRIG;
fbTimerRem : TON;
bPaused: BOOL; //For first run after a pause
bOutputPaused: BOOL;
tRem: TIME;
tCycle: TIME;
tRemOff: TIME;
bTimerTrig: BOOL;
END_VAR

--------------

//// Find tCycle

tCycle := tOnTime + tOffTime;

//// Storage of restart positions at pause

f_trig(CLK:=bControlInput);
IF f_trig.Q THEN
tRemOff:=T#0S;

tRem:= tCycle - fbTimerRem.ET;
bPaused:= TRUE;

IF tOffTime > fbTimerRem.ET THEN
tRemOff := tOffTime - fbTimerRem.ET;
END_IF

END_IF

//// Normal timings restored after 1st cycle

IF NOT bPaused THEN
tRem:=tCycle;
tRemOff:=tOffTime;
END_IF

///// Timer logic
bTimerTrig := bControlInput AND NOT fbTimerRem.Q;
fbTimerRem(IN:=bTimerTrig,PT:=tRem);

IF bTimerTrig THEN

IF fbTimerRem.ET > tRemOff THEN
bOutput:=TRUE;
ELSE
bOutput:=FALSE;
END_IF

END_IF

//// Resetting bPaused after 1st run after a pause

IF fbTimerRem.Q THEN
bPaused:= FALSE;
END_IF

//// Paused behaviour

IF NOT bControlInput THEN
bOutput := FALSE;
END_IF
 

Similar Topics

Hello again..trying something on an existing poorly written program and just wanted to double check something system is an A-B MicroLogix 1200 In...
Replies
5
Views
169
I'm trying to build my Classic Step 7 programming skills this weekend. I get stuck on little things that are not covered in YouTube tutorials. I'm...
Replies
7
Views
318
I have a program that does a 7 second "scan" sensor calibration routine whenever a setting (setting is called assistance level or "AL" and ranges...
Replies
3
Views
212
Hi all, I have a simple question that I have overcomplicated and gotten stuck on. I have a variable, we can call it "light" that I need to stay...
Replies
4
Views
316
Hi all! I am using unitronics Unistream plc, controlling two axis X and Y of polishing machine. Control is very simple as I have movement in each...
Replies
34
Views
3,957
Back
Top Bottom