Ceci est une ancienne révision du document !
More fun with dates and time Greetings fellow Beings. Yet again, I come to you from an undisclosed location somewhere in time and space. Yes, I am a fan of all things Doctor Who, Star Trek, Star Wars, and other things. Anyway, last month we looked at the subject of time change from “standard” time and “daylight saving” time and some of the issues that come with that on a Microcontroller. I promised that we would continue that subject. So here we go with a reminder of some of the issues. First, the ntptime module, used to get the network time, has a small problem when you make too many calls to it. The server simply tells you to go away after a while and you have to start all over again. I also gave you a short snippet to use the portable version of ntptime from Peter Hinch. I also talked about the fact that there are two functions that provide the current time (once it’s set) named gmtime and localtime, and the fact that they both give GMT time. There is no timezone information handled by either of these functions. So let’s talk about some of the possible remedies available to us.
In my search for an easy solution, I came across the fact that the MicroPython group has been working on creating a large library of modules that are useful for programmers writing MicroPython programs. Many of them attempt to mirror standard libraries in the Python world. One of these modules is the datetime module. MicroPython has suffered from the lack of this being in the builds. Well, now, the wait is over (at least for the most part). By using the micropython-lib datetime module in our programs, we can, with a few modifications, use “normal” python code in our MicroPython programs. Of course you have to have the datetime module “installed” on your device. There are few ways of doing this. One is my preferred way of getting the entire source code package and copying the necessary modules onto my device. By doing this, I can make sure that any of the dependencies are available and I can examine the code to see how that programmer (or group of programmers) got their code to work. Also if there are any errors being thrown, I can track it down much quicker than relying on a library where I can’t see the source code. You can find the package at https://github.com/micropython/micropython-lib/tree/master and download the entire zip file. Unzip the package into a folder (I use my Downloads folder and unzip it there, since it has the folder already there for me). Once there, you can find the file in the /python-stdlib/datetime/ folder (named datetime.py)
Copy the datetime.py to your Microcontroller device and put it into the /lib folder or, if you don’t have it, either create the folder and place it there, or just drop it into your main folder on the device. (It’s better to put it into the /lib folder.) The other way, which is a bit easier but only provides you the compressed mpy file, is to use mip. Here is a link to using mip: https://www.tomshardware.com/how-to/raspberry-pi-pico-micropython-mip. Anyway, I haven’t had a chance to fully explore all the functions available, but for this month, we’ll use the datetime library to get the datetime.now function. You will call it like this : my_timezone = timezone(timedelta(hours=10)) current_time = datetime.datetime.now(my_timezone) Of course, you need to import the library before you can call it, but we’ll see that in this month’s first project. If you are a “regular” Python programmer, you will recognize the second line, which uses the datetime.datetime.now() method.
So, for this month’s main project, we’ll connect to the Internet (be sure you’re using a RPi Pico-W), use Peter Hinch’s portable NTPTime module, get the network time, set the Real Time clock on the Pico-W, and then start printing the time in the REPL once every 10 seconds. I’ve named the program ‘timetestFCM1.py’. Make sure that you have the datetime.py or datetime.mpy file either in your main device’s folder or in the lib folder. All of the other libraries needed are “standard” libraries, except for Peter’s portable NTPtime library. I’ve got that in the repository listed at the end of this article. The Code First, we’ll need a secret.py file. This will hold your SSID and your network password. I use this to make sure that if I ever share a project that uses networking, that my network information isn’t exposed in the code. (It’s in the repository, so all you need to do is to make sure you edit it once it’s on your device). It looks like this… # secret.py # ========================== SSID = {Your Network Name Here} PASSWORD = {Your Network Password Here} Really simple huh?
Moving on. Now we’ll need Peter’s portable NTPTime routine. That’s also in the repository saved as port_ntptime.py. Make sure that’s also on your device. Now (top right) we’ll start digging into the timetestFCM1.py project. First the imports. It will seem to be a REALLY big number of imports, but it’s not much. Next comes the connectNetwork function. This is a fairly straight forward function that I reuse often. First, I set up the onboard LED of the Pico (name it “led”), then make sure it’s off. Next I start to set up the network modes, send in the SSID and Password to the wlan object and loop until we get connected. Once we are connected to our local network, we turn the onboard LED on (next page, top right). Next we have the settime2 function. It’s very similar to the one defined in the NTPTime module, but this one will return a 0 if, for some reason, it can’t set the time correctly. We get the time and date tuple by sending the number of seconds since our EPOCH (from the network time server) to utime.gmtime and then set the software real time clock with that value. If everything worked correctly we return a True, otherwise return a False (next page, top left).
Finally, we get to begin to play with the datetime module we went to “so much trouble” to get. First we need to set a value for our timezone, which in my case is -5 hours from GMT. Once we go through the time change again, this will be a -6 until the next time change. Then we take that and use it to seed the datetime.datetime.now() function, which returns a time string like this… 2024-04-07 02:49:10-05:00 We’ll get into formatting that next month. That’s it for all of our support functions. Now we have the main routine. This makes calls to the various functions that we’ve already discussed. FIrst, I define the two timezone offsets used here where I live. Cst is 6 hours behind GMT (starting in the Fall) and cdt is 5 hours behind (Starting in the Spring). I multiply the number of hours by 3600 (The number of seconds in an hour) and since we are behind GMT, I use a negative number.
cst=-6*3600 cdt=-5*3600 Next I get the Epoch which is where my device bases the number of seconds from in order to “decode” the value sent from the NTPServer. The Pico uses January 1, 1970. Other devices use January 1, 2000. But that actual date is January 1, 1900. Knowing this can help if there are any errors. After that, I get the time that the device thinks the time is. EPOCH = time.gmtime(0)[0] print(f“{EPOCH=}”) rtc=machine.RTC() dti=rtc.datetime() print(f“{dti=}”) Now, I threw in a quick check to make sure this program was running on a Pico-W. If not, well, there is no need to continue on, since we can’t connect to a network. We simply call sys.exit() if it isn’t a Pico-W. # Check to see if the Pico has network which=GetWhichPico() if which == False: sys.exit()
Now we call the connectNetwork function. # Connect to the network connectNetwork() Now that we are connected, we can try to get the time (in seconds) from the NTP server. This is fairly simple. Once we are in the loop, we make a call to Peter’s portable ntptime function. It will either return the time value from the NTP server or a 0. If the value is greater than zero, we do a quick garbage collection (to get rid of any unneeded stuff), and call the settime2 function with the proper timezone offset. If the call to settime2 is successful, we set the loop variable to False, otherwise we sleep for 2 seconds (next page, top left). At this point, we can pretty much safely assume we got the Network time. Now all we need to do is print the time.gmtime and time.local time to the REPL, then print the return from showMyTime (bottom left). If you are old enough to remember “Y2K”, you’ll be either happy, or scared, to know that in 2038, there will be another one. Hopefully, we will be more ready for that issue than we were back in 1999. We’ll talk about that next month. The repository for this month is located at https://github.com/gregwa1953/MTMT204 . Until next time, as always; stay safe, healthy, positive and creative!