Alarm clock using lv_micropython and rotary encoder

Alarm clock based on ESP32, using internal RTC and external rotary encoder/switch

  • hardware implemented on base of ESP32-WROVER-KIT_V4.1 containing ILI9341 TFT display
  • using lv_micropython implementing LittlevGL GUI library for TFT display control


  • RTC date and time is initalized to CET/CEST using NTP/WLAN on power up if network connection exists
  • in case of RTC date and time is initalized CET/CEST time shift occcures automatically
  • if network connection exists RTC is adjusted periodically every 23h53’07" via NTP/WLAN
  • click and release switch to enable/set alarm-time
  • alarm is enabled for 60 seconds when time matches
  • RTC time can be set manually, press switch for > 5 seconds (RTC date will get lost)

Sources: (6.8 KB)

Problems to be solved:

  • when lv.scr_load(scr) is executed main loop of program pauses for 50…120ms, leading to missing ticks on the rotary encoder.
  • automatic brightness control of backlight has to be implemented

Have fun :slight_smile:


1 Like

Great! Thank you for sharing!

You can count the encoder events in an interrupt and pass the number of turns to data->enc_diff in indev_read.

Thanks for sharing this project. I really like the look of your screen layout. The 7-segment font looks great. Your post is very timely for me - I’m also working on an alarm clock, using very similar hardware. Eventually I’ll document this project on Hackaday IO and github.

Can you share your source for the 7-segment font? I am currently using a roboto mono font, but your clock face looks much better. I’d like to investigate using this font. I’ll be sure to credit your project if I make this change.

I also use a rotary encoder. I wrote a MicroPython encoder driver that is available on github. Quite a few people have used it in their ESP32 and ESP8266 projects. It uses an interrupt based implementation to detect encoder ticks. The github repo describes the technical approach and has examples. I don’t know if it would be useful for your clock or not?

Thanks for the link to your rotary encoder sources! It will save a lot of my time :slight_smile:
My polling or timer interrupt approach fails when TFT-display update is run by LittlevGL…

Used following font (link see picture(s) below):

May also have a look at:

Hint: 7-segment-display range of fonts I implemented is:
Space ( ) . 0…9 : A C E F H J L P U b c d h n o r t u

Have fun!


Thanks Peter ! I downloaded the first 7 segment font you suggested. Worked perfectly :+1:

Hello Mike,
worked at the rotary encoder sources. You’re right, the way you did it it performs much better. Adapted it to ALPS EC11 style encoder.
See: Example for working with a rotary encoder?

best regards,


Made some improvements:

  • rotary encoder now interrupt driven and debounced. Works, but Pin (interrupt) handling seems not to be very fast during update of the TFT-display :frowning:
  • TFT display brightness is set automatically via PWM, depending on surrounding light
  • Sound for Alarm-buzzer is generated via PWM to be played on a external modified soundbar
  • Power-amp of soundbar can be enabled via an active low output signal
  • updated sources and removed some bugs

I’ll use it now, the way it is - and build a more professional version when time comes…

Sources: (8.5 KB)

Have fun :slight_smile:

1 Like

Improved behavior of rotary encoder and made some code re-work. Rotary encoder now hardware driven. To enable this feature on micropython for ESP32 see:

Sources for alarm clock: (8.7 KB)

Have fun :slight_smile: