ST (structured text) best way to toggle bit

Correct, can be for few scans if it cannot be accomplished in one. I have a reset bit that I'm trying to toggle from off to on then off. I do not want to leave it on. Similar to a one shot in ladder logic but I am not getting the same result with an OSRI in ST obviously.
 
Ultimately I am having problems with A-B's VHSC24 module. The present and stored counts are reset on power up to zero. So i'm trying to take the last count and store it in a program variable. then pull that value back into the module on power up.

Code:
// power cycle reset.

    if Local:2:I.PresentData = 0 then
        Local:2:C.Preset := current_count; // set preset value to last known value.
        storage.0 [:=] 1;
        if storage.0 then
            Local:2:O.CounterPreset [:=] 1; // reset value to preset.
        end_if;
    elsif Local:2:I.PresentData <> 0 then
        storage.1 [:=] 1;
        if storage.1 then
            Local:2:O.CounterPreset [:=] 0; // reset value to preset.
        end_if;
        Local:2:C.Preset := 1000;
        current_count := Local:2:I.PresentData; // store the count to a program variable.
    else
        // nothing.
    end_if;
 
I removed my post as you posted some code at the same time and my snippet didn't tie up with your code.

For ref it was as follows. ResetBit will be on for one scan after it has been made true.

Code:
ResetBit:=False;
if RestBitCondition then ResetBit:=True;
 
Last edited:
I'd be tempted to try it like this (basically using the PresentData value to trigger things):

Code:
// power cycle reset.

    if Local:2:I.PresentData = 0 then
        Local:2:C.Preset := current_count; // set preset value to last known value.
        Local:2:O.CounterPreset [:=] 1; // reset value to preset.
    elsif Local:2:I.PresentData <> 0 then
        Local:2:O.CounterPreset [:=] 0;
        current_count := Local:2:I.PresentData; // store the count to a program variable.
    else
        // nothing.
    end_if;

The idea being is that the first scan through the preset value would be updated. The second scan through the PresentData would be non-zero and would thus reset the CounterPreset bit.
 
I'd be tempted to try it like this (basically using the PresentData value to trigger things):

Code:
// power cycle reset.

    if Local:2:I.PresentData = 0 then
        Local:2:C.Preset := current_count; // set preset value to last known value.
        Local:2:O.CounterPreset [:=] 1; // reset value to preset.
    elsif Local:2:I.PresentData <> 0 then
        Local:2:O.CounterPreset [:=] 0;
        current_count := Local:2:I.PresentData; // store the count to a program variable.
    else
        // nothing.
    end_if;
The idea being is that the first scan through the preset value would be updated. The second scan through the PresentData would be non-zero and would thus reset the CounterPreset bit.

This would not allow the operator to set it seperately. as once in <> 0 condition it would be forced off no?
 
Tried again but this is getting it to boot up at 1000 instead of booting up at current count. It's almost as if the 'reset' is not turning off in time.

Code:
// begin program.
    // power cycle reset.
        if Local:2:I.PresentData = 0 then // first start after power cycle.    
            Local:2:C.Preset := current_count; // set preset value to last known value.
            Local:2:O.CounterPreset [:=] 1; // toggle reset.
        elsif Local:2:I.PresentData <> 0 then // normal operation.
            if not storage.0 then
                Local:2:O.CounterPreset := 0; // toggle reset.
                storage.0 [:=] 1; // set storage bit.
            end_if;
            if storage.0 then
                Local:2:C.Preset := 1000;
                current_count := Local:2:I.PresentData; // store the count to a program variable.
            end_if;
        else
            // nothing.
    end_if;
//end program.
 
Oh, I didn't catch that the operator would want to change things. In that case:

Code:
// power cycle reset.

    // placed outside separately but could easily be combined with lower if statement
    if (hmi_change_value_command) then
        current_count := hmi_new_value;
    end_if;

    if ((Local:2:I.PresentData = 0) OR (hmi_change_value_command)) then
        Local:2:C.Preset := current_count; // set preset value to last known value.
        Local:2:O.CounterPreset [:=] 1; // reset value to preset.
        hmi_change_value_command [:=] 0;  // turn the HMI command back off
    elsif Local:2:I.PresentData <> 0 then
        Local:2:O.CounterPreset [:=] 0;
        current_count := Local:2:I.PresentData; // store the count to a program variable.
    else
        // nothing.
    end_if;

This is assuming the HMI command is a set/latch (not momentary) command that is set on by the HMI on the rising edge of the button.
 
Perhaps take a look at the timing diagrams for the module. Perhaps it needs a little bit of time after power-up to figure itself out. You may wish to just put the whole thing on a delay timer so it doesn't fire until a little bit after powerup (assuming you don't need to have it operational immediately).
 
For example. I have a bench test setup:

System running, i pulsed the prox's 4 times (counts on up and down so reading 8)

1.jpg

after cycling power

2.jpg

you can see the counts on the side reset from 1008 back to 1000.
 
Checking to see if an admin can rename this post, got a little off topic.

As per my original post, apparently I'm tired and didn't realize I could just set my bit to the output bit of the oneshot.

The rest of my issue is pending.
 
Last edited:
Edge in ST

Hi,

I write edges allways like this:

Code:
Edge:= Input AND NOT MemorisedBit;


' Your program...


MemorisedBit:= Input;



Kind regards,
G
 
I can't think of a single platform that doesn't support either EDGEPOS() or R_TRIG(). Edgepos is an inline function, so you would use it like:

IF(EDGEPOS(MyBit)) THEN
//Code
END_IF

However, EDGEPOS cannot be used in loops, so always use R_TRIG(), which is a function block in a loop:

MyRTRIG.CLK:= MyBit;
MyRTRIG();
IF(MyRTRIG.Q) THEN
//Code
END_IF

Without using those functions, you do what Combo does:
IF(MyBit AND NOT(zMyBit)) THEN
//Code
END_IF
zMyBit:= MyBit;

EDIT: There are matching functions for the falling edge (F_TRIG() and EDGENEG()) and either edge (RF_TRIG() and EDGE())
 
Last edited:

Similar Topics

I have an expression in a structured text routine of a Logix controller that looks more or less like the following: ResultInteger := Integer1 *...
Replies
13
Views
369
Good evening. I display the step number of a SFC on a display. Sometimes, on a trip, it goes quickly through many steps and I need to prove to...
Replies
1
Views
106
I am trying to set up a piece of equipment with a Horner HE-X4R. I'd like to use structured text and so far I'm just trying to get a basic On/off...
Replies
0
Views
63
Good morning. I'm doing a rehab and I need to recycle some part of the old code that won't change and that I need. This is a calculation that...
Replies
22
Views
1,333
I'm writing some structured text that's handling a data structure that comes from a PC. The PC structure is in the "new" LREAL 64-bit floating...
Replies
3
Views
478
Back
Top Bottom