DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Sync Pico RTC with host computer

Sun Jan 31, 2021 12:26 pm

The MicroPython code below will automatically synchronise with the date/time of a host computer over a micro USB cable. This will work with Windows, Mac and Linux computers using a vanilla Pico board with no additional hardware required (beyond a micro USB cable).

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
When the Pico is connected to a host computer [or powered on by a battery] the code in main.py will automatically begin to execute and the LED on the Pico will pulse rapidly each second to indicate that its date and time have not yet been synchronised. Once the date and time have been successfully synchronised the rapid pulsing every second will cease.

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
In the code example below, the 'data capture/logging activity' consists of a simple series of messages sent to a console/serial terminal connected to the Pico board USB serial port. However, this could be replaced with your own code running at whatever interval you choose, rather than every 5 seconds.

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)[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[0].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.
Last edited by DWiskow on Mon Feb 01, 2021 3:54 pm, edited 11 times in total.

JumpZero
Posts: 1225
Joined: Thu Mar 28, 2013 7:35 pm
Location: Arcachon, France

Re: Sync Pico RTC with host computer

Sun Jan 31, 2021 2:47 pm

Nice it works!
Good workaround, but we still need a MicroPython RTC class to set the hardware rtc.

DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Re: Sync Pico RTC with host computer

Sun Jan 31, 2021 3:35 pm

JumpZero wrote:
Sun Jan 31, 2021 2:47 pm
Good workaround, but we still need a MicroPython RTC class . . .

Agreed, but in the interim this means I can build my Fridge Temperature Data Logger with just a bare Raspberry Pi Pico and a couple of AA batteries ! :D :lol: :roll:

Lordanubis
Posts: 35
Joined: Mon Dec 23, 2013 8:13 pm

Re: Sync Pico RTC with host computer

Sun Jan 31, 2021 6:49 pm

Thank you. Wil check it out. Top!!!👍🏼

I start liking the R(Pi)2co more and more.

dougg0
Posts: 4
Joined: Mon Feb 01, 2021 11:37 am

Re: Sync Pico RTC with host computer

Mon Feb 01, 2021 11:51 am

Hi. I went through this with , i think, a fine-tooth comb but get an error when running the second Script
ImportError: no module named 'serial'

I have the pico connected via USB to iMac running High Sierra and Thonny v3.3.3 and Python 3.7.9

The 'main.py' runs OK on the Pico and LEDS flash as specified, i.e. fast flash group every second. Presumably this is waiting for a new time to be uploaded from the Mac using the picoyncTime.py script.

Having got that running I went back to picoyncTime.py and ran that. I unplugged the pico and restarted Thonny and then stopped the main.py before trying picoyncTime.py again

I must be doing something wrong but can't figure what. Any ideas?

DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Re: Sync Pico RTC with host computer

Mon Feb 01, 2021 3:24 pm

dougg0 wrote:
Mon Feb 01, 2021 11:51 am
Hi. I went through this with , i think, a fine-tooth comb but get an error . . .

picoSyncTime needs to be run on your Mac (the host computer) and requires that you have installed pyserial on the host computer (you are getting 'ImportError: no module named 'serial'' because pyserial is not installed on your host computer).

pyserial is a cross platform serial communications library. You can find more information on pyserial here https://pyserial.readthedocs.io/en/latest/pyserial.html, but to install just enter the following on your Mac command line.

Code: Select all

python3 -m pip install pyserial

NOTE: Failure to mention the pyserial dependency was on oversight on my part, I have updated my initial post accordingly.
Last edited by DWiskow on Wed Feb 03, 2021 1:35 pm, edited 1 time in total.

dougg0
Posts: 4
Joined: Mon Feb 01, 2021 11:37 am

Re: Sync Pico RTC with host computer

Mon Feb 01, 2021 5:32 pm

Thank you so much for your response. Yes I did do something wrong didn't I. As they say: "read the question"

One thing: I had to use

Dougs-iMac:~doug$ python3 -m pip install pyserial
Collecting pyserial
Downloading pyserial-3.5-py2.py3-none-any.whl (90 kB)
|████████████████████████████████| 90 kB 3.7 MB/s
Installing collected packages: pyserial
Successfully installed pyserial-3.5

Now smiling again instead of scratching my head.

Best wishes
Doug

DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Re: Sync Pico RTC with host computer

Tue Feb 02, 2021 2:17 pm

dougg0 wrote:
Mon Feb 01, 2021 5:32 pm
Thank you so much for your response . .
You might be interested to know that we have now also cracked setting the RD2040 Hardware RTC directly from python on the host computer (i.e. with no need to have any special code running in the Pico to manage a timeDelta)) . . .

. . . have a look at this post (viewtopic.php?f=146&t=300275#p1810708) which explains how to set the Raspberry Pi Pico hardware RTC by running a python script on the host computer only.

dougg0
Posts: 4
Joined: Mon Feb 01, 2021 11:37 am

Re: Sync Pico RTC with host computer

Tue Feb 02, 2021 8:19 pm

That's pretty good. Thanks. I presume you could transfer any code in the same way. I'll give that a go.

DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Re: Sync Pico RTC with host computer

Wed Feb 03, 2021 10:10 am

dougg0 wrote:
Tue Feb 02, 2021 8:19 pm
I presume you could transfer any code in the same way . . .
Yes . . . but, it is worth noting that the mechanism to inject And run MicroPython code on the Pico from a host computer ( https://www.raspberrypi.org/forums/vie ... 5#p1810708) doesn’t save any code on the Pico. What is actually does is transfer the code to the MicroPython interpreter, which loads it into RAM memory and executes it.

This mechanism is the way in which tools like Thonny and rshell ( https://github.com/dhylands/rshell/tree/pico) interact with the Pico (and other MicoPython based boards).

To achieve the functionality they offer, they have constructed lots of ‘little code snippets’ (MicroPython programs) that are injected on demand onto the target board, which they then interact with through their software running on the host computer. It’s is a quite simple, but very sophisticated concept, conceived by Damien George the original creator of MicroPython.

So, to save a file onto the Pico, you would have to inject a MicroPython program to the Pico that had the contents of the file embedded in a list within it . . . and then, when executed automatically following injection, the program would write the contents of the list to the file on the Pico (and handle/communicate any issues or errors back to the host computer) as required.

dougg0
Posts: 4
Joined: Mon Feb 01, 2021 11:37 am

Re: Sync Pico RTC with host computer

Thu Feb 04, 2021 9:59 pm

Thanks again and sorry for taking a couple of days to respond. Yes I did figure that out about the code running. I shall experiment a bit to see what I can do.

joneslw2
Posts: 1
Joined: Fri Mar 12, 2021 10:54 pm

Re: Sync Pico RTC with host computer

Fri Mar 12, 2021 10:58 pm

After successfully syncing the time on my pi pico, I am having trouble implementing the date and time within my code. Every time I try importing the function it overrides the code and displays the time every 5 seconds. However, the rest of the programme will not run. How would I implement this without it overriding the main.py code

DWiskow
Posts: 56
Joined: Sun Apr 09, 2017 1:56 pm

Re: Sync Pico RTC with host computer

Sat Mar 13, 2021 1:56 pm

joneslw2 wrote:
Fri Mar 12, 2021 10:58 pm
Every time I try importing the function ...

The code provided above is not designed to be imported into your MicroPython program on the Pico. It is an example of MicroPython code that will work with the code (also provided) running on a host computer with which you wish to sync the date and time . . . You should study the code to understand it, and then incorporate it into you own code as required.

If you want something simpler, have a look at this viewtopic.php?f=146&t=300275#p1810708 . . . it runs on the host computer, syncs an attached Pico to the host computers date & time, then automatically restarts any code/program that exists in main.py on the Pico . . . all requiring no changes to, or additional, code on the Pico itself !

Return to “MicroPython”