FYI, prior to HandlingTool v8.3, BGLogic could be used for state-machine logic control, but it was more cumbersome, since without JMP-LBL, you could not create code-blocks that would only run if certain conditions were met. Every line would be executed every scan.
Now, IF-THEN-ENDIF can be used in BGLogic, so that you can create cleaner-looking state-machines, for example, in BGLogic, since only the instructions within a specific IF-THEN-ENDIF code-block might be the only thing executed until a condition is met.
An IF-THEN-ENDIF block of code could be the only code executing in a BGLogic program when a state-number register is set to a specific state number. Then when the state-transition condition occurs, an IF statement that monitors the transition condition within the IF (R[nnn:MyState]=<State1Num>) THEN-ENDIF block would assign <State2Num> to R[nnn:MyState], and then the IF (R[nnn:MyState]=<State2Num>) THEN-ENDIF code-block would start executing.
example 'code':
<always-run code here for start-of-scan processing or some conditional reset code, etc. For example, a watchdog time counter:>
R[10:ScanTimeCounter]=R[10:ScanTimeCounter]+1;
! State 10, initialize ;
IF (R[10:ConveyorState]=10) THEN ;
<initialize registers or outputs> ;
! wait for the start/enable signal ;
IF (F[1:IndexConv]) THEN ;
<do cycle inits or wait for an index signal, or possibly kick off index from here>
R[10:ConveyorState]=1000 ;
ENDIF ;
ENDIF ;
! State 1000, begin index ;
IF (R[10:ConveyorState]=1000) THEN ;
GO[1:ConvSpeed]=1000 ;
DO[1:RunConvFwd]=ON ;
R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! Just one-shot & goto State 2000 ;
R[10:ConveyorState]=2000 ;
! (It would be nice to have a JMP-LBL to end of program right here to do some check-code every scan prior to a subsequent state after a transition, but there are other ways to do that too.) ;
! (in this case it executes the subsequent state immediately, which could be preferred.) ;
ENDIF ;
!State 2000, wait for slow zone ;
IF (R[10:ConveyorState]=2000) THEN ;
! Wait til slow-down sensor ;
! Transition condition... ;
IF (DI[2:SlowSensor]),
! set slow speed... ;
GO[1:ConvSpeed]=50 ;
! Reset watchdog... ;
R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! and go to State 3000 ;
R[10:ConveyorState]=3000 ;
ENDIF ;
! Check for Watchdog ;
IF ((R[12:WatchdogCount]+42)<R[10:ScanTimeCounter]) THEN ;
! Something bad may have happened, better handle it immediately ;
<stop conveyor, set alarm, set error register value, go back to State 10, etc.>
ENDIF ;
ENDIF ;
!State 3000, wait for stop signal ;
IF (R[10:ConveyorState]=3000) THEN ;
! Wait til stop sensor ;
! Transition condition... ;
IF (DI[3:StopSensor]),
! stop conveyor... ;
DO[1:RunConvFwd]=OFF ;
! set speed back to default... ;
GO[1:ConvSpeed]=1000 ;
! Reset watchdog... ;
R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! and go to State 4000 ;
R[10:ConveyorState]=4000 ;
ENDIF ;
! Check for Watchdog ;
IF ((R[12:WatchdogCount]+22)<R[10:ScanTimeCounter]) THEN ;
! Something bad may have happened, better handle it immediately ;
<stop conveyor, set alarm, set error register value, go back to State 10, etc.>
ENDIF ;
ENDIF ;
<State 4000, etc...>
<end-of-scan always-run code>
END ;
(Can someone confirm that JMP-LBL can still not be used in v8.30? I don't have access at the moment. It would still be useful in an IF-THEN-ENDIF state-machine program in BGLogic. I know for a fact I can put a JMP in a BGLogic program without a fault in v8.30, but I didn't realize it might not work, and the program in question would actually work fine without the JMP being functional. It's only purpose was to force only one code-block to run per scan, so at transition, it JMPs to the end, but if the JMP wasn't executing, it would only execute the subsequent state code-block 1 scan early.)
For older versions, you could use a lot of IF (<mixed logic>), <assignment> statements with the State register check in every IF statement:
! State 1000, begin index ;
IF (R[10:ConveyorState]=1000), GO[1:ConvSpeed]=1000 ;
IF (R[10:ConveyorState]=1000), DO[1:RunConvFwd]=ON ;
IF (R[10:ConveyorState]=1000), R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! Just one-shot & goto State 2000 ;
IF (R[10:ConveyorState]=1000), R[10:ConveyorState]=2000 ;
!State 2000, wait for slow zone ;
! Wait til slow-down sensor ;
IF ((R[10:ConveyorState]=2000) AND DI[2:SlowSensor]),R[10:ConveyorState]=2100 ;
! Check for Watchdog ;
! If Watchdog, go to an unique error state to handle the condition... ;
IF ((R[10:ConveyorState]=2000) AND ((R[12:WatchdogCount]+42)<R[10:ScanTimeCounter])),R[10:ConveyorState]=9200 ;
!State 2100, respond to reaching slow sensor ;
! 1st set slow speed... ;
IF (R[10:ConveyorState]=2100),GO[1:ConvSpeed]=50 ; ;
! Reset watchdog... ;
IF (R[10:ConveyorState]=2100),R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! and go to State 3000 ;
IF (R[10:ConveyorState]=2100),R[10:ConveyorState]=3000 ;
!State 3000, wait for stop signal ;
! Wait til stop sensor ;
IF ((R[10:ConveyorState]=3000) AND DI[3:StopSensor]),R[10:ConveyorState]=3100 ;
! Check for Watchdog ;
! If Watchdog, go to an unique error state to handle the condition... ;
IF ((R[10:ConveyorState]=3000) AND ((R[12:WatchdogCount]+22)<R[10:ScanTimeCounter])),R[10:ConveyorState]=9300 ;
!State 3100, respond to stop signal ;
! stop conveyor... ;
IF (R[10:ConveyorState]=3100),DO[1:RunConvFwd]=OFF ;
! set speed back to default... ;
IF (R[10:ConveyorState]=3100),GO[1:ConvSpeed]=1000 ;
! Reset watchdog... ;
IF (R[10:ConveyorState]=3100),R[12:WatchdogCount]=R[10:ScanTimeCounter] ;
! and go to State 4000 ;
IF (R[10:ConveyorState]=3100),R[10:ConveyorState]=4000 ;