from machine import Pin, I2C, ADC, PWM
import time
import dht
import network
# LCD2004 I2C
class I2cLcd:
LCD_CLR = 0x01
LCD_SET_DDRAM = 0x80
def __init__(self, i2c, addr):
self.i2c = i2c
self.addr = addr
self.backlight = 0x08
self.EN = 0x04
self.RS = 0x01
time.sleep_ms(50)
self._write_init()
self.command(0x28)
self.command(0x0C)
self.command(0x06)
self.clear()
def _i2c_write(self, data):
self.i2c.writeto(self.addr, bytes([data | self.backlight]))
def _pulse_enable(self, data):
self._i2c_write(data | self.EN)
time.sleep_us(1)
self._i2c_write(data & ~self.EN)
time.sleep_us(50)
def _write4(self, nibble, mode=0):
data = (nibble & 0xF0) | mode
self._i2c_write(data)
self._pulse_enable(data)
def _write_init(self):
self._write4(0x30)
time.sleep_ms(5)
self._write4(0x30)
time.sleep_us(150)
self._write4(0x30)
self._write4(0x20)
def command(self, cmd):
self._write4(cmd & 0xF0, 0)
self._write4((cmd << 4) & 0xF0, 0)
def write_char(self, ch):
self._write4(ord(ch) & 0xF0, self.RS)
self._write4((ord(ch) << 4) & 0xF0, self.RS)
def putstr(self, s):
for ch in s:
self.write_char(ch)
def clear(self):
self.command(self.LCD_CLR)
time.sleep_ms(2)
def move_to(self, col, row):
offsets = [0x00, 0x40, 0x14, 0x54]
self.command(self.LCD_SET_DDRAM | (col + offsets[row]))
# PIN SETUP
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
devices = i2c.scan()
if not devices:
raise RuntimeError("LCD not found!")
lcd = I2cLcd(i2c, devices[0])
dht_sensor = dht.DHT22(Pin(15))
ldr = ADC(Pin(26))
pir = Pin(17, Pin.IN)
relay = Pin(16, Pin.OUT)
btn_mode = Pin(7, Pin.IN, Pin.PULL_UP)
btn_on = Pin(8, Pin.IN, Pin.PULL_UP)
btn_off = Pin(6, Pin.IN, Pin.PULL_UP)
led_temp = Pin(10, Pin.OUT)
led_motion = Pin(11, Pin.OUT)
led_relay = Pin(12, Pin.OUT)
buzzer = PWM(Pin(13))
buzzer.freq(2000)
buzzer.duty_u16(0)
# WIFI CONNECT (WOKWI)
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASS = ""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
print("Connecting to WiFi...")
wlan.connect(WIFI_SSID, WIFI_PASS)
timeout = 10
start = time.time()
while not wlan.isconnected():
if time.time() - start > timeout:
print("WiFi Failed!")
break
time.sleep(0.5)
if wlan.isconnected():
ip = wlan.ifconfig()[0]
print("WiFi Connected! IP:", ip)
else:
print("Not connected.")
# SYSTEM VARIABLES
auto_mode = False
manual_state = False
light_threshold = 25000
temp_threshold = 35
last_motion = time.ticks_ms()
# FUNCTIONS
def beep(freq=2000, ms=120):
buzzer.freq(freq)
buzzer.duty_u16(30000)
time.sleep_ms(ms)
buzzer.duty_u16(0)
# MAIN LOOP
while True:
# Button control
if btn_mode.value() == 0:
auto_mode = not auto_mode
beep(2200, 80)
time.sleep(0.3)
if btn_on.value() == 0:
auto_mode = False
manual_state = True
beep(2400, 80)
time.sleep(0.3)
if btn_off.value() == 0:
auto_mode = False
manual_state = False
beep(1800, 80)
time.sleep(0.3)
# Read sensors
try:
dht_sensor.measure()
t = dht_sensor.temperature()
h = dht_sensor.humidity()
except:
t = 0
h = 0
light = ldr.read_u16()
motion = pir.value()
if motion:
last_motion = time.ticks_ms()
is_dark = light < light_threshold
# Relay logic
if auto_mode:
if is_dark and motion:
relay.value(1)
else:
idle = time.ticks_diff(time.ticks_ms(), last_motion) / 1000
if idle > 30:
relay.value(0)
else:
relay.value(1 if manual_state else 0)
# LEDs
led_temp.value(1 if t >= temp_threshold else 0)
led_motion.value(motion)
led_relay.value(relay.value())
# Alarm
if t >= temp_threshold:
beep(1800, 150)
# LCD display
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Smart Home WiFi")
lcd.move_to(0, 1)
lcd.putstr("T:{:.1f}C H:{:.1f}%".format(t, h))
lcd.move_to(0, 2)
lcd.putstr("Light:{} PIR:{}".format(light, motion))
lcd.move_to(0, 3)
lcd.putstr("Relay:{} Auto:{}".format(
"ON" if relay.value() else "OFF",
"ON" if auto_mode else "OFF"
))
time.sleep(1)