In order for this to function, the following conditions must be met;
- the Pico must be connected to the host computer with a USB cable
- the code below must have already been placed in the file main.py on the Pico board
- no other software [e.g. Thonny] may be running on the host computer that may block the USB serial port being used
- a simple python script will need to be executed [once] on the host computer to send the host computers date and time to the Pico over the USB serial connection (python3 and pyserial are required to be installed on the host computer)
note: you may also wish to look at this post viewtopic.php?f=146&t=300676, regarding powering the Pico board using batteries
In the main while loop of the code the following happens;
- a check is made to see if date and time sync message has been received over the USB serial port [checkTimeSyncUSB].If it has, the message is processed and a timeDelta from the Pico system clock is calculated and returned.
- any timeDelta is applied to the Pico system clock to generate a correctedRTC
- every second, when the correctedRTC changes, a check is made to see if the date and time have been synchronised yet [timeDelta != 0]. If not a rapid burst of LED flashes is delivered
- then, a series of variables [year, month, day, hour, minute, second, wday, yday] are updated with the latest correctedRTC values and a string [correctedRTCstring] is constructed for use in data logging
- finally, every 5 seconds, some 'data capture/logging activity' takes place
Code: Select all
from machine import Pin from utime import time, localtime, sleep from select import select from sys import stdin timeDelta = 0 year,month,day,hour,minute,second,wday,yday = 0,0,0,0,0,0,0,0 def timeNow(timeDelta): return (time() + timeDelta) def checkTimeSyncUSB(timeDelta): ch, buffer = '','' while stdin in select([stdin], , , 0): ch = stdin.read(1) buffer = buffer+ch if buffer: for i in range(len(buffer)): if buffer[i] == 'T': break buffer = buffer[i:] if buffer[:1] == 'T': if buffer[1:11].isdigit(): syncTime = int(buffer[1:11]) if syncTime > 1609459201: # Thursday 1st January 2021 00:00:01 timeDelta = syncTime - int(time()) else: syncTime = 0 return timeDelta led_onboard = Pin(25, Pin.OUT) lastTime = timeNow(timeDelta) while True: timeDelta = checkTimeSyncUSB(timeDelta) correctedRTC = timeNow(timeDelta) # # every second do the following ... # if correctedRTC != lastTime: lastTime=correctedRTC if timeDelta == 0: for i in range(5): led_onboard.toggle() sleep(0.03) led_onboard.value(0) (year,month,day,hour,minute,second,wday,yday)=localtime(correctedRTC) correctedRTCstring="%d-%02d-%02dT%02d:%02d:%02d" % (year,month,day,hour,minute,second) # # every 5 seconds do the following ... # if (second % 5) == 0: print('CorrectedRTC Unix epoch time :',end='');print(correctedRTC) print('CorrectedRTC localtime list :',end='');print(localtime(correctedRTC)) print('CorrectedRTC composite date/time :',end='');print(correctedRTCstring) print()
In order to sync the Picos date and time, the following python script should be saved into a file [picoSyncTime.py] and run on the host computer. The Pico board should be connected to the host computer using a USB cable, before running picoSyncTime.
picoSyncTime will automatically detect which USB port the Pico has been connected to, and send the host computers date and time to the Pico board in ascii UTC format prefaced by a 'T' to indicated a time sync message. The code should only take a second or two to run and will print a message on the host computer indicating it detected the Pico [or not] and sent a message.
If the date and time sync message is successfully received and applied by the Pico, the LED on the Pico will cease its rapid pulsing every second. If the sync was not successful, you can run picoSyncTime again.
picoSyncTime can be run at any time and if a Pico board [running the code above] is connected, it will re-sync the Pico board with the host computers date and time.
Further information on epoch dates and date formats can be found here https://epochconverter.com.
Code: Select all
#!/usr/bin/env python3 # # Vendor:Product ID for Raspberry Pi Pico is 2E8A:0005 # from serial.tools import list_ports import serial, time picoPorts = list(list_ports.grep("2E8A:0005")) if not picoPorts: print("No Raspberry Pi Pico found") else: picoSerialPort = picoPorts.device with serial.Serial(picoSerialPort) as s: syncMSG = 'T'+str( int(time.time()) ) s.write(bytes(syncMSG, "ascii")) with serial.Serial(picoSerialPort) as s: syncMSG = 'T'+str( int(time.time()) ) s.write(bytes(syncMSG, "ascii")) print( "Raspberry Pi Pico found at "+str(picoSerialPort) ) print( "Time sync epoch USB MSG: "+syncMSG )
picoSyncTime needs to be run on the host computer and requires pyserial to be installed, or you may receive an 'ImportError: no module named 'serial'' message when it is run.
More information can be found on pyserial here https://pyserial.readthedocs.io/en/latest/pyserial.html. To install pyserial enter the following on the host computer command line.
Code: Select all
python -m pip install pyserial
NOTE: if you restart the code running in your Pico board or disconnect it from power, effectively reseting it, you will need to re-sync your Pico board with a host computer again to have an accurate correctedRTC (by default, at startup, the MicroPython interpreter running on the Pico initialises the Pico system clock to 1609459201 - Thursday, 1st January 2021 00:00:01)
This post viewtopic.php?f=146&t=300676 provides some more information regarding how to achieve a ‘RTC battery backup’ by attaching a battery to VSYS and GND.