A Weather Clock (with Alarms) for ESP32 / Raspberry Pi PicoW Implemented With Arduino Framework

by Trevor Lee in Circuits > Arduino

84 Views, 1 Favorites, 0 Comments

A Weather Clock (with Alarms) for ESP32 / Raspberry Pi PicoW Implemented With Arduino Framework

awc.png
pyclock_main_00.jpg

This little microcontroller project AWeatherClock (Arduino Weather Clock) was inspired by pyClock, and is implemented using the Arduino framework.

VSCode with PlatformIO extension is the primarily development environment for the project, in the similar fashion as described by the post A Way to Run Arduino Sketch With VSCode PlatformIO Directly

Naturally, the hardware used for the initial development of the project was exactly the one mention in the pyClock GitHub repository.

Nevertheless, the sketch of AWeatherClock should be adaptable to other hardware configurations, with a big enough colored TFT LCD screen.

Arduino Weather Clock Functions

sparkbot_main_00.jpg
ast_watch_alarm_01.jpg
picow_gp_slide_00.jpg

The functions of AWeatherClock are:

  1. Display of a digital clock synchronized with NTP
  2. Display of the current weather info gathered from OpenWeather with version 2.5 APIs [for free account]
  3. Alarms that can be repeated daily, with selectable days [of the week] for the repeat. Note that if hardware permits, alarm sound (beep / melody / music) can be produced when alarm is due.
  4. Idle slideshow of photos (JPEG images) uploaded to the MCU, much like the slideshow function as described by Simple Arduino Framework Raspberry Pi Pico / ESP32 TFT LCD Photo Frame Implementation With Photos Downloaded From the Internet Via DumbDisplay

Arduino Weather Clock Requirements

AWeatherClock requires hardware with the following capabilities:

  1. ESP32 line of MCU that supports WiFi, or Raspberry Pi PicoW
  2. 240x240 (or bigger) colored TFT LCD screen
  3. Able to provide with simple "trigger" input, like with
  4. BUTTON -- note that the "boot" button for ESP32 can be used as BUTTON here
  5. TOUCH SCREEN
  6. Optionally -- buzzer, speaker or audio module (like ES8311 for ESP32) -- for sounding of alarms.

Also, DumbDisplay Android app for Android phone (or Chrome OS / Android simulator etc) is an essential part of AWeatherClock since most settings -- including alarm setups and slideshow photos upload -- can be done with remote UI realized on your Android phone with the help of DumbDisplay Android app.

Notice that the remote UI on your Android phone is driven by the sketch -- i.e. the control flow of the UI is programmed in the sketch -- hence, other than the DumbDisplay Android app, there is no specific mobile app for AWeatherClock.

You may want to refer to Blink Test With Virtual Display, DumbDisplay for a bit more details about DumbDisplay Arduino library and DumbDisplay Android app.

Arduino Weather Clock Data

Indeed, there is a few [external] data AWeatherClock would need to acquire (including the weather situation icon PNG file) -- some from the Internet; some via DumbDisplay Android app; some from the Internet via DumbDisplay Android app

  1. NTP time with proper timezone
  2. the initial timezone of your MCU is hardcoded to the macro INIT_TIMEZONE defined in config.h
  3. after weather info gathering, timezone of your MCU is set to the timezone returned with the weather info
  4. Weather info of proper location, which can be found out as:
  5. according to hardcode query string (DEF_OPEN_WEATHER_API_LOCATION defined in config.h), or
  6. based on GPS location of your phone queried via DumbDisplay Android app
  7. Slideshow photos, which can be retrieved in the following ways:
  8. randomly from the Internet
  9. picsum.photos
  10. loremflickr.com
  11. placedog.net
  12. randomly from unsplash.com
  13. for downloading photos from unsplash.com, you will need to sign up and create a demo app for an Access Key
  14. pick from your phone
  15. take with your phone's camera
  16. When connected to DumbDisplay Android app, AWeatherClock is considered not idle, and hence slideshow will not start

Concerning alarm sound. Actually AWeatherClock not only will flash the screen when alarm is due, if buzzer / speaker / audio module (ES8311 for ESP32) is installed, audible alarm-specific sound will be generated. Please refer to the section Alarm Sound for more details.

Out-of-the-Box Supported Hardware

The sketch arduino_weather_clock.ino of this project is tailored for various compatible hardware that I can get hold of:

  1. PlatformIO env PYCLOCK -- ESP32 C3 pyClock
  2. it's button on the back is configured as a BUTTON for "trigger" input
  3. PlatformIO env AST_WATCH -- ESP32 C3 Astronaut-Clock-Watch (touch)
  4. it's touch screen is configured as a TOUCH SCREEN for "trigger" input
  5. it has a buzzer, which is used to generate alarm sound
  6. PlatformIO env TW3 -- ESP32 LILYGO_WATCH_2020_V3
  7. it's touch screen is configured as a TOUCH SCREEN for "trigger" input
  8. PlatformIO env ESP_SPARKBOT -- ESP32 S3 ESP-SparkBot
  9. it's right side is touchable, which is configured as a BUTTON for "trigger" input, but from my experience, this "touch-pin" mechanism doesn't work very well 😞
  10. it also has the ES8311 audio codec module, which is used to generate alarm sound
  11. PlatformIO env MUMA (touch) / MUMA_NT (non-touch) -- ESP32 S3 Little MuMa
  12. for touch version (MUMA), it's touch screen is configured as a TOUCH SCREEN for "trigger" input
  13. for non-touch version (MUMA_NT), it's "boot" button on the back right side is configured as a BUTTON for "trigger" input
  14. it also has the ES8311 audio codec module, which is used to generate alarm sound
  15. Platformio env PICOW_GP -- a Raspberry Pi PicoW attached to a gamepad-like LCD
  16. the gamepad's "start" button is configured as a BUTTON for "trigger" input
  17. PlatformIO env PICOW -- the Raspberry Pi PicoW wiring as mentioned in Simple Arduino Framework Raspberry Pi Pico / ESP32 TFT LCD Photo Frame Implementation With Photos Downloaded From the Internet Via DumbDisplay
  18. a ST7789 2.8 inch 240x320 SPI TFT LCD module is used, with a FT6336U capacitive touch layer
  19. it's touch screen is configured as a TOUCH SCREEN for "trigger" input
  20. a speaker is attached to it; the speaker is used to generate alarm sound
  21. please refer to Customizations for New Hardware PicoW Example
  22. PlatformIO env ESP32 -- an ESP32 customized hardware
  23. a ST7789V 1.3 inch 240x240 SPI TFT LCD module (ST7789) is used
  24. a button is attached to it, as BUTTON for "trigger" input
  25. a speaker is attached to it; the speaker is used to generate alarm sound
  26. please refer to Customizations for New Hardware ESP32 Example

How many slides can be stored in the MCU?

  1. E.g., for PYCLOCK which is an ESP32-C3 with 4M of flash memory, I can store 25 to 30 photos to the flash of the MCU; note that for PYCLOCK, it is configured to use no_ota.csv partitions in platformio.ini like
board_build.partitions = no_ota.csv
  1. E.g., for Raspberry Pi Pico, I can also store 25 to 30 photos to the flash of the MCU as well; note that for Raspberry Pi Pico, littlefs is configured in platformio.ini like
board_build.filesystem = littlefs
board_build.filesystem_size = 1m

Additional notes:

  1. For TWatch (TW3): If when compile you see some "include font" error, it might be that the project's folder path is too long. In such a case, try move the project to somewhere closer to the "root" of your filesystem

Showing of IP and Connecting DumbDisplay Android App

ast_watch_ip_00.jpg
dd-wifi-connect.gif
dd-permission-00.jpg
dd-permission-01.jpg

With BUTTON or TOUCH SCREEN, you can trigger AWeatherClock to show the IP of your MCU to connect to with Android DumbDisplay app

Be the "trigger" mechanism BUTTON or TOUCH SCREEN, you "double click" to trigger showing of IP.

You will need this IP to make connection between AWeatherClock and your Android phone's Arduino DumbDisplay app for the remote UI, as will be described in more details next.

BTW. You might see that DumbDisplay Android app requires "LOCATION" permission to make use of your phone's GPS service. You can grant the permission with the Settings menu option of DumbDisplay Android app.

Settings UI -- General

tab_general_00.jpg

As mentioned previously, most of the AWeatherClock settings can be modified with the UI remotely rendered on your Android phone with DumbDisplay Android app.

With the General tab, you can modify the general settings / options

  1. 🌤️ -- you click the 🌤️ button to [manually] trigger refresh of the current weather info
  2. 12 Hour / 24 Hour -- you select whether the digital clock display should be in 12-hour or 24-hour format
  3. 📡 -- you select whether to sync weather location with the GPS location of your phone
  4. Slide Show Idle -- you select the idle time (in minutes) before starting slideshow; to disable idle slideshow, select 🚫
  5. Slide Duration -- you select the duration (in seconds) each slide should be kept shown, before switching to another one
  6. Update Weather -- you select the gap (in minutes) between each auto update of the current weather info

Settings UI -- Alarms

tab_alarms_00.jpg
tab_alarms_01.jpg

With the Alarms tab, you can set up the alarms of AWeatherClock

  1. The 🕰️ icon next to an alarm indicates that the alarm is ON; below that icon, the time of the alarm is shown, like 00:00
  2. You can select any one of the alarms to edit. The details of the alarm being edited are shown on the right-side
  3. you can turn the alarm ON / OFF by selecting the ⏰ button
  4. you select the 🔄 button to set that the alarm is to be repeated daily; and the week days for the repeat are indicated by the Su / Mo / Tu / We / Th / Fr / Sa below the 🔄 button
  5. The time of the alarm is clearly shown further down below. You can press the 🔼 / 🔽 to have the alarm hour / minute changed. Alternatively, you can double-press on the hour / minute to have a pop-up dialog for you to enter the hour / minute of the alarm. Note that if you enter a value bigger than 99, like 1230, it will be interpreted as the time 12:30; if you want to enter the time, say, 00:01, enter 2401


Settings UI -- Slides

tab_slides_00.jpg
tab_slides_01.jpg
tab_slides_02.jpg
tab_slides_03.jpg
tab_slides_04.jpg

With the Slides tab, you can add / remove photos for the idle slideshow

  1. ⬅️ / ➡️ -- you use the ⬅️ / ➡️ buttons to review the slideshow photos
  2. you select the photo to be deleted from the slideshow
  3. newly uploaded photo can be saved to the slideshow, positioned after the photo selected
  4. 💾 / 🗑️ -- you delete the photo shown by double-pressing 🗑️; the 💾 is for you to add the uploaded photo to the slideshow
  5. Acquire photo to upload:
  6. 🌍 / 💦 -- you trigger download of a random photo from the Internet by pressing 🌍; 💦 is specifically for downloading a random photo from Unsplash
  7. 📱 / 📷 -- you pick a photo from your phone by pressing 📱; you take a photo with your phone's camera by pressing 📷
  8. In any case, the uploaded photo will be considered "unsaved"; you press 💾 to add the photo to the slideshow
  9. Also notice for photo that might not fit AWeatherClock screen, a crop UI will be invoked for you to crop the photo in order to fit the screen

Alarm Sound

tab_alarms_sound.jpg

As mentioned previously, in addition to flashing of the screen, in case of audible alarm sound can be generated with buzzer / speaker / audio module (ES8311 for ESP32), alarm-specific selection will be available

  1. Beep sound -- with buzzer / speaker / audio module
  2. Melody Amazing Grace (for ESP32) -- the same melody encoding as mentioned in the YouTube video Raspberry Pi Pico playing song melody tones, with DumbDisplay control and keyboard input and in the post Respberry Pi Pico W Generating Tones With Programmable I/O (PIO) Using MicroPython

Melody Birthday Song (for ESP32) -- similar to above melody Amazing Grace, but musical note encoding was generated with LLM (in happy_birthday_melody.h)

I asked LLM to generate this file's "happy birthday" melody.

Prompt:

At the end are the data structures for the melody "amazing grace". Can you figure out the data for the melody "happy birthday"?

IMPORTANT notes:
* Each musical note MUST be composed of exactly two characters, no more and no less.
* Hence, the data "nodenames" / "octaves" / "beats" for each musical note MUST be composed with two characters, and therefore might be padded with space " "
* For "nodenames" -- e.g "C " for C; "C#" for C sharp; and "Cb" for C flat
* For "octaves" -- e.g. "0 " for octave 0; "1 " for octave 1; "2 " for octave 2; note that it can be negative like "-1" (still TWO chars), for lower octaves

-----------------

const char* amazing_grace_nodenames = "G C E C E D C A G G C E C E D G E G E G E C G A C C A G G C E C E D C ";
const char* amazing_grace_octaves = "0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 ";
const char* amazing_grace_beats = "2 4 1 1 4 2 4 2 4 2 4 1 1 4 2 8 2 1 1 1 1 4 2 4 1 1 1 4 2 4 1 1 4 2 8 ";

const int amazing_grace_beatSpeed = 300;
  1. Music [sample] Star Wars (for ESP32 with audio module ES8311) -- music played with Arduino Audio Tools, with data file star_wars_music.h, which is actually the same data file used by the streams-memory_raw-i2s example

Notes:

  1. This per-alarm sound selection is only available for ESP32 line of MCU. Moreover, if your hardware has the audio module ES8311, you will have more.
  2. With the Alarms tab, you can select the per-alarm sound to alert you when the alarm is due.
  3. The sound choice Star Wars is only available for the audio module ES8311
  4. Slider next to 🔊 allows you to change the ES8311 audio module volume

Basic Hardcoded Configurations -- Config.h

config.h for secrets like WIFI_SSID, WIFI_PASSWORD and OPEN_WEATHER_MAP_APP_ID

...
// #####
// # you will need to either
// # . enable and complete the following "secret" block
// # . or create and complete the "secret" block in the file `_secret.h`
// #####
#if false

// ----------------------
// !!! "secret" block !!!
// ----------------------
//
// *****
// * you can setup WIFI_SSID / WIFI_PASSWORD; for ESP32, if WIFI_SSID not defined, will use WiFiManager to get WiFi SSID and password
// * you will need to setup OPEN_WEATHER_MAP_APP_ID
// * you can optionally setup UNSPLASH_CLIENT_ID
// *****

#define WIFI_SSID "<wifi ssid>"
#define WIFI_PASSWORD "<wifi password>"

// you MUST get APP_ID from https://home.openweathermap.org/users/sign_up
#define OPEN_WEATHER_MAP_APP_ID "<app id>"

// optionally, sign up and create an app to get Access Key from https://unsplash.com/developers
// comment out UNSPLASH_CLIENT_ID if you do not want to use unsplash.com
#define UNSPLASH_CLIENT_ID "<client id>"

#else
#include "_secret.h"
#endif
...

Notes:

  1. You define secrets like WIFI_SSID, WIFI_PASSWORD and OPEN_WEATHER_MAP_APP_ID in _secret.h, as hinted above
  2. For ESP32 line of MCU, it is not a must to define WIFI_SSID / WIFI_PASSWORD. In case not defined, WiFiManager will be used to acquire WiFi credential. Say, you connect to the AP set up by WiFiManager running on your MCU, with AP name AWClock, as defined by AUTOCONNECT_AP_NAME in config.h
  3. However, you MUST set your own OPEN_WEATHER_MAP_APP_ID for version 2.5 APIs which you can apply for from OpenWeather, say with a free account
  4. Optionally, you can sign up and create an app to get Access Key from Unsplash; with UNSPLASH_CLIENT_ID defined, your are ready to download photos from Unsplash and upload them to your MCU for slideshow

config.h for other basic hardcoded configurations

...
// TIMEZONE (in hours); note that NTP timezone will be gotten from weather api, hence, this is just the initial TIMEZONE
#define INIT_TIMEZONE 8

// In order to properly setup the openweathermap.org the endpoint
// * please head to http://api.openweathermap.org to create an account and get an APP ID (for version 2.5)
// * the country (location) for which to retrieve whether is defined with OPEN_WEATHER_API_LOCATION
// - please refer to https://openweathermap.org/api/geocoding-api
// - Please use ISO 3166 country codes -- https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
// * below DEF_SYNC_WEATHER_LOCATION_WITH_GPS ==> got location from GPS when connected to DD
#define DEF_OPEN_WEATHER_API_LOCATION "Hong Kong"

#define DEF_SYNC_WEATHER_LOCATION_WITH_GPS true /* got location from GPS when connected to DD */
#define DEF_SLIDE_SHOW_IDLE_DELAY_MINS 2 /* <= 0 means slide show not enabled */
#define DEF_SLIDE_DURATION_SECS 5
#define DEF_UPDATE_WEATHER_INTERVAL_MINS 30

#define NUM_ALARMS 5
#define AUTO_ACK_ALARM_MINUTES 10
...

Notes:

  1. INIT_TIMEZONE -- the initial timezone; as mentioned previously; your MCU's timezone will eventually be synchronized with that returned from 'get current weather' API
  2. DEF_OPEN_WEATHER_API_LOCATION -- the location (see ISO 3166 country codes) for the initial current weather info; note that when connected to DumbDisplay Android app, your phone's GPS location can be the location for getting current weather info
  3. DEF_SYNC_WEATHER_LOCATION_WITH_GPS -- The default setting whether "get current weather" should be based on GPS location got from your phone, (rather than based on DEF_OPEN_WEATHER_API_LOCATION)
  4. DEF_SLIDE_SHOW_IDLE_DELAY_MINS -- The default setting for how many idle minutes to start slideshow
  5. DEF_SLIDE_DURATION_SECS -- The default setting for how many seconds for each slideshow phone should stay displayed before switching to another one
  6. DEF_UPDATE_WEATHER_INTERVAL_MINS -- The default setting for the interval (minutes) between each update of current weather info
  7. NUM_ALARMS -- The fixed number of alarms AWeatherClock can set
  8. AUTO_ACK_ALARM_MINUTES -- The number of minutes before due alarm is automatically acknowledged (stopped)


System Hardcoded Configurations -- Sys_config.h

The system hardcoded configuration file sys_config.h not only contains most hardware pin mappings (as mentioned in Highlight for Customization for New Hardware); specifically, sys_config.h contains some values that will be useful during development:

...
// comment out to DEBUG use of WIFI MANAGER for WiFi SSID / password
//#define TEST_WIFI_MANAGER

// comment out if you want the program to delay startup for 10 seconds for debugging (examine the serial monitor output)
//#define DELAY_INITIALIZE_FOR_SECONDS 10

// suggested to set the following EEPROM_HEADER to the date you want to reset the saved program settings *** INCLUDING saved slides ***
const int32_t EEPROM_HEADER = 20250505;
...


Enjoy!

Have fun with AWeatherClock!

Peace be with you! May God bless you! Jesus loves you! Amazing Grace!