0

This should be a nice question for different approaches.I am very new, so pardon my simple question.

Say I have 6 LEDs.

LED1 AT %Q* : BOOL;
LED2 AT %Q* : BOOL;
LED3 AT %Q* : BOOL;
LED4 AT %Q* : BOOL;
LED5 AT %Q* : BOOL;
LED6 AT %Q* : BOOL;

My goal is to be able to toggle 3 LEDS (which ever I would like). therefore, if you press a specific button and toggle it ON, it will do so with the respective LED:

LED[i] := button[i]; 

That is easy. Now say I have 3 that are currently ON.

I would like to be able to press a Unique "Pulse" button and Pulse all 3 Currently Lit LEDs simultaneously for 3 pulse cycles. each 1 second long. ex. ON --> OFF --> ON --> OFF --> ON --> OFF

What would be the best way in Structured Text to be able to know which ones are currently ON, and if so, Pulse the currently ON LEDS 3 times using Timers.

Thanks!

2 Answers2

0

You need to utilize timers in TwinCAT, TON and/or TOF. You also need to detect when the buttons have been pressed, to reset the timers. Once the button has been pressed for a LED, you restart both timers and also start the on-timer.

A quick and dirty probably not 100% correct 2-min solution (not in any way elegant, and which can be significantly simplified) goes something along this: In here I only use one of the buttons. Put all of this inside a for-loop to get what you want.

Function-block header:

bLED : ARRAY [1..6] OF BOOL ;
bLEDButton : ARRAY [1..6] OF BOOL;
tTimersOn : ARRAY [1..6] OF TON := [(PT := T#1S)];
tTimersOff : ARRAY [1..6] OF TON := [(PT := T#1S)];
fbLEDButtonTimerReset : ARRAY [1..6] OF R_TRIG;
fbLEDOnReset : ARRAY [1..6] OF R_TRIG;
fbLEDOffReset : ARRAY [1..6] OF R_TRIG;

Function block body

fbLEDButtonTimerReset[1](CLK := bLEDButton[1]); 
IF fbLEDButtonTimerReset[1].Q THEN
    tTimersOn[1](IN := FALSE);
    tTimersOn[1].IN := TRUE;
    tTimersOff[1](IN := FALSE);
END_IF

IF bLEDButton[1] THEN
    tTimersOn[1]();
    tTimersOff[1]();
    fbLEDOffReset[1](CLK := tTimersOff[1].Q);
    IF fbLEDOffReset[1].Q THEN
        tTimersOn[1](IN := FALSE);
        tTimersOn[1].IN := TRUE;
    END_IF
    fbLEDOnReset[1](CLK := tTimersOn[1].Q);
    IF fbLEDOnReset[1].Q THEN
        tTimersOff[1](IN := FALSE);
        tTimersOff[1].IN := TRUE;
    END_IF

    bLED[1] := NOT tTimersOn[1].Q;
END_IF
Jakob
  • 1,288
  • 7
  • 13
  • Thank you @Jakob for putting in the time! How come we need to keep track of when they were pressed? Say if I pressed 3 buttons = meaning 3 lights would come on. Then 30 min later I wanted to pulse the 3 currently lit LEDs, how come we are timing them? – CuriousEngineer Feb 04 '18 at 02:49
  • Hi @CuriousEngineer! The keeping track of the push-buttons is just to reset the timers for when the lights are lit and off. Say for instance you disable the switching in the middle (0.5s) of an ON-light. If you push the button again you just want to make sure that the timers are reset and a new 1s-ON/1s-OFF/1s-ON/1s-OFF starts again. – Jakob Feb 05 '18 at 20:16
0

Let me offer my 5c. I know that might be late, but I think many will find my code usefull.

PROGRAM PLC_PRG
VAR
    xLed1 : ARRAY [1..6] OF BOOL; (* Array of LEDs *)
    xLed1M : ARRAY [1..6] OF BOOL; (* Array of LEDs to remember what to blink*)
    xLedButtons: ARRAY [1..6] OF BOOL; (* Array of buttons to toggle LED state *)
    xLedButtonsM: ARRAY [1..6] OF BOOL; (* Array of button press memmories to use pulse on rised edge of button press *)
    i:INT;
    xButtonBlink: BOOL; (* Button to press to start blinking *)
    xButtonBlinkM: BOOL; (* Memory of the button state to detect raising edge *)
    xBlinkLock: BOOL; (* Lock programm during blinking *)
    xBlinkLockM: BOOL; (* Memory of the lock to detect raising and falling edge *)
    fbTP1:TP; (* timer to enable lock for 6 seconds *)
    fbBLINK1: BLINK;
END_VAR
    (* Start lock timer of raising edge of blink button *)
    fbTP1(IN := xButtonBlink AND NOT xButtonBlinkM, PT := T#6s);
    xButtonBlinkM := xButtonBlink;

    xBlinkLock := fbTP1.Q;

    (* If locked start blinking *)
    IF xBlinkLock THEN
        (* If raised edge, of first cycle of blinking save LED array *)
        IF NOT xBlinkLockM THEN
            xLed1M := xLed1;
        END_IF
        fbBLINK1(ENABLE := TRUE, TIMEHIGH  :=  T#1s,  TIMELOW  :=  T#1s);
        FOR i :=1 TO 6 DO
            IF xLed1M[i] THEN
                xLed1[i] := fbBLINK1.OUT;
            END_IF
        END_FOR
    ELSE
        (* If falling edge of lock, restore LED array and reset blink FB *)
        IF xBlinkLockM THEN
            xLed1 := xLed1M;
            fbBLINK1(ENABLE := FALSE);
        END_IF

        (* Track button clicks and toogle state of led *)
        FOR i := 1 TO 6 DO
            IF xLedButtons[i] AND NOT xLedButtonsM[i] THEN
                xLed1[i] := NOT xLed1[i];
            END_IF;
            xLedButtonsM[i] := xLedButtons[i];
        END_FOR
    END_IF
    xBlinkLockM := xBlinkLock;
END_PROGRAMM
Sergey Romanov
  • 2,949
  • 4
  • 23
  • 38