getTime() Accuracy

Posted on
  • There is an strange behavior with the getTime() function, if I execute console.log(getTime()-getTime()), always get -0.00004019642 ¿Why?
    Example:

    >console.log(getTime()-getTime())
    -0.00004019642
    

    Regards,
    Pinnchus

  • You might be looking at a deterministic call time for getTime().
    getTime() will be interpreted and then call into c++ code, this will consume some time.

    Try

    var timeNow = getTime();
    console.log(timeNow-timeNow); //you'll get 0 ;)
    
  • I´m trying to know how much time expend in getTime() and caught my attention the result, is negative ¿?.

  • timeNow - timeSlightlyAfterNow = negative

    1 - 2 = -1

    :)

  • Absolutely right, i'm feeling like an idiot.

    Thanks

  • LOL... been there, will go there again!... It's just life!

  • Me too. It's the programmer's life; content reminders of how stupid** we all are...

    **at least when we're compared against an even dumber, but perfectly logical minion - such as a micro-controller.

  • Hi @Gordon,

    I revive this old thread mainly because of its title.

    On a Pico 1v3 with Espruino 2.01, I have a time shift of about 4.5 s per minutes: that is, I used new Date() on the console twice, separated by 4 minutes from my PC own time and got 18 s of difference. The pico was in late by that much.
    This was also shown to me by a Gps time provided resynchronising the system time every 20 s or so each time there was more than 1 s of difference between system time and UTC time provided by the gps. Again the pico was always in late from gps time.

    This resist to power on/off and getTime() gives the same results.
    The pico is in a standard room, neither sunny place, nor cold one (22°C).

    Any idea of why there is such a difference or could it be that a crystal is required?

    Thanks for your reading anyway.

  • Wow, that's really far off. Do you have more than one Pico and they both experience the same issue?

    Can you try shorting B3 and B4 and:

    analogWrite(B3,0.5,{freq:0.5});
    setWatch(function(e) {
      print(e.time - e.lastTime);
    }, B4, {repeat:true});
    

    Any two pins should work. That'll compare the internal RC oscillator with the high speed oscillator. I just tried on one running 2v01 and it returns numbers roughly around 1.01, so that's 1% off. In a minute you might expect half a second.

    One fix is definitely to add an external oscillator. I guess the other is a firmware change to ignore the RC oscillator completely, but that would then mean deep sleep doesn't work. Would that be an issue for you?

  • Hi @Gordon,

    Yes, this is quite far off.
    I only have one Pico, an original and a NucleoF401RE which, I guess could be the other candidate although it is bulky and lacks the mosfet...

    Unfortunately, I expect to use:

    • deep sleep most of the time (one wake up every 4 hours).
    • setTimeout for shorted durations (3-6 minutes).

    Actually, I was testing the setTimeout when I found this problem.

    So Here are the results of the test you proposed: 0.925 seems to be t a constant value.

    process.memory();
    ={ free: 5076, usage: 24, total: 5100, history: 7,
      gc: 0, gctime: 5.15270233154, "stackEndAddress": 536958912, flash_start: 134217728, "flash_binary_end": 385848,
      "flash_code_start": 134234112, flash_length: 393216 }
    >for (var i in global) print(i+" : "+E.getSizeOf(global[i]))
    JSON : 1
    process : 1
    i : 1
    E : 1
    =undefined
    >    analogWrite(B3,0.5,{freq:0.5});
    =undefined
    >    setWatch(function(e) {
    :      print(e.time - e.lastTime);
    :    }, B4, {repeat:true});
    =1
    NaN
    0.92654609680
    0.92720031738
    0.92611026763
    0.92719173431
    0.92583274841
    0.92541325092
    0.92637145519
    0.92529761791
    0.92329704761
    0.92374420166
    0.92555725574
    0.92385566234
    0.92300796508
    0.92220115661
    0.92258453369
    0.92306327819
    0.92353439331
    0.92302989959
    0.92228221893
    0.92291343212
    0.92221176624
    0.92150974273
    0.92200851440
    0.92271804809
    
  • Wow, ok. I don't think I've seen one so far off. Can you check the VCC line and check it really is 3.3v? The early Picos didn't have a very powerful diode and is was easy to slightly frazzle it if they got shorted - in that case it might not be getting the full voltage needed for 3.3v, which might be affecting the RTC speed?

    But yes, if you need deep sleep I think using an external low speed oscillator (or a whole external RTC like http://www.espruino.com/DS3231) is probably the only solution.

    Newer Espruino Originals actually have an RTC crystal on them so that could be a good choice?

    I think the NucleoF401RE doesn't use the RTC so it wouldn't actually keep time properly with deep sleep at all.

  • Powered from USB connector I measured:
    Vbat-Gnd = 4.27V
    Vbat_in - Gnd = 4.27V also
    3.3 - Gnd = 3.28V to 3.29V also.

    B0 is shorted by a solder bridge which I intend to use powering the pico from Vbat_in while powering my gps receiver from vbat controlled through the mosfet and b0 one day.

    My pico came from Kickstarter campaign...

  • Ok, your Pico would have had the weaker diode in it if it was from the KickStarter, but looking at the voltage you're fine so that won't be the issue. It looks like the internal RC oscillator is just way off.

    Looking at the source code it's possible I could add something that allowed you to tweak it for a different speed RTC. I don't know if that's something that would help at all?

    I've just had a go at it but something isn't working right I'm afraid. I need to look into it in a bit more detail.

    I think realistically fitting the Abracon ABS06-107 is the best way to get decent accuracy though - even tweaking the RTC won't bring it to the same kind of levels you'd get from a proper crystal.

  • Ok, fixed it. If you flash a build from http://www.espruino.com/binaries/travis/­36e263aabe91be08ebaf60ef1960807963e2130e­ then it'll have a function called E.setRTCPrescaler.

    The default value is 32000 (what ST say the internal clock speed should be) but let's say you're getting 0.923 average running that code above, you'd do:

    // 32000 * 0.923 = 29536
    E.setRTCPrescaler(29536);
    

    It'll take a few seconds to stabilise, and you might need to do some fiddling to get it a bit more accurate, but that should help you out a lot.

    If it looks like it's something useful I'll see about getting it into the main branch of Espruino.

  • Ok,

    So I flashed this frimware and restarted tests using my Gps provided time.
    I guess there is more precise clock than a Gps available to me.

    So apparently, if I do E.setPrescaler(32000) then it will drift (same value as usual), while with E.setRTCPrescaler(29536), it is only once (a time sync I think) and not later.
    Longer tests are required...

    Anyway, nice way to correct potential time shifts as it is now possible to measure the coefficient of shift and apply it automatically.

    Just to ask more, E.getRTCPrescaler() would be usefull too. :)
    Thank you.

  • Hi again,
    After a longer test I get the following results:
    -466.385 s (the Pico is counting a bit faster than the Gps) on a gps duration of 46190 s: so -0.0101 % of error having used E.setRTCPrescaler(29536); before the sync of gps's time and pico's time.
    So i expect no drift is I use E.setRTCPrescaler(29534); or more precisely E.setRTCPrescaler(320000.923(1+466.385/46190));

    Let's get started again with this!

  • That's great news! The temperature of the chip will affect the RTC speed a little, but that's still a really promising improvement. I'd be interested to see what others think but that sounds like it would be a good thing to merge into normal Espruino. I'll file an issue for it.

    There is some potential for working out that value automatically as well - it wouldn't be perfect, but would improve the accuracy a lot from what you were seeing at the start!

  • So, the results are really promising with little or no more shift with:
    E.setRTCPrescaler(320000.923(1+466.385/46190))
    The pico is still ahead of gps time by -1.42972660064 s / 4215 s.

    Note that those figures are now not really meaningfull: The time granularity on gps time and pico's time are 1 second each...

    So now, more test, more or less at room's constant temperature with:
    E.setRTCPrescaler(320000.923(1+466.385/46190)*(1+1.42972660064/4215)­)

    Finally, there is the prescaler granularity too..

  • Ok, it's now merged into master.

    I added the ability to auto-calibrate with:

    E.setRTCPrescaler(E.getRTCPrescaler(true­));
    

    as well.

    It's not going to be amazing, but it'll be miles better than the ~10% we were getting before!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

getTime() Accuracy

Posted by Avatar for Pinnchus @Pinnchus

Actions