from machine import I2C, Pin, RTC
import time
# --- STEROWNIK LCD I2C (Klasa pomocnicza) ---
# Umozliwia obsluge wyswietlacza 16x2 po magistrali I2C
class I2cLcd:
def __init__(self, i2c, i2c_addr, num_lines, num_columns):
self.i2c = i2c
self.i2c_addr = i2c_addr
self.i2c.writeto(self.i2c_addr, bytearray([0]))
self.i2c.writeto(self.i2c_addr, bytearray([0x30]))
time.sleep_ms(5)
self.i2c.writeto(self.i2c_addr, bytearray([0x30]))
time.sleep_ms(1)
self.i2c.writeto(self.i2c_addr, bytearray([0x30]))
time.sleep_ms(1)
self.i2c.writeto(self.i2c_addr, bytearray([0x20]))
time.sleep_ms(1)
self.hal_write_command(0x28)
self.hal_write_command(0x0C)
self.hal_write_command(0x06)
self.hal_write_command(0x01)
self.num_lines = num_lines
self.num_columns = num_columns
def hal_write_init_nibble(self, nibble):
byte = ((nibble >> 4) & 0x0f) << 4
self.i2c.writeto(self.i2c_addr, bytearray([byte | 0x04]))
self.i2c.writeto(self.i2c_addr, bytearray([byte]))
def hal_backlight_on(self):
self.i2c.writeto(self.i2c_addr, bytearray([1 << 3]))
def hal_write_command(self, cmd):
byte = ((self.backlight << 3) | ((cmd >> 4) & 0x0f) << 4)
self.i2c.writeto(self.i2c_addr, bytearray([byte | 0x04]))
self.i2c.writeto(self.i2c_addr, bytearray([byte]))
byte = ((self.backlight << 3) | (cmd & 0x0f) << 4)
self.i2c.writeto(self.i2c_addr, bytearray([byte | 0x04]))
self.i2c.writeto(self.i2c_addr, bytearray([byte]))
def hal_write_data(self, data):
byte = (0x01 | (self.backlight << 3) | ((data >> 4) & 0x0f) << 4)
self.i2c.writeto(self.i2c_addr, bytearray([byte | 0x04]))
self.i2c.writeto(self.i2c_addr, bytearray([byte]))
byte = (0x01 | (self.backlight << 3) | (data & 0x0f) << 4)
self.i2c.writeto(self.i2c_addr, bytearray([byte | 0x04]))
self.i2c.writeto(self.i2c_addr, bytearray([byte]))
def clear(self):
self.hal_write_command(0x01)
self.hal_write_command(0x02)
def move_to(self, cursor_x, cursor_y):
addr = cursor_x & 0x3f
if cursor_y & 1:
addr += 0x40
self.hal_write_command(0x80 | addr)
def putstr(self, string):
for char in string:
self.hal_write_data(ord(char))
backlight = 1
# --- KONFIGURACJA SPRZETOWA ---
# I2C dla LCD (SDA=GP0, SCL=GP1)
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
# Adres LCD zazwyczaj 0x27, w Wokwi czesto takze
lcd = I2cLcd(i2c, 0x27, 2, 16)
# RTC (Zegar czasu rzeczywistego)
rtc = RTC()
# Ustawienie czasu startowego: R, M, D, DzienTyg, Godz, Min, Sek, SubSek
rtc.datetime((2024, 1, 23, 2, 12, 0, 0, 0))
# Przyciski (Pull Down - domyslnie 0, wcisniecie to 1)
btn_mode = Pin(15, Pin.IN, Pin.PULL_DOWN)
btn_up = Pin(14, Pin.IN, Pin.PULL_DOWN)
btn_down = Pin(13, Pin.IN, Pin.PULL_DOWN)
# Zmienne stanu
state = 0 # 0=Display, 1=Set Hour, 2=Set Minute
last_mode_press = 0
debounce_delay = 200
# --- GLOWNA PETLA PROGRAMU ---
def get_time():
t = rtc.datetime()
return t[4], t[5], t[6] # Godz, Min, Sek
def display_time(h, m, s, mode):
lcd.move_to(0, 0)
lcd.putstr("ZEGAR CYFROWY")
lcd.move_to(0, 1)
# Formatowanie z zerami wiodacymi
str_h = "{:02d}".format(h)
str_m = "{:02d}".format(m)
str_s = "{:02d}".format(s)
if mode == 1 and (time.ticks_ms() % 1000) < 500:
str_h = " " # Miganie godziny przy ustawianiu
if mode == 2 and (time.ticks_ms() % 1000) < 500:
str_m = " " # Miganie minut przy ustawianiu
lcd.putstr(f"Czas: {str_h}:{str_m}:{str_s}")
# Zmienne tymczasowe do edycji
temp_h = 12
temp_m = 0
print("Start systemu...")
lcd.clear()
while True:
current_time_ms = time.ticks_ms()
# Obsluga przycisku MODE
if btn_mode.value():
if current_time_ms - last_mode_press > debounce_delay:
state += 1
if state > 2:
state = 0
# Zapisz czas do RTC przy wyjsciu z edycji
# (Rok, M, D, Dzien, H, M, S, Sub)
rtc.datetime((2024, 1, 23, 2, temp_h, temp_m, 0, 0))
else:
# Wejscie do edycji - pobierz aktualny czas
h, m, s = get_time()
temp_h, temp_m = h, m
lcd.clear()
last_mode_press = current_time_ms
# Obsluga edycji
if state == 1: # Edycja Godzin
if btn_up.value():
temp_h = (temp_h + 1) % 24
time.sleep(0.2)
if btn_down.value():
temp_h = (temp_h - 1) % 24
time.sleep(0.2)
display_time(temp_h, temp_m, 0, 1)
elif state == 2: # Edycja Minut
if btn_up.value():
temp_m = (temp_m + 1) % 60
time.sleep(0.2)
if btn_down.value():
temp_m = (temp_m - 1) % 60
time.sleep(0.2)
display_time(temp_h, temp_m, 0, 2)
else: # Normalny zegar
h, m, s = get_time()
display_time(h, m, s, 0)
time.sleep(0.1)Loading
pi-pico
pi-pico