87 lines
3.2 KiB
Python
87 lines
3.2 KiB
Python
|
|
|
|
import time
|
|
import serial
|
|
|
|
def readTime(serialPort):
|
|
'''Reads the time from the AVR over the serial port'''
|
|
serialPort.flushInput()
|
|
character = ""
|
|
while(not character == "\n"): # loop until see end of line
|
|
character = serialPort.read(1)
|
|
## The time string looks something like '011:045:023\r\n'
|
|
timeString = serialPort.read(13)
|
|
hms = timeString.split(":")
|
|
hms = [int(x) for x in hms] # make hour, minute, second numeric
|
|
return(hms)
|
|
|
|
def setTime(serialPort, hours, minutes, seconds):
|
|
'''Sends the time over the serial port'''
|
|
serialPort.flushOutput()
|
|
serialPort.write("S")
|
|
time.sleep(0.1) # delay while AVR sends
|
|
serialPort.write(str(hours) + "\r")
|
|
time.sleep(0.2) # delay while AVR sends
|
|
serialPort.write(str(minutes) + "\r")
|
|
time.sleep(0.2) # delay while AVR sends
|
|
serialPort.write(str(seconds) + "\r")
|
|
|
|
def setTimeNow(serialPort):
|
|
'''Sets the AVR clock to the current time'''
|
|
hours, minutes, seconds = time.localtime()[3:6]
|
|
setTime(serialPort, hours, minutes, seconds)
|
|
return(time.time())
|
|
|
|
def calculateTimeDelay(serialPort):
|
|
'''Gets AVR time and subtracts off actual (computer) time'''
|
|
avrHMS = readTime(serialPort)
|
|
hms = time.localtime()[3:6]
|
|
hmsDifference = [x - y for x,y in zip(avrHMS, hms)]
|
|
out = "AVR is fast by: {x[0]} hours, {x[1]} minutes, and {x[2]} seconds"
|
|
print out.format(x=hmsDifference)
|
|
return(hmsDifference)
|
|
|
|
def calculateTimeDrift(serialPort, startTime):
|
|
'''Calculates the ratio to multiply OVERFLOWS_PER_SECOND
|
|
given a start time and current error'''
|
|
h, m, s = calculateTimeDelay(serialPort)
|
|
driftSeconds = 60*60*h + 60*m + s
|
|
elapsed = time.time() - startTime
|
|
print "After {:.0f} seconds, ".format(elapsed)
|
|
return (driftSeconds / elapsed + 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
## Set time automatically, recording start time,
|
|
## then periodically calculate multiplication factor
|
|
OVERFLOWS_PER_SECOND = 31250 # set this to equal the value in your code
|
|
|
|
SLEEP_TIME = 10
|
|
ratioLog = []
|
|
|
|
s = serial.Serial("/dev/ttyUSB0", 9600, timeout=5)
|
|
print "Setting time to current time...."
|
|
ratio = 0
|
|
while not ratio == 1: # make sure starting time is right on
|
|
startTime = setTimeNow(s)
|
|
ratio = calculateTimeDrift(s, startTime)
|
|
|
|
## Note: you can either leave this running or
|
|
## you can re-run calculateTimeDrift() at any time in the future,
|
|
## as long as you don't overwrite the original startTime
|
|
while(True):
|
|
ratio = calculateTimeDrift(s, startTime)
|
|
ratioLog.append([time.time()-startTime, ratio])
|
|
newOverflow = int(OVERFLOWS_PER_SECOND * ratio)
|
|
print "OVERFLOWS_PER_SECOND should be {}\n\n".format(newOverflow)
|
|
time.sleep(SLEEP_TIME)
|
|
|
|
## As you leave this routine running, you should see it bounce
|
|
## around a lot in the beginning and then settle down after
|
|
## running a few hours. Ironically, it'll converge to a good
|
|
## number faster if it's initially very out of sync. (If it
|
|
## drifts faster, you can figure out the drift rate sooner.)
|
|
## Leave it running for 24 hours and you'll get one-second-per-day
|
|
## accuracy.
|