Showing posts with label NodeMCU. Show all posts
Showing posts with label NodeMCU. Show all posts

Friday, May 15, 2026

NTFY part 2: Send notifications with ESP32 and Pico

For an index to all my stories click this text.

This is the second story about NTFY. The first story showed what NTFY is and how it can send notifications and messages to your Android smartphone from a PC dashboard.

This story shows how you can send notifications from your EP8266 or ESP32 in Arduino language (C++) to your phone, and how you can do that with a Raspberry Pi Pico in MicroPython.

So before you go on I recommend reading the previous story which you can find here: https://lucstechblog.blogspot.com/2026/05/notifications-with-ntfy.html

I'll start with sending a message from the Raspberry Pi Pico as a notification to a smartphone.

For your convenience I hereby give you the link to the NTFY website: https://ntfy.sh/

Limits and solution

First I hope you remember that with the free service NTFY there is a limit of 250 messages per day.
 
The messages remain for 12 hour on the server.
This means that if your phone is off, or has no internet connection, for 13 hours you will miss messages.

There are two solutions for this.
First you can get a paid subscription and then you get a lot more messages each day.
The second solution is to install your own NTFY server. You can do that on a Raspberry Pi (even the humble Zero) and then you can decide how many messages you can send per day  and how long they stay on the server.

Mind you: 250 messages per day is about 10 messages per hour which would be more than sufficient for most projects.

Nevertheless I chose the second solution and installed my own server. Maybe something for another story ........................

Sending a message from MicroPython with a Pico 

(Scroll down for the ESP32 arduino version)

We are going to do this the easy way. We are going to attach a button to the Pico and simulate that it is a door contact. Everytime the button is pressed the Pico will send a notification to the phone.

We are going to send an alarm with the text:

The door opened X times

The X will alter each time we press the button.

Let's start with the breadboard setup which is really easy.



It is just the Raspberry pi pico with a button attached to GP14. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).

Here is the complete program.

import machine
import network
import urequests as requests
import time

button1 = machine.Pin(14, machine.Pin.IN)
dooropen = 0

# Router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "YOUR-PASSWORD"
print("Connecting to wifi...")

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

# wait for connection
while not wifi.isconnected():
    pass

print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))

while True:
    if button1.value() == 0:
        dooropen = dooropen + 1
        sendstring ="The door opened " + str(dooropen) + " times"
        requests.post("http://ntfy.sh/lucstechblog",
        data= sendstring              
        )
        print("Data is send. dooropen = "+str(dooropen))
        time.sleep(3)

Let's have a look at the program in some detail.

import machine
import network
import urequests as requests
import time 

These are the libraries that are needed to get the program running. They are all included in the standard MicroPython distributions. So no need to download libraries.

button1 = machine.Pin(14, machine.Pin.IN)
dooropen = 0

The button is attached to GP14 and defined as a variable with the name button1. An extra variable with the name dooropen is defined. This will be used to count the number of times you press the button.

# Router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "YOUR-PASSWORD"
print("Connecting to wifi...")

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

# wait for connection
while not wifi.isconnected():
    pass

print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))

Nothing special here. These are the standard program lines to connect the Pico to your router. Don't forget to replace YOUR-ROUTERS-NAME and YOUR-PASSWORD with the required values for your router.
When the connection is established you will find the Pico's IP number in MicroPython's shell.

while True:
    if button1.value() == 0:
        dooropen = dooropen + 1

The while loop is where the actual action takes place.
First the program tests if the button is pressed. If so then the variable dooropen is increased by 1.

        sendstring ="The door opened " + str(dooropen) + " times"

In this line we prepare the text that is going to be send.
This is the important line. Here you can fill in any information you like to send. If you would add a digital thermometer and put it's value in the variable temp you could alter the text like like this:

        sendstring ="The temperature is now " + str(temp) + " degrees"

On to the next part.

        requests.post("http://ntfy.sh/lucstechblog",
        data= sendstring              
        )


NTFY needs a post request in stead of the get requests which we normally use. We post to the site http://ntfy.sh/ and the topic is lucstechblog.

        print("Data is send. dooropen = "+str(dooropen))
        time.sleep(3)


Next we print a confirmation in the shell and wait a few seconds to make sure the request is send.

That is all.

The result.

Run the program. Press the button.



And this is what you'll see in Thonny's shell.



And here is how I got a notification in the top left corner of my phone's screen. My phone also gave an audio signal to draw my attention to the notification.



This is how the notification appeared on my phone's screen



And this is how it looks in the NTFY app on my phone.

At the same time the message appeared in the PC web version of NTFY.







Sending a message with an ESP32 in Arduino language (C++)

Just like we did with the Pico and MicroPython, we are going to do this the easy way. We are going to attach a button to the ESP32 and everytime the button is pressed the ESP32 will send a notification to the phone.

We are going to send an alarm with the text:

The button attached to the ESP32 was pressed X times.

The X will alter each time we press the button.

Let's start with the breadboard setup which is really easy.



It is just the ESP32 with a button attached to D22. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).

Here is the complete program.


#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";

//Where to send the notification
const char* ntfyurl = "http://ntfy.sh/lucstechblog";

const int buttonPin = 23;
int butpress = 0;

void setup() 
  {
  pinMode(buttonPin, INPUT);  
  
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) 
    {
      delay(500);
      Serial.print(".");
    }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
  }

void loop() 
{
    if (digitalRead(buttonPin) == LOW) 
      {
      butpress = butpress + 1;  
      if(WiFi.status()== WL_CONNECTED)
        { 
      WiFiClient client;
      HTTPClient http;
    
      // Your Domain name with URL path or IP address with path
      http.begin(client, ntfyurl);
      http.addHeader("Content-Type", "text/plain");
      
      // Build the text to send with HTTP POST:
      // The button attached to the ESP32 was pressed X times.
      String httpRequestData = "The button attached to the ESP32 was pressed "; 
      httpRequestData = httpRequestData + butpress;
      httpRequestData = httpRequestData + " times";  
      
      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      Serial.print("The response we got : ");
      Serial.println(httpResponseCode);
        
      // Close connection
      http.end();

      // Wait before the next round
      delay (3);
        }
      }  
}


Lets look at some details in the program.

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR-ROUTERS-NAME";
const char* password = "PASSWORD";

//Where to send the notification
const char* nyfyurl = "http://ntfy.sh/lucstechblog";

const int buttonPin = 23;
int butpress = 0;

Nothing special here. The necessary libraries are loaded and The variables are defined. The variable ntfyurl is defined as http://ntfy.sh/lucstechblog which is the address of the NTFY server and the topic.

The setup() has nothing unusual.

The loop() is where the fun begins.

    if (digitalRead(buttonPin) == LOW)
      {
      butpress = butpress + 1;  
      if(WiFi.status()== WL_CONNECTED)
        {
      WiFiClient client;
      HTTPClient http;

The program continually tests if the button is pressed. If so the butpress variable is increased by 1 and the wifi and http clients are activated.

      // Your Domain name with URL path or IP address with path
      http.begin(client, ntfyurl);
      http.addHeader("Content-Type", "text/plain");

The http communication with the NTFY server is started with the previous defined ntfyurl. A header is sent first that identifies the data we are going to send as plain text.

      // Build the text to send with HTTP POST:
      // The button attached to the ESP32 was pressed X times.
      String httpRequestData = "The button attached to the ESP32 was pressed ";
      httpRequestData = httpRequestData + butpress;
      httpRequestData = httpRequestData + " times";

The text "The button attached to the ESP32 was pressed X times." is build here by combining several parts. One of the parts that is added is butpress which is the variable that counts how many times the button was pressed.

      // Send HTTP POST request
      int httpResponseCode = http.POST(httpRequestData);
      
      Serial.print("The response we got : ");
      Serial.println(httpResponseCode);
        
      // Close connection
      http.end();

The request is send as a http POST request with the previous defined httpRequestData. The request receives a response with an indication if it has succeeded. The response is then printed in the serial monitor. After sending the request the connection is closed.

      // Wait before the next round
      delay (3);


The program then waits for 3 seconds. This time can be shortened but a short delay is preferred to prevent detecting a bouncing button as a button press.

It is obvious that this code can easily be adapted to send sensor readings etc. etc. etc.



This is what the Serial Monitor shows. As you can see there are 4 responses with the number 200 that means that the request was received ok.



And here are the notifications I received. As you can see I subscribed to 6 topics. The topics were made just for testing.

Expansion

In this example I use the same topic all the time: lucstechblog. It is of course possible to create multiple topics. So a single Pico or ESP can send notifications to several topics. However you can also have multiple microcontrollers sending data to several topics.

In the above examples we send notifications with just one line of text. You can send notifications with multiple lines of text. The documentation of NTFY shows how to do this. You can find the documentation here: https://docs.ntfy.sh/

Even better: you can attach files to a notification. These can be text files but also pictures !! I have successfully experimented with sending pictures from C++ and from MicroPython. I can see a chat program coming up...........

You can have the Pico's and ESP's send notifications to several NTFY servers.
On the NTFY documents pages there is a list of public NFTY servers. You can find the docs and that list here: https://docs.ntfy.sh/integrations/

You can start your own private server. A Raspberry Pi is sufficient. Even a humble Raspberry Pi Zero will do.
Using your own private server does not expose your topics (if someone finds them) and their data to a general audience. It restricts the information to those you have given the information about the server and it's topics.
On a private server you can expand the lifetime of the messages from 12 hour to any timelimit that suits you. And the number of messages you can send per day can be limitless !!!

Not only can you send notifications but using the right API call you can also get all notifications that have been send with a certain topic from the server. This way you can have two-way conversation between microcontrollers. A microcontroller can retrieve the messages on a certain topic from the server, and can act on that, and then send a notification with the same or a different topic. You do need a private server for this.

If you want a story on sending multiple line notifications, sending a textfile or a picture with the notification, starting your own server on a Raspberry Pi or retrieving notifications from your private server please send me an email.

I can see loads of possibilities with NTFY and therefore already installed my own private server.

Till next time.
Have fun
Luc Volders

Friday, May 1, 2026

Notifications with NTFY

For an index to all my stories click this text.

When working with IOT projects several things can happen. A certain temperature is reached, movement is detected, a light is set on in a room, someone is at the door etc. etc.etc. When something like this happens you will want to get a notification. You can, of course, build a website on which values are shown. But that implies that you need to go to that website to look at the values.

It is more efficient when you get a notification (an alarm) on your smart phone.



A notification like this is put on the startscreen of your phone so it will always draw your attention.

There is a free service that you can use to get these notifications it is called NTFY
You can find the website here: https://ntfy.sh/

NTFY

NTFY is of course short for NoTiFY. It is a free service that you can use. 

There is a limit of 250 notifications per day for a free or anonymous account. That is 10 messages per hour !!!

If you need more than 250 messages per day then you need to get a paid subscription.

To use NTFY you need to download a (free) app on your phone or tablet. But there is also a desktop (PC) version that can receive messages but can also send messages.

To send notification messages to your phone, tablet or PC there is a simple to use API that can be used with Arduino (C++) and MicroPython.

For using the free version you do not have to log-in or make an account. You can just use it. That is a bit like dweet.

Another similarity to Dweet is that a message/notification consists of two parts: a topic and the message itself. To get the notifications on your Phone or PC you need to "subscribe" to that topic.
A topic might be for example "Alarm" and the message can be "The garage door is open". Another topic might be "Myhome" and a message could be "The temperature = 22 degrees"

You may create as many topics as you like as long as you do not exceed the limit of 250 messages. A topic is created automatic when you send a message with your microcontroller that includes a non existant topic.

And yet another similarity to Dweet is that (unless you have a paid account) the topics are public. This means that anybody can get your messages and notifications as long as they know the topic you are using.
So use a cryptic topicname like LV23kit where LV are my initials, 23 is the year (2023) and kit means that the messages concern my kitchen. Just be creative.

If you need private topics you will need to get a paid plan.

The big difference with Dweet is that NTFY can send notifications to your phone/tablet/pc. Dweet can not send them, you need to collect them yourself. So for sending alarms NTFY is the best option.

There is one extra option that might prove usefull. NTFY can also send emails. So you can get your messages in your mailbox. For alarms that is not really an option as you want an instant notification if something is wrong. However it might be usefull for some of you so I will show how to use this option. With the free version you can send 5 emails per day.

One more thing though. The messages/notifications are stored for 12 hours. After 12 hours the messages disappear.

NTFY on the PC

First thing we are going to do is to get NTFY on your PC. Well that is easy. Just point your browser to https://ntfy.sh/app and you're done.



This is how the webpage looks..



Click on + Subscribe to topic and a window opens that allows you to enter the name of a topic.
Like stated before, for an anonymous (and free account), topics are public so choose a topic name that others can not guess easily.



You can also click on GENERATE NAME and NTFY will generate a topic for you that closely resembles a password.
This will give you some better privacy and secrecy but is more difficult to use on multiple devices at the same time. If, for example, you are using NTFY at the same time on your PC and on your smart phone you will need to find a way to send this cryptic topic name to your phone.

I choose a topic name myself: lucstechblog

Then click SUBSCRIBE.



This is how your screen will look now. On the left there is a list of subscribed topics. At this moment there is just one: lucstechblog. In the center there is a message that no notifications have been send or received with this topic.

NTFY on the Android Phone

To get notifications we need to install the NFTY app from the playstore. You can find it here:
https://play.google.com/store/apps/details?id=io.heckel.ntfy
Or just search for NTFY in the app store.



Install the app and open it.





It looks almost the same as the PC version. 





Press the + at the bottom of the screen for subscribing to a topic. We will use the same topic: lucstechblog
A big difference from the PC version is that there is no option to have NTFY generate a topic for you. This is because the phone version is only used for receiving notifications.

We now have 1 subscription to a topic.

Sending a message from the PC

Click with your mouse on the subscribed topic (lucstechblog)



And at the bottom type a test message like I did. Then click on the small arrow next to the message.



The PC screen will inform you that the message is send.



And you will almost immediately get a notification on your phone.
This is the important part. This shows that we can get alarm messages and other important messages as a notification on our phone.



And the NFTY app will inform you that a notification has been received.
And shows message also in the app.

First steps done.

The first setup is done.

Make yourself comfortable with the concept and create some topics for yourself and play around a bit.

Next time we are going to send notifications from the ESP32 using Arduino language (C++) and from the Raspberry Pi Pico with MicroPython.

A few small tips

You can use the browser version next to the app on your Phone. Just point your browser to: https://ntfy.sh/app That way you can also send messages from the phone that will be received by the PC. You will not get notification alarms through the browser but you will still get them through the app.

You can use NTFY on multiple phones and tablets. As long as they all subscribe to the same topics, they will all get the same notifications/messages.

And please remember that you can make as many topics as you like but there is a limit of 250 messages per day for the free account. The messages are stored on the server for 12 hours after which they vanish.

Although you can create loads of topics it is better and easier to maintain if you just use a few topics and make the messages in the topics more verbal.

Next story covers how to send notifications from your ESP32 with Arduino language (C++) or Raspberry Pi Pico W with MicroPython


So Till next time
have fun


Luc Volders











Friday, January 30, 2026

Easy AI with MicroPython

For an index to all my stories click this text

This story tells how to use a free (no sign-in) API to connect to an AI system with MicroPython. The program is tested both on a Raspberry Pi Pico W and Pico 2W. But it should run on an ESP8266 or ESP32 with MicroPython equally well.

Like I said in previous stories on this weblog: I love playing with AI.
In one of the previous stories I wrote how to install a LLama (a complete AI system) on a Raspberry Pi. You can read that story here:
https://lucstechblog.blogspot.com/2026/01/run-ai-models-local.html

That works great but the Llama's (Language models) are limited because the memory of the Raspberry Pi is limited. The AI systems we access through our browser like ChatGPT, Copilot, Gemini, Grok etc. are multi million dollar systems with hundreds of Gigabytes (GB) memory.

And then I found a very simple API that allowed connecting to one of the cloud based large models.
The APi is so simple that I could use it with MicroPython and with Javascript.

This story tells how to use it with MicroPython. The next story shows how to use it with Javascript.

The API

The API call looks like this:

http://nimaartman.ir/science/L1.php?text=:HERECOMESTHEQUESTION

If you want to try it (and fill in some real question) you can just put it in your browsers URL and press enter.

As you can see, after "text=:" comes the actual question. But there are no spaces allowed in the question. So our program needs to filter them out.


This works in your browser however the answer looks like this:
data    "🤔💭 What’s your question? 🚀✨"

It is JSON coded with emoticons and other characters.
I want to filter these out, so our program needs to take care of that too.

So here is the complete program in MicroPython.

'''
program to get data from an ai system
'''

import network
import urequests
import ujson

# Router credentials
ssid = "YOUR-ROUTERS-NAME"
pw = "Routers-PAssword"
print("Connecting to wifi...")

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

# wait for connection
while not wifi.isconnected():
    pass

# wifi connected
print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))

question = "Translate 'twee' from dutch to german"
question = question.replace(' ','')

url = "http://nimaartman.ir/science/L1.php?text="
url = url + question

# Send the GET request
response = urequests.get(url)

try:
    # Attempt to parse the JSON response
    response_str = response.text
    data = ujson.loads(response_str)

    # Extract the text field from the JSON data
    text_with_unicode = data.get("data")

    ## Clean the unicode text
    cleaned = ''.join(ch for ch in text_with_unicode if ord(ch) < 128)
    print(cleaned)

    response.close

except ValueError:
    # Handle the case where the response is not valid JSON
    print("Error: The response is not valid JSON or the server returned an error message.")
    print("Raw response2:", response.text)
    response.close


Let us have a look at some parts of the code.

The program starts with iporting the necessary libraries (that are included in the MicroPython instalation).

ssid = "YOUR-ROUTERS-NAME"
pw = "Routers-PAssword"

Don't forget to replace YOUR-ROUTERS-NAME and Routers-Paswword with the credentials of your router.

The program then connects to the internet and shows the IP Number the microcontroller got from the router.

question = "Translate 'twee' from dutch to german"
question = question.replace(' ','')

The question I used as a first test is to translate 2 (two) into German.
The next line replaces all spaces with an empty string and so effectively removes the spaces. This is needed for the API to work as discussed earlier.

url = "http://nimaartman.ir/science/L1.php?text="
url = url + question

This is where the API call is constructed.

# Send the GET request
response = urequests.get(url)

The urequests library sends the API call and gets an answer which is stored in the variable response

    # Attempt to parse the JSON response
    response_str = response.text
    data = ujson.loads(response_str)

    # Extract the text field from the JSON data
    text_with_unicode = data.get("data")

The first part decodes the JSON code in the response variable and puts that in the data variable.

The second part gets the answers actual text. It is put in the text_with_unicode variable as it still contains all the unicode characters like emoticons etc.

    cleaned = ''.join(ch for ch in text_with_unicode if ord(ch) < 128)
    print(cleaned)

Now this looks coplicated but in fact really isn't.
We start with and empty string. In that we put all the characters (ch) if their ascii value is less then 128 (ord(ch) < 128)

And then we print the cleaned text.

Copy the code from this page and paste it in Thonny. Save it with an appropriate name and run the code.

Some examples.


Here is what I received when I asked to translate the Dutch word "twee" into German


And here I asked to translate "hello" into Japanese.


And here I asked what the book with the title "This perfect day" is about.
The description is brief but correct while not giving away the plot !!!

Small side-note from me: it is about a society that is run by a supercomputer that makes all decisions for humans.
Written by Ira Levin and highly recommended !!


I guess these are enough examples.

If you have a developed a nice project with this: let me know.

Till next time
Have fun

Luc Volders

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