IF condition problem

Is there a problem with this IF condition as I have it? I can't seem to make it work.
IF (timbuf[hours]==6) AND (timbuf[minutes]==59) AND (timbuf[seconds]=>40)

Comments

  • Looks like C code so it should be written:
    if ((timbuf[hours] == 6) && (timbuf[minutes] == 59) && (timbuf[seconds] >= 40))
    

    Mike
  • @AGCB, your code is syntactically correct for Spin. Post the rest of your code, and we may be able to find the problem.
  • Here's the main loop. Everything works fine but the low temp will not reset for a new day. I assume you'll be interested in only the last 16 lines or so. I don't want to waste your time but appreciate your help! Aaron
    PUB init   |  mtpl     ''start objects and define 1wire addresses
      waitcnt(clkfreq*2+cnt)  '2 seconds for TV to come on
      tv.start(0)
      ow.start(10)
    
      cognew  (counter,@stack)
      cognew  (RTCcog,@RTCstack)  
    
      dira[24]:=1     'make pin 24 output for freezer 110 volt alarm 
      
         'define device addresses of temp sensors
             'use spin_onewire_test to determine addresses of devices
      addrs0[0]:=$3e676928        'least significant long of 64 bit address        shop
      addrs0[1]:=$87000006         'most significant long of 64 bit address  
      A_temp := @addrs0          ' the memory location of complete 64 bit address value                 
      
          'other sensors
      addrs1[0] :=$3F560228
      addrs1[1] :=$7A000006                                                       'coop
      B_temp := @addrs1       
     
      addrs2[0] :=$70056F28
      addrs2[1] :=$7F011431                                                       'boiler
      C_temp := @addrs2
    
      addrs3[0] :=$045B4E28
      addrs3[1] :=$6F011431                                                       'Outside 
      D_temp := @addrs3
    
      addrs4[0] :=$2BD92B28
      addrs4[1] :=$E5011431                                                       'Pen 
      E_temp := @addrs4
    
      addrs5[0] :=$5AE5AA28
      addrs5[1] :=$B202131C                                                       'TV_RM freezer
      F_temp := @addrs5
    
      addrs6[0] :=$C59EAA28
      addrs6[1] :=$D402131C                                                       'Cave freezer
      G_temp := @addrs6
    
      addrs7[0] :=$BB6DAA28
      addrs7[1] :=$8102131C                                                       'Pantry freezer
      H_temp := @addrs7
    
      flag:=0
      index:=1   
    
     {  
      setconfig(12,0,0)  'leave commented out unless you want to change the
                                       ' resolution of all the devices
      }
      main
     
    PUB  main  ''loop
      waitcnt(clkfreq*2+cnt)    'wait for time keeping things to get started
      OSsensor :=readTemperature(D_temp)
      OSmin:=OSsensor                    
      frstBrnHrs:=timbuf[hours]      'preload 1st burn clock
      frstBrnMints:=timbuf[minutes]
    
      oldHours:=(timbuf[hours])
      oldMints:=(timbuf[minutes])  
      oldDay:=(timbuf[day])
    
      tv.move(1,28)
      tv.hex((oldHours & %0011_1111),2) 'the & %0011_1111  gets rid of extra character in hours display ?
      tv.str(string(":"))
      tv.hex(oldMints,2)
      tv.str(string("  "))
      tv.str(lookup(oldDay:string("SUN"),string("MON"),string("TUE"),{
          }string("WED"),string("THU"),string("FRI"),string("SAT")))
       
      
      repeat         
          'Get readings from sensors
        ShopSens:=readTemperature(A_temp)                                 'shop
        
        waitcnt(clkfreq/10+cnt)
        CoopSens:=readTemperature(B_temp)                                 'coop
        
        waitcnt(clkfreq/10+cnt)
        BoilerSens:=readTemperature(C_temp)                                 'boiler
        
        waitcnt(clkfreq/10+cnt)
        OSsensor :=readTemperature(D_temp)                                 'OS
        
        IF (OSsensor < OSmin) AND (timbuf[seconds] =<3)        '
          OSmin:=OSsensor - 1   'update low temp  (done pre conversion to °F)  'but restricted by time
          oldHours:=(timbuf[hours])
          oldMints:=(timbuf[minutes])  
          oldDay:=(timbuf[day])
    
        waitcnt(clkfreq/10+cnt)
        PenSens:= readTemperature(E_temp)                                  'pen
    
        waitcnt(clkfreq/10+cnt)    
        TVsens:= readTemperature(F_temp)                                   'TV rm freezer
        TVout:=output
             
    
        waitcnt(clkfreq/10+cnt)
        caveSens:= readTemperature(G_temp)                                 'cave freezer
        CaveOut:=output
        
    
        waitcnt(clkfreq/10+cnt)
        PantrySens:= readTemperature(H_temp)                               'pantry freezer
        PanOut:=output
        
        
        waitcnt(clkfreq/10+cnt)
          
          'display temps
        TV.move(1,1)
        tv.out($08)   'backspace       
          
        tv.str(string("Outside = "))
        showf(OSsensor,0)
        
        tv.move(1,17)
        tv.str(string("LOW                    "))
        tv.move(1,21)
        showf(OSmin,0)
        
           'show time of LOW reading 
        tv.move(1,28)
        tv.hex((oldHours & %0011_1111),2) 'the & %0011_1111  gets rid of extra character in hours display ?
        tv.str(string(":"))
        tv.hex(oldMints,2)
        tv.str(string("  "))
        tv.str(lookup(oldDay:string("SUN"),string("MON"),string("TUE"),{
            }string("WED"),string("THU"),string("FRI"),string("SAT")))
              
        tv.move(2,1)
        tv.out($08)
        tv.str(string("Machine Shop = "))
        showf(ShopSens,0)
        
        tv.str(string(13,"Chicken Coop = "))
        showf(CoopSens,0)
        
        tv.str(string(13,"Chicken Pen  = "))
        showf(PenSens,0)
        
        tv.str(string(13,"Boiler Water = "))     'now on row 5 ?
        showf(BoilerSens,0)       
        
        IF INA[23]==1 AND flag==0  'when signal appears on pin 23 from boiler fan via optocoupler AND flag not set
          ms:= 0           'clear counter
          flag:=1          'set flag to prvent this again
         
          tv.move(7,1)
          tv.str(string("                                   "))  'clear line
          tv.move(7,7)
          tv.str(string("Fan and Furnace are ON!"))
          beep1        
          
          IF index=>34         'if past 6th position          
            index:=0     'reset index to 1st position
            IF rowcnt==1   'if already on line 10
              rowcnt:=0    'go back to line 9
              tv.move(9,1)   'clear lines 9 & 10
              tv.str(string("                                   ",13))
              tv.str(string("                                   "))
              frstBrnHrs:=timbuf[hours]      'update 1st burn clock
              frstBrnMints:=timbuf[minutes]            
            ELSE
              rowcnt:=1    'if not already on line 10 go there
          
        IF flag==1
          BurnTime:=ms  
          tv.move(8,1)
          tv.str(string("BurnTimes; Oldest First at "))
          tv.hex((frstBrnHrs & %0011_1111),2) 'the & %0011_1111  gets rid of extra character in hours display ?
          tv.str(string(":"))
          tv.hex(frstBrnMints,2)
          'IF index==1 AND rowcnt==0 AND burnTime =<4                 
            
          tv.move(row+rowcnt,collunm+index)    '1st position is row 9, collunm 1
          tv.dec(burnTime)
          IF burnTime=>1200 AND burnTime=< 1210   'low wood warning
            beep3
    
        IF INA[23]==0 AND flag==1  'when fan goes off AND flag set
          flag:=0             'clear flag, ready for next burn cycle
          tv.move(7,1)
          tv.str(string("    Draft Fan is off               "))       
          burnTime:=0
          beep2
          index+=5       '1,6,11,16,21,26,31      'increment index for next cycle
          
            'show freezer temperatures
       tv.move(11,1)
       tv.out($08)   'backspace 
       tv.str(string("TV Freez "))
       showf(TVsens,0)
       tv.str(string(" Cave "))
       showf(CaveSens,0)
       tv.str(string(" Pantry "))
       showf(pantrySens,0)
          
       tv.move(12,1)
       tv.out($08)   'backspace
       tv.str(string("Current time is  "))
       tv.hex(timbuf[hours] & %0011_1111,2) 'the & %0011_1111  gets rid of extra character in hours display ?
       tv.str(string(":"))
       tv.hex(timbuf[minutes],2)     
             
       IF  ||TVout   < 62     'absolute value of ~~dsOut   62=25°F  lower value = higher temp                                   
         FreezWarn
       IF  ||CaveOut < 62     'absolute value of ~~dsOut   62=25°F  lower value = higher temp                                   
         FreezWarn
       IF  ||PanOut  < 106     'absolute value of ~~dsOut   106=20°F  lower value = higher temp                                   
         FreezWarn      
      '  outa[24]~~    'sound loud 110v alarm through relay and manual switch
    
             'Reset low for a new day
       IF (timbuf[hours]==9) AND (timbuf[minutes]==59) AND (timbuf[seconds]=>40)
         OSmin:=OSsensor         'output 426 = 80F 'reset low temp & time
         oldHours:=(timbuf[hours])
         oldMints:=(timbuf[minutes])  
         oldDay:=(timbuf[day])
    
    PUB  RTCcog
      I2C.start(SCL,SDA,bitrate)    
    
      repeat   'display time at lower center of screen      
         waitcnt(clkfreq+cnt)
         I2C.readbytes(RTC,0,@timbuf,7)
         IF INA[16] ==1               'DST/CST switch for daylight savings time
              timbuf[hours] := timbuf[hours] + 1   'this will be summer (spring ahead)
    
  • Here's a screen shot of the TV output
    4288 x 2416 - 3M
  • It appears that your time information is stored in BCD (Binary Coded Decimal) format - the first 4 bits are the 10's value and the second 4 bits are the 1's value.

    I base this on these lines, where you're handling the display of the values in hex:
    tv.hex((oldHours & %0011_1111),2) 'the & %0011_1111  gets rid of extra character in hours display ?
      tv.str(string(":"))
      tv.hex(oldMints,2)
    

    This means that you need to convert the value from BCD to binary before any comparisons.
    'This code should work but I haven't tested it...
    PRI GetBinFromBCD(bcdVal)
      result := ((bcdVal & $30) >> 4) * 10 + (bcdVal & $0F)
    

    Walter

    Tulsa, OK

    My OBEX objects:
    AGEL: Another Google Earth Logger
    DHT11 Sensor

    I didn't do it... and I promise not to do it again!
  • Dave HeinDave Hein Posts: 5,948
    edited 2019-03-27 - 13:36:42
    Your code doesn't show where you declare timbuf, or where you update it. Assuming that you are declaring it correctly, and updating it correctly, then I see 2 potential issues. When you print the hours you use the line
    tv.hex(timbuf[hours] & %0011_1111,2) 'the & %0011_1111  gets rid of extra character in hours display ?  
    
    This implies that there are non-zero bits beyond the 6 least significant bits. Your IF statement doesn't account for this possibility. Maybe that is what's causing the problem. The other potential problem is that the seconds comparison uses "=>40", which means that the low temperature resets when the hours and minutes match your criteria, and the seconds are between 40 and 59. I don't know how fast timbuf is updated or how fast the main repeat loop runs, but maybe you are missing the 10-second window that your IF conditional uses. Or maybe timbuf isn't being updated fast enough.
  • The DS1302 timekeeping chip (for example) uses BCD format for the time registers. It also uses the high bit in the seconds and hours registers as flags.

    For this chip, the high bit has to be set for 12 hour mode (instead of 24 hour mode).

    Which means that Aaron's code will need to also account for AM/PM when making the time comparison. Otherwise it will trigger twice a day.
    Tulsa, OK

    My OBEX objects:
    AGEL: Another Google Earth Logger
    DHT11 Sensor

    I didn't do it... and I promise not to do it again!

  • wmosscrop
    The RTC is a DS3231N and yes it is BCD output. I'll have to play with your conversion code. I also found this one in my old notes.
    return (((BCD >> 4) * 10) + (BCD & $F))
    
    . Don't know if they work similar.
    I'm displaying 24 hour mode.

    Dave Hein
    That brings up a second minor problem in that when the hour should read 10 it actually reads 0A. I've done RTC displays before and not had this problem. Must have used a different code then but can't find it.

    The timbuf is a global byte VAR (IE) BYTE timbuf[7].
    The RTC updates once per second (RTC COG) and the main loop takes about 4 - 6 seconds.

    Thanks
    Aaron
  • Per the DS3231 datasheet, bit 7 is used as I indicated, to indicate 12/24 hour format.

    In addition, bit 6 is used to denote PM status in 12 hour mode.

    In other words, 10 PM in 12 hour mode would have the binary value %0101_0000.

    Your code won't work, it needs to strip off the high 2 bits of the value:
    return ((((BCD & $30) >> 4) * 10) + (BCD & $F))
    
    Tulsa, OK

    My OBEX objects:
    AGEL: Another Google Earth Logger
    DHT11 Sensor

    I didn't do it... and I promise not to do it again!
  • Dave HeinDave Hein Posts: 5,948
    edited 2019-03-27 - 17:20:14
    I didn't realize that the time is in BCD. You don't need to convert from BCD to binary. You just need to do your comparisons with BCD value, which can be represented by hex notation. So your IF statement should be:
    IF (timbuf[hours]==$6) AND (timbuf[minutes]==$59) AND (timbuf[seconds]=>$40)
    
    If your using the 24-hour format you don't need to mask off the upper 2 bits. They will always be 0.
  • There is a problem with your daylight savings adjustment. The code is:
         IF INA[16] ==1               'DST/CST switch for daylight savings time
              timbuf[hours] := timbuf[hours] + 1   'this will be summer (spring ahead)
    
    If timbuf[hours] has a value of $09 you will get $0A after the adjustment, which is not a valid BCD number. Also if the value was $23 you will get $24 instead of $00. You need to test for those special cases, so your code should look like this:
         IF INA[16] ==1               'DST/CST switch for daylight savings time
              timbuf[hours] := timbuf[hours] + 1   'this will be summer (spring ahead)
              IF timbuf[hours] == $0A
                 timbuf[hours] := $10
              ELSEIF timbuf[hours] == $24
                 timbuf[hours] := $00
    
  • Thanks Dave! I'll correct that. I didn't realize that it was when I added the DST part that it went goofy.
    Aaron
  • Thanks Dave and Walter. It works great now!

    As usual, when I ask a question on this forum I learn more than I expected.

    Aaron
Sign In or Register to comment.