Shop OBEX P1 Docs P2 Docs Learn Events
Need help comparing timestamps with the DS1302 and Prop — Parallax Forums

Need help comparing timestamps with the DS1302 and Prop

electromanjelectromanj Posts: 270
edited 2011-12-30 06:11 in Propeller 1
Hello all. I'm playing around with a simple demo to get familiar with the DS1302 and I've run into a snag.
For this demo the Propeller reads the seconds from the DS1302 into the variable secondrecord. Then if I press a pushbutton the Prop reads the seconds into the second variable. If less then 10 seconds has expired the time difference is displayed on the PST and "To soon!" is displayed. If more then 10 seconds has passed the time (hours min secs) is displayed. This all works well with exception of when seconds rolls around past :00. I've tried to correct this by subtracting secondrecord from 60 and adding second.
example: secondrecord = :53 second = :04. (60-53) +04 = (7)+4 = 11. That's not working out very well at all. I was hoping someone could look at my code and tell me where I've gone horribly wrong.
Thanks. traVis
CON
  _clkmode = xtal1 + pll16x 
  _xinfreq = 5_000_000

OBJ
  SN    : "Simple_Numbers"
  rtc   : "DS1302_full"
  debug : "SerialMirror"        

VAR
  byte hour, minute, minuterecord, second, secondrecord, day, month, year, dow, timedif
  
PUB init
  dira[0] := 0
  Debug.start(31, 30, 0, 115200)
  waitcnt(clkfreq/5+cnt)
  rtc.init( 4, 5, 6 )
  waitcnt(clkfreq/5+cnt)
  main                             
Pub main
  
  repeat
    rtc.readTime( @hour, @minute, @second )     'read time from DS1302
    secondrecord := second                      'capture seconds
    minuterecord := minute                      'capture minutes
    debug.str(string("secondrecord ="))
    debug.str(SN.decx(secondrecord,2))
    debug.str (string(13))
    repeat until ina[0] == 0                     'wait for button press
    rtc.readtime ( @hour,@minute,@second )       'get current time reading 
    debug.str (string("second ="))
    debug.str (SN.decx(second,2))
    debug.tx(13)
    if minute > minuterecord                  
        if second <=9
          
          timedif := (60-secondrecord) + second      'trying to subract secondrecord from 60 and add it to second
          debug.str(string("modified timedif",13))
    else
        timedif := second - secondrecord
        debug.str(string("stardard timedif",13))
    debug.str(string("Time difference in seconds ="))
    debug.str(SN.decx(timedif,2))
    debug.tx(13)
    
    if timedif >= 10 
        Debug.str( SN.decx(hour,2) )
        Debug.str( string(":"))
        Debug.str( SN.decx(minute,2) )
        Debug.str( string(":") )
        Debug.str( SN.decx(second,2))
        Debug.Str(String(13,10))    
        waitcnt( clkfreq + cnt )
    else
        Debug.Str (String("To soon!",13,10))
    waitcnt (clkfreq+cnt)
439 x 610 - 61K
PST.JPG 60.9K

Comments

  • Mike GMike G Posts: 2,702
    edited 2011-12-29 14:03
    How about always using the seconds that have elapsed since 12:00am?
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 14:10
    thanks for the quick reply. I guess I'm really curious why I'm not getting the result I want from the line
    timedif := (60-secondrecord)+second
    If I plug specific numbers into that equation the result is correct. There something going on there that I don't understand.
  • Mike GMike G Posts: 2,702
    edited 2011-12-29 14:34
    60-1+10 = 69

    But 15:34:30 = (60)(60)(15) + (60)(34) + 30 = 54,000 + 2040 + 30 = 56,070

    Just make a simple method that returns the second since 12:00am. That's a lot easier, and accurate over a minute.
    CON
      _clkmode = xtal1 + pll16x     
      _xinfreq = 5_000_000
    
    OBJ
      pst           : "Parallax Serial Terminal"
    
    
    PUB Main  | t1, t2, seconds
      pst.Start(115_200)
      pause(500)
    
      t1 := CalcSeconds(15, 30, 30)
      t2 := CalcSeconds(15, 30, 35)
      seconds := t2 - t1
    
      pst.dec(seconds)
      
    
    
    
    PUB CalcSeconds(hours, minutes, seconds)
      return (60 * 60 * hours) + (60 * minutes) + (seconds)
    
    PRI Pause(Duration)  
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return
    
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 15:14
    Ok I added this to test.
    hour2seconds := hours2secondCalc
        debug.str(string("Hour seconds ="))
        debug.str(SN.decx(hour2seconds,8))
    
    Pub hours2secondCalc
      return (60 * 60 * hour)
    
    I display a result of 00000016
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-12-29 15:23
    Hi Travis, I once built an application using an SX and DS1302 that monitored temperature change. If the temp was outside of a particular range for a certain period of time it would arm an alarm. Because the set point temperature varied throughout the day rather than do the math on hours minutes and seconds I kept a record of accumulated seconds from whenever the temp went out of range. If the temperature came back within range I would reset the accumulated time.

    In a loop waiting for an input to go low you will never miss a second.
    Pub Main | Accumulated_Time , temp
    
    
       repeat
         rtc.readTime( @hour, @minute, @second )     'read time from DS1302
         secondrecord := second                      'capture seconds
         temp:=second
         debug.str(string("secondrecord ="))
         debug.str(SN.decx(secondrecord,2))
         debug.str (string(13))
    
         repeat until ina[0] == 0
            rtc.readTime( @hour, @minute, @second )
            if  temp <>  second
               Accumulated_Time ++
               temp:=second
    
    

    just another way of skinning the proverbial cat

    regards

    Jeff
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 15:25
    Here are the methods that are called when time is read:
    PUB readTime( _hr, _min, _sec ) | tmp1, tmp2
    ''Read current hour, minute, second
    ''Usage: rtc.readTime( @hour, @minute, @second )
    
      byte[_hr]  := bcd2bin( read($85) )
      byte[_min] := bcd2bin( read($83) )
      byte[_sec] := bcd2bin( read($81) )
    
    
    PRI bcd2bin(dataIn)
    'Convert a byte of binary coded decimal data to binary
    
      result := (dataIn & %00001111) +  ((dataIn >> 4) & %00001111)*10
    
    Is there a problem with how the data is being stored in the variables compared to using a decimal value for multiplication or subtraction?
  • Mike GMike G Posts: 2,702
    edited 2011-12-29 15:25
    electromanj, how about posting all of your code. The RTC is in BCD format so you have to convert from BCD to an integer. Once you have the ints then it's a simple matter of math.

    @Unsoundcode, hitting that RTC I2C bus pretty hard eh. Why not use a seconds timer while waiting for the low?
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-12-29 15:34
    Hi Mike,
    @Unsoundcode, hitting that RTC pretty hard eh.

    does that matter? just asking.

    The DS1302_full converts the bcd to a binary value from the RTC so the conversion should be ok for the comparison

    Jeff T.
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 15:36
    @ Jeff Thanks! always up for new ways to skin the proverbial cat!

    @ Mike G Thanks for your help. The code in the first post is complete exept for a few changes I made in the last few minutes, minus the objects. Here is the archived edition.

    traVis
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-12-29 15:40
    Good deal Travis, I'm gonna skin the cat anyways.

    Jeff
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 15:54
    The thing I keep wondering about is:

    timedif:= second-secondrecord returns the desired result just fine (unless second happens to have wrapped past :59 which is the reason for the next line)
    timedif:=60-secondrecord+second never gives the desired result. Once the 60 is out in there things go wacky. If I declare the variable to a number such as 52 things work fine. The problem arises when 60 is used in an operation with the variable as recieved from the DS1302 full object.

    (or have I been at this too long today?) :D
  • Mike GMike G Posts: 2,702
    edited 2011-12-29 15:55
    does that matter? just asking.

    Doesn't matter as long as you get the results you want. I thought this might a bit more efficient.
    ...
      seconds := 0
      repeat until ina[0] == 0
        Pause(1000)
        seconds++
    ...
    
    PRI Pause(Duration)  
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return
    
  • Mike GMike G Posts: 2,702
    edited 2011-12-29 16:20
    electromanj, I don't have a DS1302 but I do have a 35390A. Should work the same if the BCD is converted to an integer by the RTC object. One thing, the s-35390A I'm using requires invoking the "update" method to read the current date/time and place the values in the object's member variables.
    CON
        _clkmode = xtal1 + pll16x
        _clkfreq = 80_000_000
    
    OBJ
     rtc           : "s-35390A.spin"
     PST           : "Parallax Serial Terminal.spin" 
    
    
    PUB start | t1, t2, seconds
    
      rtc.Start
      Pause(500)   
      PST.Start(115_200)
      Pause(500)
    
      pst.str(string("Time Diff Demo",13))
      
      rtc.update
      t1 := CalcSeconds(rtc.GetHour, rtc.GetMinutes, rtc.GetSeconds)
      Pause(5000)
      
      rtc.update 
      t2 := CalcSeconds(rtc.GetHour, rtc.GetMinutes, rtc.GetSeconds)
    
      pst.str(string("T1 = "))
      pst.dec(t1)
      pst.char(13)
    
      pst.str(string("T2 = "))
      pst.dec(t2)
      pst.char(13)
    
      seconds := t2-t1
      pst.str(string("Seconds past: "))
      pst.dec(seconds)
      pst.char(13)
    
      
    PUB CalcSeconds(hours, minutes, seconds)
      return (60 * 60 * hours) + (60 * minutes) + (seconds)
    
    
    PRI Pause(Duration)
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return  'end of PauseMSec
    
      
    
    
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-12-29 16:35
    Thanks Mike, you made me think that possibly there was a limit on how fast you should poll the RTC, you might have a point there.

    Jeff T.
  • electromanjelectromanj Posts: 270
    edited 2011-12-29 18:42
    Woohoo!!!!! I got it!!!!!!!!!!!!!!!!

    If it hadn't been through this many times before I would feel pretty silly right now for working pretty much all day on this problem only to find out the damage was being done by this:

    changed
    if second <=9
    
    to
    if second =<9
    

    after changing that all is good! But as to be expected the joy was short lived as the program started treating any second difference as valid and displaying the time. On a roll, I changed
    if timedif >= 9
    
    to
    if timedif >= (9)
    

    and that took care of that issue!

    I wish I could take credit for being so smart and figuring this out but the simple truth is I just kept trying this and that until the magic moment arrived!
    My thinking was that by writing <= i was saying greater then or equal to..... oops.

    If someone could review my initial code and the fix that I have here and explain what was happening I would be grateful....

    Thanks to Mike G and Jeff for your help. I really appriciated your replies!

    traVis.
  • Jorge PJorge P Posts: 385
    edited 2011-12-30 06:11
    That always gets me every time I use those operators, I have a habit now of keeping my Propeller Manual(v1.1) opened to page 114. There is also a single page (2 sided) Operators Sheet you can print out but I don't recall where I downloaded it from. Maybe someone can refresh my memory for me.

    >= is greater than (but not equal)
    => is equal to or greater than
Sign In or Register to comment.