Measure Real Time with Imp using Server/Agent time

Test program to prove it works. Accurate to a few milliseconds.

`imp.configure(“time”,[],[]);
local t,mt;

function getms() {
local s,i,s1,s2;
i=(hardware.millis()%1000)-t;
if(i<0) i+=1000;
s1=s=time();
imp.sleep(0.1); //blocking
s2=time();
if((s2>s1)&&(i<100)) s=s2;
//if((s2>s1)&&(i>900)) s=s1;
//return(s); //1365…
s=s%1000000; //not 1e6
return(mt=(s*1000+i+1000)); //2000?
}
local ms1,ms2,ms3,ms=0,n=0;

function fdn(value){
local x1,x2,x3;
n++;
if(n==1) ms1=getms()%1000;
if(n==2) ms2=getms()%1000;
if(n==3) { ms3=getms()%1000;
x1=math.abs(ms1-ms);
x2=math.abs(ms2-ms1);
x3=math.abs(ms3-ms2);
if((x1<50)&&(x2<50)&&(x3<50)){
if(ms1<ms)ms=ms1;
if(ms2<ms)ms=ms2;
if(ms3<ms)ms=ms3;
ms2=ms; //return value
agent.on(“dn”,fdn2);
//server.log(ms);
}
ms=ms3;
n=0;
}
}
function fdn2(value){
server.log((getms()+50-ms2)%10000);
if((mt/1000)%10 !=(value%10)) server.log(“Bad”); //time() drifts about 4ms/min
}
function initt(){
local s;
imp.enableblinkup(true);
s=time();
while(s==time());
t=hardware.millis()%1000;
agent.on(“dn”,fdn);
}
function inittest(){ //this shows time() drifts about 4ms/min
local s,tt;
s=time();
while(s==time());
tt=hardware.millis()%1000;
server.log(tt-t);
imp.wakeup(60,inittest);
}
initt();
//inittest();
`

Obsolete. Can achieve same results with just one line of code to determine offset between millis() and NTC time. Verified using above code. Drifts by only 1ms / day.

I’ve been looking for a way to do just that using NTC time.
Can you post an example code?
Thanks.

`Agent:
local s,i;
for(i=0;i<50;i++) {
s=time();
while(s==time());
device.send(“dn”,(s+1));
}

Device:
dtm2=(value%1000000)*1000-hardware.millis()+50; //value is time() from Agent

//to print absolute accurate time later
server.log(dtm2+hardware.millis());
`

Thanks!
Is the time() function somehow synced to NTC time?
Why does it drift at all, then?

Time is synced to RTC. RTCs drift! I believe we are 30ppm over temperature - 30ppm is ~2.5 seconds per day.

Device time is synced to UTC using the RTC. Agent time is synced to UTC using NTP. So you can sort of see how it’s confusing to ask about “NTC”, because I’m not sure which you’re asking about… :wink:

Peter

Thanks Peter!
So if agent time is synced to UTC using NTP, I guess you can safely say that there is no drift… right?!

Correct.

Time on agent is within milliseconds. Time on Device drifts a lot. My code syncs them or at least allows you to measure the drift of millis(). millis() drifts much less than time(). You can find a constant to lower drift to 1ppm within a temperature range. That’s a few ms per day. You can resync as often as you want.

Perhaps I’m missing the ‘sync’ concept here @sbright. My understanding is that device time() is based off the device RTC, which is updated (re-sync’d) only after sleep or cold boot. You mention your code ‘syncs them’ (I’m assuming device to agent?). Is this done w/o the cold boot? How?

So am I right in thinking that if you don’t sleep or reboot your Imp for a month, its RTC could be over a minute out at the end of the month?

Yes, that’s my understanding. I recall Hugo’s comments re: oscillator accuracy of
+/- 30ppm (+/- 2.5 sec per day) … so this would be roughly a minute per month. (My measurements are consistent with this sort of drift).

@sbright seemed to be suggesting some sort of software resync of the device RTC (to agent, or UTC time) w/o the cold boot, so I as just trying to follow up on that comment. Perhaps I’m just misunderstanding though.

It’s a DIY concept open to experimentation. Trust me I have tested the idea thoroughly. Even when resyncd after sleep time() may still be off by 1 second. The Agent is always within milliseconds. The only variable is the time it takes for my device.send() to get to the Imp. With a good connection it is often consistent to within 1-2ms. To repeat: millis() is much more accurate than time() on the device. All you have to do is calculate the difference between Agent time() and Device millis(). Now you have an accurate absolute time! Multiply by an experimental constant and it runs on it’s own without a wifi connection. Larry what you said is true except my experiments show that time can be much worse than 30ppm. My code is simplified so as not to confuse anyone. I think it illustrates the concept, and only needs a few more lines to run. The Agent sends a message to the Imp when the time() changes each second exactly within milliseconds. The 50 represents the time it takes for the message to reach the Imp. I found this experimentally by measuring the round trip time /2. It is consistent to within a few ms every second it is sent. When the Imp receives the message the first line of code is executed to calculate the difference between Agent time() and millis(). This only needs to be done once. Again millis() is much more accurate than time() on the Imp. You can resync as often as you want without a cold boot. The 50 may vary a few ms from day to day. If you resync once each day, that is the biggest source of error. Now your Imp can tell time with extreme accuracy! It begins only a few ms from the correct absolute time. And drifts a few more ms per day. If you resync by executing my 1 line of code, it will jump a few ms. If you had no Wifi for a year, then connected again, you could calculate the error each day of the year for saved data in a log. This is as good as it gets unless…

Do you need accurate time to within 100 nanosecods of absolute time? Use the PPS pin of the Ultimate GPS. Now you can measure how long it takes a laser to travel 200 meters one way without reflecting it back!

Questions?

Thanks for the detailed response/explanation @sbright. Have got a few things going on today, so will take a much closer look into your code and explanation a bit later. (Yes, I agree with your observation that the oscillator appears to exceed the +/-30 ppm offset).

Thanks again … just need a bit of time now to digest your input. Will look it thru in detail, and be back in touch.

When the following code is put within the agent:
date <- date();
server.log(date.month);

The wrong month is being logged, 11 instead of 12. Does anybody else get the same result?

month starts counting with 0

Why would the month start with 0?, the day in date is displayed correct.

sorry, I’m only the messenger.
Why do you want to know?