Pages

Friday, January 9, 2026

Perform a daily task

For an index to all my stories click this text.

What's this story about.

This story shows how to get the accurate time from an NTP server and use that to perform a daily task, every day at the same time. The program is written in MicroPython and will work on a Raspberry Pi Pico W as well as on an ESP32 or ESP8266.

A daily task ??

You can use this to set the coffee machine on every day at the same time so you'll have a fresh cup of java every morning when you wake.
Another option is to water your plants every day at the same time when you are on a holiday. Or use this to build an automatic fish feeder that feeds the fish once a day. You could even make an alarm clock that wakes you every day. Plenty of tasks you can use this for. Just use your imagination.


Actually I wrote this story because I got a question on my Discord server from one of my readers, who wanted to know if I found a way to execute a daily task by using the NTP server. As you may have noticed I am no longer on Discord. if you want to reqach me, please do so by mail.

CHAT_GPT

My Discord server had a CHAT-GPT section where you could ask questions to CHAT-GPT. So I asked CHAT-GPT to write a MicroPython program that achieved this. And CHAT-GPT came up with this:


Besides the fact that this code is not going to retrieve the NTP time in any way, there are some issues with it.

- The rp2040 has a RTC in which you can set hours, minutes, seconds, day, month, and year, then read back the current time later. Unfortunately the Pico board clock oscillator is rated at about 30 ppm. Since there are 86400 seconds/day, this means a deviation of up to 2.6 seconds a day. That does not look much however is about 16 minutes a year.

- I showed in a previous story that the NTP time actually is the UTC time which does not take in account your timezone or Dailight Savings Time (DST). 

Corrections

To get this working we need to make several corrections:

- Get the Actual UTC time from an NTP server
- Adjust the time for your timezone
- Adjust that time for DST (Dailight Savings time)
- Do the above every day to correct the internal clock

After these steps we can check for a certain time (hour and minutes) for the task to start.

Timezone and DST

First thing I did is creating a function that uses a timezone as a parameter. That function looks like this:

def settime(timezone):
    global local_time
    rtc = machine.RTC()

    # Set the time from NTP server
    ntptime.settime()

    time.sleep(2)
    # Get the local time
    local_time = time.localtime()

    #adjust for timezone Netherlands
    local_time = time.localtime(time.mktime(local_time) + (timezone*3600))

    # Adjust for DST if necessary
    if is_dst_europe(local_time):
        local_time = time.localtime(time.mktime(local_time) + 3600)

    return

This function depends on another function to adjust the retrieved time for the European DST (Dailight saving time).

# Function to check if DST is in effect
def is_dst_europe(t):
    year, month, day, hour, minute, second, weekday, yearday = t
    print(t)
    # Last Sunday in March
    #dst_start = max(week for week in range(25, 32) if time.localtime(time.mktime((year, 3, week, 1, 0, 0, 0, 0, 0)))[6] == 6)
    dst_start = 0
    for day in range(25, 32):
        if time.localtime(time.mktime((year, month, day, 1, 0, 0, 0, 0, 0)))[6] == 6:
            dst_start = day


    # Last Sunday in October
    #dst_end = max(week for week in range(25, 32) if time.localtime(time.mktime((year, 10, week, 1, 0, 0, 0, 0, 0)))[6] == 6)
    dst_end = 0
    for day in range(25, 32):
        if time.localtime(time.mktime((year, month, day, 1, 0, 0, 0, 0, 0)))[6] == 6:
            dst_end = day

    start = time.mktime((year, 3, dst_start, 1, 0, 0, 0, 0, 0))
    end = time.mktime((year, 10, dst_end, 1, 0, 0, 0, 0, 0))
    now = time.mktime(t)

    return start <= now < end

To call these functions use this line:

settime(1)

Adjust the 1 for your own timezone.


Test if a new day has started

Like described in the beginning of this story the Pico's internal clock has a deviation of about 3 seconds a day. To correct that we will have to the correct time once a day. Here is the code that checks if a new day has started.

# Function to get the current date
def get_current_date():
    current_time = time.localtime()
    return current_time[0], current_time[1], current_time[2]  # year, month, day

# Initialize the previous date
previous_date = get_current_date()

while True:
    current_date = get_current_date()

    # Check if the day has changed
    if current_date != previous_date:
        print("A new day has started!")
        previous_date = current_date

What this code does is checking if the year, month and day of the previous_day variable are equal to the current_date varaiable. If that is not the case then a new day has begun and the previous_date is set to the current_date so the cycle starts anew.


Start a task every day at the same time

Now that we have gotten the exact time we can use that to start our task every day as the same time.

import time

# Function to perform the daily task
def daily_task():
    print("This task runs every day at 10:00 AM")

# Set the target time for the task
target_hour = 10
target_minute = 0

while True:
    current_time = time.localtime()
    current_hour = current_time[3]
    current_minute = current_time[4]

    # Check if the current time matches the target time
    if current_hour == target_hour and current_minute == target_minute:
        daily_task()
        # Wait for a minute to avoid running the task multiple times within the same minute
        time.sleep(60)

    # Sleep for a short while before checking the time again
    time.sleep(1)


This part is easy. We check the current hour which is the 4th entry in the current_time tuple (number 3). Then we check the current minutes which is the 5th entry (number 4). Then these are compared to the hour and time we defined as the starting time. If these are the same the task is started.

The complete program.

All in all this is a lot of code to get a task starting every day at the same time. Below is the complete program in which all the above functions are combined together with the code for accessing the internet.

The NTP server library can be obtained from my previous story which you can find here: https://lucstechblog.blogspot.com/2023/04/getting-right-time-with-micropython.html

import network
import ntptime
import time
import machine

# Set your router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "PASSWORD"

# At what hour and minutes should the task start
target_hour = 22
target_minute = 47

# set the local time to the internal time
# to initialise the local_time variable
local_time = machine.RTC()

# Set the timezone
timezoneadjust = 1

# Start the wifi connection
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, pw)

# wait for connection
print('Waiting for connection.',end="")
while wifi.isconnected() == False:
    time.sleep(1)
    print('', end='.')
print("")

ip = wifi.ifconfig()[0]
print("Connected with IP adress : "+ip)

time.sleep(1)

# set the time from the server
ntptime.settime()

# set date for date checking
current_time = time.localtime()
previous_date = current_time[0], current_time[1], current_time[2]

# ===============================================================
# Function to check if DST is in effect
def is_dst_europe(t):
    year, month, day, hour, minute, second, weekday, yearday = t
    # print(t)
    # Test last Sunday in March
    dst_start = 0
    for day in range(25, 32):
        if time.localtime(time.mktime((year, month, day, 1, 0, 0, 0, 0, 0)))[6] == 6:
            dst_start = day

    # Last Sunday in October
    dst_end = 0
    for day in range(25, 32):
        if time.localtime(time.mktime((year, month, day, 1, 0, 0, 0, 0, 0)))[6] == 6:
            dst_end = day

    start = time.mktime((year, 3, dst_start, 1, 0, 0, 0, 0, 0))
    end = time.mktime((year, 10, dst_end, 1, 0, 0, 0, 0, 0))
    now = time.mktime(t)

    return start <= now < end

#===========================================================
def settime(timezoneadjust):
    # Get the local time
    local_time = time.localtime()

    #adjust for timezone Netherlands
    local_time = time.localtime(time.mktime(local_time) + (timezoneadjust*3600))

    # Adjust for DST if necessary
    if is_dst_europe(local_time):
        local_time = time.localtime(time.mktime(local_time) + 3600)

    return (local_time)

#===============================================================
def testday():
# Function to get the current date
    global previous_date

    current_time = settime(timezoneadjust)
    current_date = current_time[0], current_time[1], current_time[2]  # year, month, day

    # Check if the day has changed
    if current_date != previous_date:
        print("A new day has started!")
        previous_date = current_date
        ntptime.settime()
    else:
        print("Still the same date")
    return


#=================================================
# Start of the actual program
while True:
    current_time = settime(timezoneadjust)
    print("Adjusted time:", current_time)
    testday()
    # print("in the while",current_time)
    current_hour = current_time[3]
    print(current_hour)
    current_minute = current_time[4]
    print(current_minute)
    # Check if the current time matches the target time
    # Then here comes the daily task
    if current_hour == target_hour and current_minute == target_minute:

        print ("Here comes the daily task")

        # Wait for a minute to avoid running the task multiple times within the same minute
        time.sleep(60)

    time.sleep(10)

You can copy this code and paste it in Thonny's editor to transfer it to your microcontroller,

In this example the time for the daily task is set at 22:47. And you need to change the code at where it says: Here comes the daily task to fill in the task you want to have performed.

Expansion

By adding multiple target hours and minutes and use multiple tests in the main part of the program you can use this for scheduling multiple tasks in one day.

Till next time
Have fun

Luc Volders