AWatchDogTimer (WDT) is a hardware timer that is used to detect and recover from errors in our programs or faults in their execution. Once initiated, a watchdog timer is constantly counting down and when (orif) it reaches zero, it reboots our device. The only thing that stops the timer reaching zero is periodic resetting of the timer back to its starting position. We place lines in our code at strategic points that perform this reset, so that under normal operation the timer should never reach zero. These resets are referred to as ‘patting the dog’, ‘feeding the dog’ or cruelly, ‘kicking the dog’ (not happy about that one).
While we aren’t going to purposely design our software to freeze, strange things can happen (cosmic rays - really!) and it is often practical to prepare for the unexpected. Conversely, you might notice that your device hangs for no apparent reason after long periods. Weird stuff does happen. When it’s more important that the system keeps functioning than it is to troubleshoot the problem, a watchdog timer could be your friend.
In the Raspberry Pi Pico or more precisely the RP2040, the watchdog has a 24-bit counter that decrements from a user defined value. The maximum time between resetting the watchdog counter is approximately 8.3 seconds before it reaches zero and reboots our device.
In a very simple code example from the MicroPython documentation we can see the watchdog timer library loaded, the timer is enabled with a time of 2000 milliseconds (2 seconds) and then the watchdog is fed.
frommachineimportWDTwdt=WDT(timeout=2000)# enable it with a timeout of 2swdt.feed()
In our code we would set our timer appropriate for the occasion and place the feeding statements in strategic places so that under normal circumstances, there shouldn’t be a situation where it would run down for more than the specified amount of time before being fed again.
The on-board LED on the original Pico corresponds with GPIO pin 25, but this was changed to be connected to one of the GPIO pins from the wireless chip (CYW43439) on the Pico W. The examples used in the Raspberry Pi Pico Tips and Tricks book use code suitable for the Pico W and to adapt any of that code for the Pico we need to change ‘LED’ for 25 in the following code example;
However, as responsible engineers with an eye to the foibles of uncertain hardware changes, it might be useful if we had some code that would allow us to illuminate the LED independent of which board we were using. Well good news, we can utilise the board class of functions that will allow us to determine just which type of Pico we are using and this will let us set the LED pin appropriately. The following code demonstrates this;
A Real Time Clock (RTC) is a crucial component for any microcontroller-based system that needs to keep track of time. Ostensibly this would then allow the system to maintain time even when the system is powered off or reset.
An RTC is a small, clock circuit that is designed to keep track of the current date and time. It typically includes a clock crystal oscillator, a battery, and a small amount of non-volatile memory for storing the time and date information.
Typically RTC’s will be separate modules that can interface with a microcontroller using a variety of communication protocols such as I2C, SPI, or UART to read and write the date and time information. The RTC provides accurate timekeeping for the microcontroller and can be used to timestamp events, trigger time-based events, and schedule tasks.
An RTC is especially useful for systems that require time-sensitive actions such as data logging, scheduling, and timing critical operations. It can also be used to implement features such as alarms, timers, and watchdogs (used to facilitate automatic correction of temporary hardware faults).
Overall, an RTC is an essential component for any microcontroller-based system that needs to keep accurate track of time, even when power is lost or the system is reset.
The RTC on a Raspberry Pi Pico
The RP2040 chip in the Raspberry Pi Pico incorporates a Real Time Clock internally. This derives an accurate time from a reference oscillator (internal by default, although an external reference is possible) and a fixed start time (which in the Pico appears to be initialised to start on the 1st of January 2021.
This is great, but there is a bit of a caveat. When the Pico is first started, without an external reference point it will default to the time being the 1st of January 2021. The worst case scenarios for this type of set up is when there is a power interruption and the time gets reset. It can be overcome in many external modules by utilising a battery backup that preserves the timing circuit, but this is not built into the Pico.
Therefore, it is useful to find a method to synchronise the Pico with an external time source to ensure that the time is accurate. This can be most easily accomplished by using a WiFi connection on the Pico W to use the Network Time Protocol to find the correct time.
From there we can use Greenwich Mean Time (GMT) (now referred to as Coordinated Universal Time or Universal Time Coordinated (UTC)) to know what time it is.
Hang on a minute I hear you say. I want to know what the time is in the country where I am running my Pico! I hear you and I acknowledge your concerns. Sadly this turns out to be way more difficult that it seems at face value. It appears that keeping track of local times is a complex job more suited to super computers and rooms full of frustrated programmers with sleeping disorders. In short, we need to learn to embrace UTC and where required to convert to our respective local times we do it as required (i.e programmatically in a script or spreadsheet. This is the only way we preserve our sanity.
The Code
The following code connects to our local WiFi network (using the secrets file to set all the appropriate network particulars (see the WiFi section for details)). From there it connects to a NTP server, pulls a time value and sets the Pico’s RTC. Then it goes about logging a timestamp every 30 seconds and flashing the on-board LED every time it writes a value to memory.
importnetworkimportsocketimporttimeimportstructimportmachinefromsecretsimportsecretsNTP_DELTA=2208988800host="pool.ntp.org"rtc=machine.RTC()defset_time():# Get the external time referenceNTP_QUERY=bytearray(48)NTP_QUERY[0]=0x1Baddr=socket.getaddrinfo(host,123)[0][-1]s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)try:s.settimeout(1)res=s.sendto(NTP_QUERY,addr)msg=s.recv(48)finally:s.close()#Set our internal timeval=struct.unpack("!I",msg[40:44])[0]tm=val-NTP_DELTAt=time.gmtime(tm)rtc.datetime((t[0],t[1],t[2],t[6]+1,t[3],t[4],t[5],0))wlan=network.WLAN(network.STA_IF)# Set up Wifi connection detailsssid=secrets['ssid']password=secrets['pw']rp2.country('NZ')# change to <your> country codeip=secrets['ip']netmask=secrets['netmask']gateway=secrets['gateway']dns=secrets['dns']# Connect to Wifiwlan.active(True)# activate the interfaceifnotwlan.isconnected():# check if connected to an APprint('Connecting to network...')wlan.connect(ssid,password)# connect to an APwlan.ifconfig((ip,netmask,gateway,dns))whilenotwlan.isconnected():# wait till we are connectedprint('.',end='')time.sleep(0.1)print()print('Connected:',wlan.isconnected())else:print("Already connected!")led_onboard=machine.Pin('LED',machine.Pin.OUT)led_onboard.value(0)file=open("timestamps.txt","a")#Set our RTCset_time()# Log some timewhileTrue:timestamp=rtc.datetime()timestring="%04d-%02d-%02d%02d:%02d:%02d"%(timestamp[0:3]+timestamp[4:7])print(timestring)file.write(timestring+"\n")file.flush()led_onboard.value(1)time.sleep(0.01)led_onboard.value(0)time.sleep(30)
For general use we would replace the data logger portion of the code to allow it to carry out whatever task we desired that included accurate time!
What gives? My Pico appears to have accurate time already!
For those who (like me) were a bit confused when not only did their Raspberry Pi Pico return accurate time while it was connected to my computer, but it returned it in accurate local time. There is a cool reason for this.
A change in the code for Thonny was introduced which allowed a small piece of code to be executed on a host computer (Windows, Mac or Linux) that will automagically find a connected Pico and then synchronise its date and time.
No MicroPython code needs be added or running on the Pico for this to work. It works by injecting a small MicroPython script, which it modifies on the fly with the host computers UTC, into the Pico over the USB serial link using the RAW REPL functionality of MicroPython! how about that.