Conditional commands.

russbow

Senior Member
I am using this bit of code to call an external eeprom write routine.

Code:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Note HourHi=b11,HourLo=b12,MinHi=b7,MinLo=b8

check_it:

	if b7=2 or b7=5 and b8=9 Then
  		If flag = 0 Then gosub count_it
    		flag = 1
  	
		Else	flag = 0
	End If
	
return

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
expecting to store data at 29 minutes and 59 minutes past the hour.

In essence it works, but looking at the eeprom dump it is timed at 20 minutes past, and not 29.
The 59 minute seems ok.

Next Address is 224

Start Date 20/12

Time Low High


19:20 0 0
19:59 17 18
20:20 18 20
20:59 18 20
21:20 18 19
21:59 17 18
22:20 17 18
22:59 15 18
23:20 14 15
23:23 14 14
23:59 12 14
00:20 11 12
00:59 10 11
01:20 10 10
I can only guess that the reason is buried somewhere somewhere in the complete code.

Code:
'08m2 Min/Max with reset and log
'Working 05/12/11
'modified and checked 09/12/11

#picaxe08M2

#No_Data

init:
symbol MINTEMP = b1
symbol MAXTEMP = b2
symbol NOWTEMP = b4

symbol LCD= c.0
symbol DEG= c.4
symbol WIPEIT= pinc.3
Symbol flag=w13
Symbol address=w12
let address=8
serout LCD,N2400,(254,1,254,1) 'clear screen
pause 200

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
gosub wipe

hi2csetup i2cmaster, %10100000, i2cslow, i2cword	'set up eeprom

	hi2cout 0,(address)
	pause 100
	hi2cout 1,(b9,b10,b2,b3)
	pause 100
	


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Main:

'if WIPEIT=1 then gosub wipe    ' Reset values to zero

gosub timeit  'Get current time

gosub check_it

gosub disp1

gosub get_temp

gosub check	'check for neg values & display

goto main   ' Doit again

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

get_temp:

	ReadTemp DEG, NOWTEMP Read 0, MINTEMP
 	Read 1, MAXTEMP
 	Read 2,b5:Read 3,b6:read 4,b7
 	Read 5,b8:read 6,b9:read 7,b10
 
 If MINTEMP = 0 And MAXTEMP = 0 Then
 	MINTEMP = 255
 End If
 
 If NOWTEMP < MINTEMP Then
 	MINTEMP = NOWTEMP
 	Write 0, MINTEMP
 End If
 
 If NOWTEMP > MAXTEMP Then
 	MAXTEMP = NOWTEMP
 	Write 1, MAXTEMP
 End If 

return
 
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

timeit:

i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0,(b0,b1,b2,b3,b4,b5,b6)
	
	pause 100

	b11=b2/16	 'hour MSD
	b12=b2 & $0F 'hour LSD
	b7=b1/16	 'min  MSD
	b8=b1 & $0F  'min  LSD
	b9=b4/16	 'day MSD
	b10=b4 & $0F 'day LSD
	b2=b5/16
	b3=b5 & $0F
	b0=b6/16:b4=b6 & $0F
	
return

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

check:

	if NOWTEMP > 127 then neg2
	serout LCD,N2400,(254,192,"Temp ",#NOWTEMP,$df,"C ")
	pause 5000
	serout LCD,N2400,(254,128,"                ")
goto checkmin

neg2:
	let NOWTEMP = NOWTEMP - 128 &#8216; adjust neg value
	serout LCD,N2400,(254,128,"Temp -",#NOWTEMP,$df)
 
checkmin:

	if MINTEMP > 127 then neg3  'test negative
	serout LCD,N2400,(254,128,"Lo ",#MINTEMP,$df,"   ")
goto checkmax

neg3:
	let MINTEMP = MINTEMP - 128  'adjust neg value
	serout LCD,N2400,(254,128,"Lo -",#MINTEMP,$df)

checkmax:

	if MAXTEMP > 127 then neg4  'test for negative
	serout LCD,N2400,(254,136,"Hi ",#MAXTEMP,$df)
goto fini

neg4:
	let MAXTEMP = MAXTEMP - 128 ' adjust neg value
	serout LCD,N2400,(254,136,"Hi -",#MAXTEMP,$df)

fini:

	serout LCD,N2400,(254,192,"R/S ",#b11,#b12,":",#b7,#b8," Z= ",#address)
	pause 5000
	serout LCD,N2400,(254,1,254,1)
return

''''''''''''''''''''''''''''''''''''''''''''''''''''''

wipe:
	gosub timeit
	write 0,0:write 1,0
	write 2,b11:write 3,b12:write 4,b7
	write 5,b8:write 6,b0:write 7,b4

return

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

disp1:

serout LCD,N2400,(254,128,#b11,#b12,":",#b7,#b8,"   ") 'H/M

	serout LCD,N2400,(254,136,#b9,#b10,"/",#b2,#b3,"/",#b0,#b4)
	

return

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

count_it:


	Read 0, MINTEMP:pause 100
	Read 1, MAXTEMP:pause 100

	hi2csetup i2cmaster, %10100000, i2cslow, i2cword	'set up eeprom

	hi2cin 0,(address)	'get next address from location zero
	pause 200


	hi2cout address,(b11,b12,b7,b8,mintemp,maxtemp)	' HH MM
	
	pause 200

	let address=address+8
	pause 200
	

	
	hi2cout 0, (address)	'and write it to location zero
	
	pause 200	

	gosub wipe
	
	
return

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Note HourHi=b11,HourLo=b12,MinHi=b7,MinLo=b8

check_it:

	if b7=2 or b7=5 and b8=9 Then
  		If flag = 0 Then gosub count_it
    		flag = 1
  	
		Else	flag = 0
	End If
	
return

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Any ideas please
 
Last edited:

russbow

Senior Member
So

Code:
'Note HourHi=b11,HourLo=b12,MinHi=b7,MinLo=b8

check_it:

	if b11=2 and b12=3 and b7=5 and b8=9 Then
  		If flag = 0 Then gosub count_it
    		flag = 1
  	
		Else	flag = 0
	End If
	
return
should be ok for a 23:59 daily write ?
 

lewisg

Senior Member
My first thought is you need to make your code easier to read by using symbols. You start off fine with three variables then some pin assignments. Then you start to go off track with some more variable assignments. Once you get to the first sub you are back to the dark side of directly calling PICAXE byte vars by bX names.

It's really no big deal, more a matter of personal preference to only use symbols in your code. A program will work either way.

However I see b1,b2,b4 being used in at least two places, symbols for xxxTEMP and timeit:. Unless I don't understand your program this sort of thing usually results in unreliable operation.

So:

Hippy's rule number one, simplify your program and be sure the smallest possible parts work before adding complexity.

Rule number two, USE SYMBOLS for all variables in code blocks. Multiple symbol names can be assigned to the same variable or pin and they have no overhead so there is little reason not to use them. The HUGE advantage is (just like "option explicit" in other BASIC dialects) assistance from the editor in NOT screwing up. Properly listed symbol blocks will show any conflicts in your variable usage. And you code will be easier to read.

Here is a symbol section from a fairly big project of mine:
Code:
#picaxe20X2

'refrigerator vars
symbol Rtemp  = b0
symbol Rmin   = b1
symbol Rmax   = b2
symbol Rstate = b3
symbol Ron    = w2
symbol Roff   = w3
symbol tFD    = b14     'temporary location for freezer duty cycle calc
    
'freezer vars
symbol Ftemp  = b8
symbol Fmin   = b9
symbol Fmax   = b10
symbol Fstate = b11
symbol Fon    = w6
symbol Foff   = w7
symbol tRD    = b14     'temporary location for refrigerator duty cycle calc
    
'poke peek memory locations
'poke 30, time      active - do not use!
'peek 40, Roff      active - do not use!    
'poke 50, time      active - do not use!
'peek 60, Foff      active - do not use!
    
'poke 70, Rtemp     temp - hold val while calc for display
'poke 80, Rmin      temp - hold val while calc for display
'poke 90, Rmax      temp - hold val while calc for display

'poke 70, Ftemp     temp - hold val while calc for display
'poke 80, Fmin      temp - hold val while calc for display
'poke 90, Fmax      temp - hold val while calc for display
   
'poke 70, Fon       temp - "borrow" freezer var to calc refrigerator duty cycle
'poke 80, Foff      temp - "borrow" freezer var to calc refrigerator duty cycle
'poke 90, Ron       temp - "borrow" refrigerator var to calc freezer duty cycle
'poke 100,Roff      temp - "borrow" refrigerator var to calc freezer duty cycle
    
'display vars
symbol Tsign = b16      'current temp
symbol Ttens = b17
symbol Tones = b18
symbol Nsign = b19      'min temp
symbol Ntens = b20
symbol Nones = b21
symbol Xsign = b22      'max temp
symbol Xtens = b23
symbol Xones = b24
symbol Dxxxx = b25      'duty cycle, xxxx not displayed
symbol Dtens = b26
symbol Dones = b27

'DS1307 variables
symbol secs    = b26
symbol mins    = b27
symbol hour    = b38
symbol day     = b39    'day of week  1-7
symbol date    = b40    'day of month 1-31
symbol month   = b41
symbol year    = b42
symbol control = b43

'DS1307 display variables
symbol yr10    = b44
symbol yr01    = b45
symbol mo10    = b46
symbol mo01    = b47
symbol dt10    = b48
symbol dt01    = b49
symbol hr10    = b50
symbol hr01    = b51
symbol mn10    = b52
symbol mn01    = b53
symbol sc10    = b54
symbol sc01    = b55
    
'input pins
symbol RSense =  C.0        'DS18B20 in refigerator
symbol FSense =  C.1        'DS18B20 in freezer
symbol CabTemp = C.2        'DS18B20 in refigerator/freezer cabnet
symbol RmTemp  = C.3        'DS18B20 in room
symbol ECTemp  = C.4        'DS18B20 engine compartment
symbol EnTemp  = C.5        'DS18B20 on enfgine
symbol ACVolt  = C.6        'Shore power?
symbol BatVolt = C.7        'House battery voltage
symbol pRRun= pinB.3        'high when refigerator compressor is running
symbol pFRun= pinB.4        'high when freezer compressor is running
'i2c sda         B.5
'i2c scl         B.7
    
'output pins
symbol ActLED  = B.0        'flashes once per loop, off during delay
symbol LCD     = B.1        'Serial LCD display, Scott Edwards ILM-216
symbol Logger  = B.2        'Serial logger, SparkFun Logomatic v2
symbol CabFan  = B.6        'cabinet fan, run if cooler air is available
    
symbol LCDbaud = t9600_8
symbol LOGbaud = t9600_8
Once in the code blocks of the program only symbols are used. There are NO references to bX, wX or pins. The project with the above listing has been upsized twice to bigger chips as more functionality has been added. With symbols all that had to be done to existing code was changing/adding the symbols section to get started with the larger chip. Sometimes when it comes time to solder a circuit you find that swapping pins is useful, no problem, just change a few symbols. Once you get used to symbols I can't imagine you will want to go back to explicit vars and pins. There are just too many advantages.

The above listing is from older code. Currently I am prefacing symbols with their type so the first section would look more like this:
Code:
'refrigerator vars
symbol bRtemp  = b0
symbol bRmin   = b1
symbol bRmax   = b2
symbol bRstate = b3
symbol wRon    = w2
symbol wRoff   = w3
symbol btFD    = b14     'temporary location for freezer duty cycle calc
For a bit more on this see post 13 in this thread.

Does this make sense?
 

PieM

Senior Member
Try :


Code:
	if b8=9 and b7=5 or b7=2  Then
  		If flag = 0 Then gosub count_it
    		flag = 1
  	
		Else	flag = 0
	End If
The boolean equation is if A and (B or C)
 

Armp

Senior Member
That works 'correctly' in simulation:

Code:
Main:
for b7=2 to 5
for b8 =4 to 10

if  [COLOR="#FF0000"]b8=9 and b7=5 or b7=2[/COLOR]  Then 
  If flag = 0 Then gosub count_it
  flag = 1  	 
Else flag = 0
End If

Next b8
Next b7

goto main 

count_it:
sertxd (#b7," ",#b8," ",#flag)
Return
ScreenShot.jpg

So here we effectively get : b8=9 and (b7=5 or b7=2)

and in the original post it was b7=2 or (b7=5 and b8=9)

Hmmm....
 

westaust55

Moderator
I'm not sure the manual makes it clear that you shouldn't mix them though?
You are correct with respect to the manuals, however the topic (don't use AND and OR in same IF Statment) has been raised before.
Guess it is one of those things that the experienced / longer term members know but may trip up new comers.
 

Armp

Senior Member
I wasn't clear about this earlier. Here's the thread. there is a suggestion these can be mixed.
As I showed earlier with PieM's example - they can be mixed, but it does NOT get evaluated left to right, nor is there any apparent operator precedence. So its not clear, to me anyway, how to 'order' the conditionals to get the desired answer.
 

westaust55

Moderator
A test in the simulator (V5.4.3) finds that

if b8 = 0 OR b8=5 AND b9 = 0 then
acts like:
IF (b8 =0) OR (b8 = 5 AND b9 = 0)


whereas
if b9 = 0 AND b8 = 5 OR b8 = 0 then
acts like:
IF (b9 = 0) AND (b8=5 OR b8=0) THEN
 

russbow

Senior Member
I was actually looking for

if ( b7=2 or b7=5 ) and ( b8=9 ) Then

which passed syntax ok but gave wrong results.

Hippy's code

Code:
 if b7=2 or b7=5 then
  if b8=9 Then
    ...
  end if
end if
is much more elegant and I think more logical
 

MPep

Senior Member
@Armp,
I think that Hippy's method of writing this tends to be more logical, and intuitive.
Whilst the one line method will work, if you need to keep remembering the order in which things should work, but then spend time on adjusting the code to make it work, surely you are wasting time? :)
The compound statement method (Hippy's method) clearly states the order in which things will work.

Just my 2c worth.
 

Armp

Senior Member
@MPep We'll just agree to disagree :)

The REAL question IMO is how to define the syntax of IF.. THEN in the manual in a way consistent with the actual actions of the software.
 

PieM

Senior Member
In Boolean algebra without parenthesis, If A = B or C and D, A is true if B is true, independently of C and D
but if A = B and C or D, B must be true with C or D

It's the same as Hippy's code:

if b8=9 then
if b7=2 or b7=5 then
........
 

westaust55

Moderator
IMHO it comes down to the undocumented rule:
"Don't mix AND and OR in a single IF...THEN statement"

Currently as shown, while no syntax error is flagged it does not obey the usual left to right rules under all circumstances.
 

Armp

Senior Member
IMHO it comes down to the undocumented rule:
"Don't mix AND and OR in a single IF...THEN statement"
Code:
IF its not documented THEN 
  Its not a rule 
  IF the left-to-right rule doesn't apply THEN its an error
Endif
Goodnight All :eek:
 

marks

Senior Member
You'll find using boolean statements is strictly left to right.
you just need to try a little harder ! lol
I know its easy to confuse the order and get unexpected results.

One way
is to think of AND Statements as contacts in series
and think of OR Statements as contacts in parrellel
then its easy!

I think it's then obvious that order of AND and OR Statements can make
a big difference to the output.
 

westaust55

Moderator
You'll find using boolean statements is strictly left to right.
you just need to try a little harder ! lol
Unfortunately when you mix AND and OR in IF...THEN commands the "strictly left to right" fails. See post 13.

So its back to post 2 (and 19)
 

marks

Senior Member
Ican only try and have a go to explain what works for me !

if b9=0 and b8=5 or b8=0 then high c.1 : endif (actual statement)
result
b9=0,b8=5 true
b9=0,b8=0 true

although we wont get syntex we can rewrite as
Code:
if b9=0 AND b8=5  '(result  b9=0,b8=5 true)
         OR b8=0  '(result  b9=0,b8=0 true)
confusion is setting in if we think we are programming like a PLC(an extra instruction is used  (AND STR))
we get a different result.
With the picaxe every time we use the OR function we are infact branching off

IF b7=2             '(result b7=2,b8= dontcare true)
OR b7=5 AND B8=9    '(result b7=5,b8=9 true)

IF b8=9 AND b7=2     '(result b7=2,b8=9 true)
        OR  b7=5     '(result b7=5,b8=9 true)
get a move on santa I see nothin under the tree.....
 

Armp

Senior Member
As I showed earlier with PieM's example - they can be mixed, but it does NOT get evaluated left to right, nor is there any apparent operator precedence. So its not clear, to me anyway, how to 'order' the conditionals to get the desired answer.
After running some tests on the Simulator I now think my statement above is probably wrong :eek: and join @Marks and @PieM ... Not easy to explain, but here goes.

The function DOES get evaluated strictly from left to right, without operator precedence, one condition and one operator at a time, but evaluation STOPS when a TRUE or FALSE determination is reached, based on a couple of boolean shortcut rules.


  1. FALSE AND anything is FALSE : Skip the rest of the expression
  2. TRUE OR anything is TRUE : Skip the rest of the expression

Example IF A AND B OR C AND D THEN Doit

Look at the the first condition, and the operator to its right:
A AND ........
Rule #1
If A is FALSE the whole expression is FALSE, end evaluation, THEN Statement is NOT executed.
If A is TRUE the result is not determined. Drop 'A AND' from consideration and proceed to next terms

B OR ...
Rule #2
If B is TRUE the whole expression is TRUE, end evaluation, THEN Statement IS executed.
If B is FALSE the result is not determined. Drop 'B OR' from consideration and proceed to next terms

C AND ....
Rule #1
If C is FALSE the whole expression is FALSE, end evaluation, THEN Statement is NOT executed.
If C is TRUE the result is not determined. Drop 'C AND' from consideration and proceed to next terms

D THEN .....
No logical operator, so if D is TRUE, THEN Statement IS executed, If FALSE it is not.

Thus you can mix ANDs and ORs in the same expression to get complex results, but in most cases nested IF statements with only one or the other operator is the easier, more readable, logically understandable solution.

I'd still mix them for Mins=9 AND Tens=2 OR Tens=5 though....
 
Last edited:
Top