Programming avoiding GOTOs

This post follows earlier discussion in another category/topic: see Understanding IF statements)

I am struggling to grasp how to avoid line-number branching from IF-THEN statements as recommended by Maurice.

Rather than looking at just 3 or 4 lines of code covering a single decision, I would find it more instructive to consider a slightly larger section which involves a bigger series of inter-related decisions and actions.

This example concerns whether to start a central heating system in a block of apartments. Each apartment has an individual thermostat controlled zone valve. At mid-range outdoor temperatures the zone valves may be closed meaning no heat is required.

Plain language functional description:
A) Pre-conditions: Start heating only if all the following conditions are satisfied (collectively PRECONDS):

  • hot water priority flag not set by earlier program (HWPRIORT = off)
  • heating mode is selected (IN3 switch closed)
  • the heating circulator has no fault (IN4 switch closed)

B) Operation also based on Outdoor Air Temperature (IN1_OAT):

  • IN1_OAT > 16degC - Heat not required (HEATREQ flag off)
  • IN1_OAT < 8degC - Heat is required (HEATREQ flag on)
  • IN1_OAT between 8 to 16 deg - Heat required if circulating flow is above a
    defined value eg 5). Otherwise no heat required, circulator off

C) Minimum low test using circulator pump as follows: (SUBROUTINE)

  • start PUMP
  • allow 10sec for flow to stabilise
  • measure circulating flow IN2_ FLOW.
  • If flow IN2 < 5, TESTFAIL - HEATREQ flag off, stop PUMP
  • If flow IN2 > 5, Test passed - HEATREQ flag on (leave pump running)

D) If test failed and while preconditions remain satisfied, recheck every 15 minutes if OAT is still within 8-16deg range and, if so, repeat flow test (ie repeat C) above)

E) Commence heating: HEATREQ flag acted on by subsequent program

My original code effort used a number of “GOTOs” ie “skip to End” and also a jump-back to repeat the flow test which could potentially create an endless loop. I have reviewed this for many hours and have developed a revised code below.

Maybe I just dont have sufficient ability to restructure this the right/preferred way - I would greatly appreciate further review and assistance.

To allow for repeating the flow test, I put it into a subroutine - called once initially and repeated as required. I dont know if variables used by both main program and subroutine must be global or if local will work.

10 REM ** HEATING DECISION
15 REM ** HWPRIORT AND HEATREQ ARE GLOBAL VARIABLES
20 IF HWPRIORT AND IN3 AND IN4 THEN PRECONDS = 1 ELSE PRECONDS = 0
30 IF PRECONDS AND IN1_OAT > 16 THEN HEATREQ = 0
40 IF PRECONDS AND IN1_OAT <8 THEN HEATREQ = 1
50 IF PRECONDS AND IN1_OAT < 16 AND IN1_OAT > 8 THEN GOSUB 100
60 IF+ TESTFAIL THEN HEATREQ = 0 ELSE HEATREQ = 1
70 IF TIME-ON (TESTFAIL) > 0:15 THEN GOSUB 100
80 IF+ HEATREQ THEN START PUMP
90 REM ** HEATREQ FLAG USED BY NEXT PROGRAM
95 END

100 REM ** SUBROUTINE FOR FLOW TEST
105 TIMEFLAG = 0
110 TESTFAIL = 0 (initialise flags)
120 START PUMP
130 IF+ TIME-ON (PUMP) > 0:0:10 THEN TIMEFLAG
135 IF+ TIMEFLAG THEN MEASFLOW = IN2_FLOW
140 IF+ TIMEFLAG AND MEASFLOW < 5 THEN TESTFAIL = 1
145 IF+ TESTFAIL THEN STOP PUMP (if test passes, leave pump running)
150 RETURN

I’d create a variable called FLOWFLAG in line 50 and then do some statements inline further down to act on the flag. Just my two bits worth and helps the program flow from top to bottom with no jumps as Ive been preaching.

Line 130 doesnt appear to be doing anything.

The rest of the program looks fine, if a bit complex.

Thanks for your comments.

FLOWFLAG is to avoid the subroutine?

Line 130 is (trying) to introduce a 10s time delay between starting the pump (line 120) and measuring flow (line 135).

Have I made another mistake in 130? I see I did not leave a spaces next to parentheses.

Line 50: FLOWFLAG is to encapsulate the logic in line 50 into a single variable. Then you can use it elsewhere, more than once if you need it, elsewhere in your program. Also you can timers on it for other logic, place it on displays and build a trend log with it.

Line 130: You have an if+ statement with a then timeflag…its missing the action. It should be then do something with timeflag, or do some other action.

Yes, Line 130 should end with …THEN TIMEFLAG = 1