import machine
import dht
import time
# --- LCD Driver Setup ---
i2c = machine.SoftI2C(sda=machine.Pin(21), scl=machine.Pin(22), freq=400000)
class I2CLcd:
def __init__(self, i2c, addr=0x27):
self.i2c, self.addr = i2c, addr
for cmd in [0x33, 0x32, 0x28, 0x0C, 0x06, 0x01]:
self._write(cmd); time.sleep(0.01)
def _write(self, cmd, mode=0):
hd, ld = cmd & 0xF0, (cmd << 4) & 0xF0
for val in [hd, ld]:
self.i2c.writeto(self.addr, bytes([val | mode | 0x08 | 0x04]))
self.i2c.writeto(self.addr, bytes([val | mode | 0x08]))
def display(self, text, row):
lines = [0x80, 0xC0, 0x94, 0xD4]
self._write(lines[row])
padded = text[:20] + " " * (20 - len(text[:20]))
for char in padded: self._write(ord(char), 1)
# --- Pin Definitions ---
led1 = machine.Pin(12, machine.Pin.OUT) # LED1 (Motion Indicator)
led2 = machine.Pin(26, machine.Pin.OUT) # LED2 (Green - Safe)
led3 = machine.Pin(27, machine.Pin.OUT) # LED3 (Red - Alarm)
buzzer = machine.Pin(25, machine.Pin.OUT) # Buzzer
pir = machine.Pin(13, machine.Pin.IN) # PIR Sensor
dht_sensor = dht.DHT22(machine.Pin(15)) # DHT22
ldr = machine.ADC(machine.Pin(34)) # LDR Sensor
btn = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
ldr.atten(machine.ADC.ATTN_11DB)
# --- Initial State ---
devices = i2c.scan()
lcd = I2CLcd(i2c, devices[0]) if devices else None
led2.value(1) # Green starts ON
led3.value(0)
led1.value(0)
buzzer.value(0)
while True:
try:
# 1. READ SENSORS
dht_sensor.measure()
temp = dht_sensor.temperature()
motion_state = pir.value()
light_val = ldr.read()
# 2. LED1 MOTION LOGIC
if motion_state == 1:
led1.value(1) # ON when Ada Orang
motion_msg = "Ada Orang"
else:
led1.value(0) # OFF when Tiada Orang
motion_msg = "Tiada Orang"
# 3. LDR MODE LOGIC
mode_msg = "Malam" if light_val > 2000 else "Siang"
# 4. UPDATE LCD
if lcd:
lcd.display("Smart Urban Safety", 0)
lcd.display(f"Temp: {temp}C", 1)
lcd.display(f"Motion: {motion_msg}", 2)
lcd.display(f"Mode: {mode_msg}", 3)
# 5. PUSHBUTTON TASK LOGIC
if btn.value() == 0:
start_press = time.ticks_ms()
while btn.value() == 0: pass # Wait for release
press_duration = time.ticks_diff(time.ticks_ms(), start_press)
if press_duration < 1000: # Press and Release (Short)
led3.value(1) # LED3 ON
led2.value(0) # LED2 OFF
buzzer.value(1) # Buzzer ON
else: # Hold and Release (Long)
led2.value(1) # LED2 ON
led3.value(0) # LED3 OFF
buzzer.value(0) # Buzzer OFF
except Exception as e:
print("System Error:", e)
time.sleep(0.1)