Shop OBEX P1 Docs P2 Docs Learn Events
Time measuring — Parallax Forums

Time measuring

H2O2H2O2 Posts: 9
edited 2008-12-07 21:54 in Propeller 1
Hi!
I have a need to measure the time between two events in an application, ie I am building an GPS based navigator and want to be able to calculate the traversed distance.

I am doing this by a simple numerical integration [noparse][[/noparse]Distance := Distance + speed*DeltaTime]. Therefore I need the time elapsed [noparse][[/noparse]DeltaTime] between the reading the GPSreceiver.

My first approach was to read the System Clock Counter [noparse][[/noparse]cnt] at the beginning and end of reading the NMEA string containing the speed. The difference would then be my DeltaTime. However, after some experimenting I've found that this approach only works when the time between beginning and end is approx 0.25s or less. I am not sure the time between two consecutive readings is less than this. Larger intervals result in negative values.


An alternative solution would be much appreciated!


//G

Comments

  • Goran (Sweden)Goran (Sweden) Posts: 68
    edited 2008-12-07 19:12
    Hi G
  • Mike GreenMike Green Posts: 23,101
    edited 2008-12-07 19:17
    With an 80MHz system clock, the maximum time interval that can be measured by using the system clock is about 54 seconds. This is the amount of time it takes for the 32 bit CNT register to wraparound. I don't know why you're only able to measure 0.25s. That doesn't make sense. Note that time intervals greater than about 27 seconds will give you a "negative" difference between the two system clock values because the difference is greater than 31 bits.

    If you need time intervals greater than this, I suggest you come up with a real time clock routine that runs in its own cog. It could keep its own one second timer, then use the system clock for the time from the last recorded second. It would also use the system clock (with the WAITCNT statement) to keep the one second interval.
  • H2O2H2O2 Posts: 9
    edited 2008-12-07 19:30
    Yes, that was my first idea, but the receiver I am using [noparse][[/noparse]Parallax] only gives the time with the a resolution of one second. I don't think this is enough to get a accurate integration.

    I've seem in NMEA documentation that time is given i milli-secs, but maybe it is some limitation in the Parallax receiver.

    //G
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-12-07 19:34
    Hello G
  • H2O2H2O2 Posts: 9
    edited 2008-12-07 19:44
    Mike,

    attached please find my test program.

    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    OBJ

    Debug : "FullDuplexSerialPlus"

    PUB Main | ok

    ok := Debug.start(31, 30, 0, 57600)
    TestTiming

    PUB TestTiming | BaseTime, TimeNow, TimePast, Loop, Delay, ElapsedTime

    ElapsedTime := 0
    TimeNow := cnt
    BaseTime := TimeNow
    Delay := clkfreq / 5 ' When this 5 is changed to say 2 it does not work...
    Loop := 0
    repeat while Loop < 10000
    TimePast := TimeNow
    waitcnt(BaseTime += Delay)
    TimeNow := cnt
    ElapsedTime := ElapsedTime + 100*(TimeNow - TimePast)/clkfreq 'In 100th of a sec
    Debug.str(String("Elapsed Time: "))
    Debug.dec(ElapsedTime)
    Debug.str(String(10, 13))
    Loop++




    //G
  • TJHJTJHJ Posts: 243
    edited 2008-12-07 20:41
    Just a thought, since you can never get a new speed faster than 1 second later in the update cycle, due to the limitation of the GPS unit.

    Why not calc it against a known value.
    Update speed as oftan as you can, or want to.

    But only perform this calculation once per second.
    waitcnt(clkfreq +cnt)
    Distance := Speed*(1 Second  ) ' youll need to account for what units you want it in, and make sure there not a decimal. 
    
    
    or 
     ' This is not the most accurate way of doing it, as depending on the calcs in the loop in can be more than 1 second by a few cycles. , 
    secondCounter = clk
    repeat 
      'DO other things here. 
      if secondCounter > (clk + clkfreq) ' if one second has passed. 
        Distance := Speed*(1 Second) ' unit again here.... FIND DISTANCE
        secondCounter := clk + clkfreq ' update when the counter will be at 1 second again. 
    
    
    
    


    The other thing is Im taking a guess that this thing is not insanely fast. Why not just calculate your distance using the GPS data points, it will take float math 32 full, but since it only updates once per second, the added calculation time should not be an issue, even this in full float will be way shorter than 1 second.

    Here is the formula for cacluating distance using decimal lat long.

    R = earth’s radius (mean radius = 6,371km) ( you have altitude so you can compensate this to increase the accuracy. )
    Δlat = lat2− lat1
    Δlong = long2− long1
    a = sin²(Δlat/2) + cos(lat1)*cos(lat2)*sin²(Δlong/2)
    c = 2*atan2(√a, √(1−a))
    d = R*c

    its not the easiest calculation, but I think it will end up being alot more accurate than dealing with speed. As your speed can fluctuate greatly over your sample times.

    TJ

    Post Edited (TJHJ) : 12/7/2008 8:52:58 PM GMT
  • Chuck RiceChuck Rice Posts: 210
    edited 2008-12-07 21:54
    I think that this is the calculation you need (see the attached file for the full object.


    pub calcHaversineDistance(lat1,lon1,lat2,lon2) : distance | t1,t2,t3, tsq1,tsq2,a,c,d,deltaLat,deltaLon
    
    '' Calculate distance between two lat/long pairs using Haversine method.
    '' reference: http://www.movable-type.co.uk/scripts/latlong.html
    ''
    '' lat1,lon1,lat2,lon2 floating point variables in radians
    '' Returns distance in floating point StatMiles
    
    'cEarthR   = earth's radius (mean radius = 6,371km)
    'deltaLat  = lat2 - lat1
    'deltaLon  = lon2 - lon1
    'a         = sin^2(deltaLat/2) + cos(lat1).cos(lat2).sin^2(deltaLon/2)
    'c         = 2.atan2(sqrt(a), sqrt(1-a))
    'd         = R.c
    
     deltaLat := fp.fsub(lat2,lat1)
     deltaLon := fp.fsub(lon2,lon1)
    
     t1   := fp.sin(fp.fdiv(deltaLat,2.0))
     t2   := fp.sin(fp.fdiv(deltaLon,2.0))
     tsq1 := fp.fmul(t1,t1)
     tsq2 := fp.fmul(t2,t2)
     t3   := fp.fmul(fp.fmul(fp.cos(Lat1),fp.cos(lat2)),tsq2)
     a    := fp.fadd(tsq1,t3)
    
     t1   := fp.fsqr(a)
     t2   := fp.fsqr(fp.fsub(1.0,a))
     t3   := fp.atan2(t1,t2)
     c    := fp.fmul(2.0,t3)
     d    := fp.fmul(cEarthR,c) ' result in kilometers
    
     return fp.fmul(d,0.621371192) ' Convert kilometers to StatMiles
    
Sign In or Register to comment.