Analog-Uhr

Hier werden einzelne Projekte mit MicroPython vorgestellt
Antworten
Heinrichs
Beiträge: 178
Registriert: Do 21. Okt 2010, 18:31

Analog-Uhr

Beitrag von Heinrichs » Mi 25. Jan 2023, 12:35

Hier stelle ich ein einfaches Programm für eine Analog-Uhr-Anzeige vor. Es eignet sich sowohl für das Modul TTGO T-Display als auch für das Modul T-QT. Je nach Modul muss im Programmtext ein entsprechender Eintrag (board = 0 bzw. board = 1) vorgenommen werden.

Uhr_klein.jpg
Abb. 1 (Uhr_1a.py)
Uhr_klein.jpg (68.3 KiB) 9134 mal betrachtet

Folgende Themenbereiche werden behandelt:
  • Klassen für graphische Objekte definieren und einsetzen
  • RTC-Klasse

1. Klassen für graphische Objekte definieren und einsetzen

Das Programm stellt ein sehr einfaches Beispiel dafür dar, wie man Klassen für graphische Objekte definieren und einsetzen kann. Die Kommentierungen sollen helfen, es als Vorlage für eigene Programme einzusetzen.


2. Die RTC-Klasse

Mit Hilfe der RTC-Klasse erhält man einen Zugriff auf die Systemzeit des ESP32. Diese Information erhält er übrigens von dem Betriebssystem ihres Rechners, an den Sie ihn angeschlossen haben. Die RTC-Klasse importieren wir zunächst aus dem machine-Modul:

from machine import RTC

Nun bilden wir eine RTC-Instanz mit dem Namen rtc:

rtc = RTC()

Mit der Methode datetime dieses Objekts erhalten wir ein Zahlentupel, welches wie hier timetuple nennen:

timetuple=rtc.datetime()

Ein solche Tupel sieht z. B. so aus:

(2023, 1, 25, 2, 13, 19, 14, 926068)

Die einzelnen Elemente des Tupels haben folgende Bedeutung:

Element 0: Jahr (2023)
Element 1: Monat (1 für Januar)
Element 2: Tag (25)
Element 3: Wochentag (2 für Mittwoch; Zählung beginnt am Montag mit 0)
Element 4: Stunde (13)
Element 5: Minute (19)
Element 6: Sekunde (14)

Auf die Elemente eines Tupels kann man wie bei Listen zugreifen: Der Wert von timetuple[2] ist dann z. B. 25.

Und hier das Programm:

Code: Alles auswählen

# Uhr_1b.py (für TTGO und T-QT)

############################## Beutztes Board #######################################
#
# Tragen Sie hier ein, welches Board Sie benutzen (0 = T-QT, 1 = TTGO):
board = 0
#
#####################################################################################

# Die Systemzeit (inkl. Datum) erhält das ESP32-System aus dem Betriebssysstem des Rechners:
# Wenn Sie z. B. Thonny benutzen, gibt Thonny beim Start diese Informationen vom Betriebssytenm
# an den ESP32 weiter. 

# Import für exit()
import sys

# Import für Uhrzeit
from machine import RTC

# RTC-Objekt instanziieren und Systemzeit (inkl. Datum) im Terminal anzeigen
rtc = RTC()
timetupel=rtc.datetime() # now() git es nicht!

h=timetupel[4]
m=timetupel[5]
s=timetupel[6]
print('Systemzeit: ',h ,':',m, ':', s)
print('-------------------------------')

# Importe für Analog-Anzeige der Uhrzeit
from machine import Pin, SPI, RTC
import st7789
import vga1_8x8 as font
from time import sleep
import math

# Eine Klasse für die Uhrzeiger definieren
class Uhrzeiger:
    def __init__(self, r, w, display): # r(adius) = Zeigerlänge), (start)w(inkel) in Grad (bezogen auf Nordrichtung)
        self.r = r
        self.w = w
        self.__x0 = 64 # Anfangspunkt des Zeigers ist (64, 64)
        self.__y0 = 64
        self.__display = display
        
    def draw(self, color=st7789.WHITE): # color = WHITE, wenn keine Parameterangabe
        b = math.radians(self.w) # Winkel in Bogenmaß 
        x1 = self.r * math.sin(b)
        y1 = self.r * math.cos(b)
        self.__display.line(self.__x0, self.__y0, self.__x0+int(x1), self.__y0-int(y1), color)

    def delete(self): # Löschen über fill-Methode zeigt Ruckeln, weil das Ziffernblatt auch immer neu gezeichnet werden muss
        self.draw(0)
        
def circle(x, y, r): # Kreis mit Mittelpunkt und Markierungen für 0, 3, 6 und 9 Uhr
    c = st7789.GREEN
    y0 = y - r
    x0 = x
    # Ziffernblatt mit Markierungen
    for w in range(0, 360, 2):
        b = math.radians(w) # Winkel in Bogenmaß 
        x1 = x + int(r * math.sin(b))
        y1 = y - int(r * math.cos(b))
        display.pixel(x1, y1, c) # Kreispunkt
        x0 = x1
        y0 = y1
    display.line(x, y-r, x, y-r+3, c) # Markierungen
    display.line(x, y+r-3, x, y+r, c)
    display.line(x-r, y, x-r+3, y, c)
    display.line(x+r-3, y, x+r, y, c) 
    display.fill_rect(63,63,4,4,c) # Mittelpunkt

# Display initialisieren
if board == 0: # T-QT
    spi = SPI(1, baudrate=20000000, sck=Pin(3), mosi=Pin(2)) # für T-QT
    display = st7789.ST7789(spi, 128, 128, reset=Pin(1, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(6, Pin.OUT), backlight=Pin(10, Pin.OUT), rotation=1, color_order=st7789.BGR) # für T-QT
    display.init()
    display.off() # umgekehrte Logik gegenüber TTGO!
    display.fill(0) # Display löschen
elif board == 1: # TTGO:
    spi = SPI(1, baudrate=20000000, polarity=1, sck=Pin(18), mosi=Pin(19))
    display = st7789.ST7789(spi, 135, 240,  reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3) # Landscape
    display.init()
    display.on() 
    display.fill(0) # Display löschen
else:
    print('Keine Passende Board-Kennzeichnung eingegeben!')
    sys.exit(0)

# Instanziierung des Zeigers:              
minutenzeiger = Uhrzeiger(25, 0, display)
stundenzeiger = Uhrzeiger(15, 0, display)

# Uhrzeit und Datum im Display anzeigen
display.text(font, 'Lilygo-Uhr', 24, 12, st7789.BLUE)
circle(64, 64, 30) # Ziffernblatt

# Uhrzeiten anzeigen:
wochentag_liste = ['Mo ', 'Di ', 'Mi ', 'Do ', 'Fr ', 'Sa ', 'So ']
while True:
    timetuple=rtc.datetime() # now() gibt es nicht!
    print(timetuple) # zum Testen
    jahr = timetuple[0] 
    monat = timetuple[1]
    tag = timetuple[2]
    wochentag = timetuple[3]
    datum = wochentag_liste[wochentag] + str(tag)+'.'+str(monat)+'.'+str(jahr)
    display.text(font, datum, 13, 110, st7789.RED)    
    minuten = timetuple[5]
    stunden = timetuple[4]
    minutenzeiger.w = minuten * 6 
    stundenzeiger.w = stunden * 30 + minuten // 2 # Ganzzahldivision
    minutenzeiger.draw()
    stundenzeiger.draw()
    sleep(10) # Aktualisierung jede 10 s; d. h. die Analoganzeige geht maximal um 10 s falsch
    minutenzeiger.delete()
    stundenzeiger.delete()
Bitte beachten Sie: Wenn Sie das Programm "stand alone", d. h. nicht von einer Programmierumgebung wie Thonny aus starten, dann beginnt die Uhr bei 00:00:00 Uhr, Samstag 1.1.2000, zu laufen. Es besteht allerdings die Möglichkeit, das Programm so zu erweitern, dass es beim Start über WLAN ein korrektes timetuple von einem entsprechenden Server bezieht (s. https://www.forum.g-heinrichs.de/viewto ... p=251#p251.

Antworten