from machine import Pin, I2C, ADC, PWM, SPI
import utime
import framebuf
# ---------------- Nokia 5110 Ekran ----------------
class Nokia5110:
def __init__(self, spi, dc, cs, rst):
self.spi = spi
self.dc = Pin(dc, Pin.OUT)
self.cs = Pin(cs, Pin.OUT)
self.rst = Pin(rst, Pin.OUT)
self.buffer = bytearray((84 * 48) // 8)
self.framebuf = framebuf.FrameBuffer(self.buffer, 84, 48, framebuf.MONO_VLSB)
self.reset()
self.init_display()
def reset(self):
self.rst.value(0)
utime.sleep_ms(100)
self.rst.value(1)
def init_display(self):
self._write_cmd(0x21)
self._write_cmd(0xB1)
self._write_cmd(0x04)
self._write_cmd(0x14)
self._write_cmd(0x20)
self._write_cmd(0x0C)
def _write_cmd(self, cmd):
self.dc.value(0)
self.cs.value(0)
self.spi.write(bytearray([cmd]))
self.cs.value(1)
def _write_data(self, data):
self.dc.value(1)
self.cs.value(0)
self.spi.write(bytearray([data]))
self.cs.value(1)
def show(self):
for page in range(6):
self._write_cmd(0x40 | page)
self._write_cmd(0x80 | 0)
for col in range(84):
self._write_data(self.buffer[page * 84 + col])
def clear(self):
self.framebuf.fill(0)
def text(self, string, x, y):
self.framebuf.text(string, x, y, 1)
# --- Donanım Tanımları ---
spi = SPI(0, baudrate=2000000, sck=Pin(6), mosi=Pin(7)) # CLK=GP6, DIN=GP7
lcd = Nokia5110(spi, dc=2, cs=10, rst=0) # DC=GP2, CE=GP11, RST=GP0
i2c = I2C(0, scl=Pin(5), sda=Pin(4)) # RTC DS1307 için I2C: SCL=GP5, SDA=GP4
rtc_address = 0x68
led = Pin(3, Pin.OUT) # LED: GP3
buzzer = PWM(Pin(8)) # Buzzer: GP8
button = Pin(9, Pin.IN, Pin.PULL_UP) # Button: GP9
pot = ADC(Pin(26)) # Pot: GP26
alarm_hour = 0
alarm_minute = 0
alarm_active = False
alarm_triggered = False
# Mario müziği için notalar ve frekanslar
NOTES = [
392, 392, 392, 311, 466, 392, 311, 466, 392,
587, 587, 587, 622, 466, 369, 311, 466, 392,
392, 392, 392, 311, 466, 392, 311, 466, 392,
784, 392, 392, 784, 740, 698, 659, 622, 659,
415, 554, 523, 493, 466, 440, 466,
392, 466, 440, 466, 392, 392, 392, 392
]
DURATIONS = [
300, 300, 300, 150, 150, 300, 150, 150, 600,
300, 300, 300, 150, 150, 300, 150, 150, 600,
300, 300, 300, 150, 150, 300, 150, 150, 600,
150, 300, 150, 150, 150, 150, 150, 150, 300,
150, 150, 150, 150, 150, 150, 300,
150, 150, 150, 150, 150, 150, 150, 600
]
# --- Yardımcı Fonksiyonlar ---
def bcd2dec(bcd):
return (bcd // 16) * 10 + (bcd % 16)
"""
DS1307 RTC modülünden okunan BCD (Binary-Coded Decimal) formatındaki saat verilerini normal decimal sayılara çevirir.
Örnek:
BCD değeri 0x21 (33) ise bu 21 dakika anlamına gelir.
"""
def read_time():
try:
data = i2c.readfrom_mem(rtc_address, 0x00, 7)
second = bcd2dec(data[0] & 0x7F)
minute = bcd2dec(data[1])
hour = bcd2dec(data[2])
weekday = bcd2dec(data[3])
day = bcd2dec(data[4])
month = bcd2dec(data[5])
year = bcd2dec(data[6]) + 2000
return (year, month, day, weekday, hour, minute, second, 0)
except Exception as e:
return (2000, 1, 1, 0, 0, 0, 0, 0)
"""RTC (Real-Time Clock) modülünden güncel zamanı okur ve decimal olarak
(yıl, ay, gün, hafta_günü, saat, dakika, saniye) bilgilerini döndürür."""
def read_alarm_from_pot():
global alarm_hour, alarm_minute
val = pot.read_u16()
total_minutes = int((val / 65535) * 1439) # 24*60-1 = 1439
alarm_hour = total_minutes // 60
alarm_minute = total_minutes % 60
"""Potansiyometre ile alarm saati belirlenmesini sağlar.
Pot'un 0-65535 arası değeri, 0-1439 dakika arasına (24 saat) dönüştürülür."""
def check_alarm(now):
global alarm_active, alarm_triggered
year, month, day, weekday, hour, minute, second, _ = now
if hour == alarm_hour and minute == alarm_minute and second == 0:
if not alarm_triggered: # Alarm yeni tetiklendi
alarm_active = True
alarm_triggered = True
elif alarm_triggered and (hour != alarm_hour or minute != alarm_minute):
alarm_triggered = False # Alarm zamanı geçti, resetle
"""Mevcut saat, alarm saatine eşitse alarmı başlatır."""
def play_song():
for i in range(len(NOTES)):
if not alarm_active: # Alarm durdurulduysa çalmayı kes
break
if NOTES[i] == 0:
buzzer.duty_u16(0) # Sesi kapat
else:
buzzer.freq(NOTES[i])
buzzer.duty_u16(32767) # %50 duty cycle
utime.sleep_ms(DURATIONS[i])
buzzer.duty_u16(0) # Sesi kapat
"""Buzzer ile tanımlı Mario melodisini çalar."""
def trigger_alarm():
global alarm_active
led.value(1)
play_song()
if alarm_active:
utime.sleep(0.1)
trigger_alarm()
"""Alarm tetiklendiğinde LED'i yakar ve müziği başlatır."""
def stop_alarm(pin):
global alarm_active
alarm_active = False
led.value(0)
buzzer.duty_u16(0)
"""Butona basıldığında alarmı durdurur"""
button.irq(trigger=Pin.IRQ_FALLING, handler=stop_alarm)
""" butona basıldığı anda alarmı durdurmak için otomatik olarak stop_alarm() fonksiyonunu çalıştırır."""
# --- Nokia Display Fonksiyonları ---
def update_display(now, alarm_set):
lcd.clear()
year, month, day, weekday, hour, minute, second, _ = now
# 1. Satır: Saat
lcd.text("Saat:", 10, 0)
# 2. Satır: Şu anki zaman (hh:mm:ss)
lcd.text(f"{hour:02}:{minute:02}:{second:02}", 2, 8)
# 3. Satır: Alarm
lcd.text("Alarm:", 10, 16)
# 4. Satır: Alarm zamanı veya "Kurulu Degil"
if alarm_triggered or (alarm_hour == 0 and alarm_minute == 0):
lcd.text("Kurulu", 0, 24)
lcd.text("Degil", 0, 32)
else:
lcd.text(f"{alarm_set[0]:02}:{alarm_set[1]:02}", 2, 24)
# 5. Satır: Alarm çalıyorsa
if alarm_active:
lcd.text("Caliyor", 0, 40)
lcd.show()
# --- Ana Döngü ---
while True:
now = read_time()
read_alarm_from_pot()
check_alarm(now)
update_display(now, (alarm_hour, alarm_minute))
if alarm_active:
trigger_alarm()
utime.sleep(0.1)Loading
nokia-5110
nokia-5110