from machine import Pin, I2C, ADC
from ssd1306 import SSD1306_I2C
import dht
import time
import utime
# Hardware Pin Definitions
OLED_SCL = 22
OLED_SDA = 21
DHT_PIN = 14
LIGHT_SENSOR_PIN = 34
PIR_SENSOR_PIN = 12
LED_CONTROL_PIN = 2
IR_RECEIVER_PIN = 13
# System Configuration Parameters
SCREEN_DISPLAY_TIME = 2 # Screen data refresh interval (seconds)
BOOT_INFO_DISPLAY_TIME = 3 # Boot info display duration (seconds)
LIGHT_THRESHOLD_DEFAULT = 1500 # Default light threshold (0-4095)
TEMP_THRESHOLD_DEFAULT = 28.0 # Default temperature threshold (°C)
# Hardware Initialization
i2c = I2C(0, scl=Pin(OLED_SCL), sda=Pin(OLED_SDA))
oled = SSD1306_I2C(128, 64, i2c)
dht_sensor = dht.DHT22(Pin(DHT_PIN))
light_sensor = ADC(Pin(LIGHT_SENSOR_PIN))
pir_sensor = Pin(PIR_SENSOR_PIN, Pin.IN)
led_output = Pin(LED_CONTROL_PIN, Pin.OUT)
ir_receiver = Pin(IR_RECEIVER_PIN, Pin.IN)
# System State Initialization
system_state = {
"light_threshold": LIGHT_THRESHOLD_DEFAULT,
"temp_threshold": TEMP_THRESHOLD_DEFAULT,
"display_mode": 0, # 0:System Info 1:Sensor Data 2:Settings Menu
"ir_code": 0,
"last_ir_time": 0
}
# IR Remote Key Codes (Calibrate with Actual Remote)
IR_KEYS = {
0xFFA25D: "POWER",
0xFF629D: "MODE",
0xFFE21D: "MUTE",
0xFF22DD: "PREV",
0xFF02FD: "NEXT",
0xFFC23D: "EQ",
0xFFE01F: "MINUS",
0xFFA857: "PLUS",
0xFF906F: "0",
0xFF6897: "1",
0xFF9867: "2",
0xFFB04F: "3",
0xFF30CF: "4",
0xFF18E7: "5",
0xFF7A85: "6",
0xFF10EF: "7",
0xFF38C7: "8",
0xFF5AA5: "9"
}
# IR Interrupt Handler
def ir_interrupt_handler(pin):
current_time = time.ticks_ms()
if current_time - system_state["last_ir_time"] < 50: # Debounce
return
system_state["last_ir_time"] = current_time
system_state["ir_code"] = pin.value() # Simplified; Use IR Decode Library for Real Case
ir_receiver.irq(trigger=Pin.IRQ_FALLING, handler=ir_interrupt_handler)
# System Functions
def get_current_time():
t = utime.localtime()
return f"{t[0]}-{t[1]:02d}-{t[2]:02d} {t[3]:02d}:{t[4]:02d}:{t[5]:02d}"
def read_sensor_data():
try:
dht_sensor.measure()
temperature = dht_sensor.temperature()
humidity = dht_sensor.humidity()
except OSError:
temperature = humidity = None
light_value = light_sensor.read()
pir_status = pir_sensor.value()
return {
"temperature": temperature,
"humidity": humidity,
"light": light_value,
"pir": pir_status
}
def display_boot_info():
oled.fill(0)
oled.text("Smart Home System", 0, 0)
oled.text("Name: Chen Haijing", 0, 12) # Updated to your name
oled.text("ID: 2023103030039", 0, 24) # Updated to your student ID
oled.text("Initializing...", 0, 48)
oled.show()
time.sleep(BOOT_INFO_DISPLAY_TIME)
def display_sensor_data(sensor_data):
oled.fill(0)
oled.text("Environmental Data", 0, 0)
if sensor_data["temperature"] is not None:
oled.text(f"Temp: {sensor_data['temperature']:.1f}°C", 0, 12)
else:
oled.text("Temp: Read Fail", 0, 12)
if sensor_data["humidity"] is not None:
oled.text(f"Humi: {sensor_data['humidity']:.1f}%", 0, 24)
else:
oled.text("Humi: Read Fail", 0, 24)
oled.text(f"Light: {sensor_data['light']}/4095", 0, 36)
oled.text(f"PIR: {'Detected' if sensor_data['pir'] else 'Not Detected'}", 0, 48)
oled.show()
def display_settings_menu():
oled.fill(0)
oled.text("System Settings", 0, 0)
oled.text(f"1. Light Threshold: {system_state['light_threshold']}", 0, 12)
oled.text(f"2. Temp Threshold: {system_state['temp_threshold']:.1f}°C", 0, 24)
oled.text("3. Save Settings", 0, 36)
oled.text("4. Back", 0, 48)
oled.show()
def control_system(sensor_data):
# Light Control Logic
if sensor_data["light"] < system_state["light_threshold"]:
led_output.on()
else:
led_output.off()
# Over-Temperature Alert (Extend to Control Fan, etc.)
if (sensor_data["temperature"] is not None and
sensor_data["temperature"] > system_state["temp_threshold"]):
print("Warning: Ambient Temperature Too High!")
def handle_ir_input():
if system_state["ir_code"] == 0:
return
ir_key = system_state["ir_code"]
system_state["ir_code"] = 0 # Clear Key State
# Main Screen (Display Mode 0)
if system_state["display_mode"] == 0:
if ir_key == 0xFF629D: # MODE Key
system_state["display_mode"] = 1 # Switch to Sensor Data
# Sensor Data Screen (Display Mode 1)
elif system_state["display_mode"] == 1:
if ir_key == 0xFF629D: # MODE Key
system_state["display_mode"] = 2 # Switch to Settings
# Settings Screen (Display Mode 2)
elif system_state["display_mode"] == 2:
if ir_key == 0xFF30CF: # Number 4 Key (Back)
system_state["display_mode"] = 1 # Back to Sensor Data
elif ir_key == 0xFF18E7: # Number 5 Key (Adjust Light Threshold)
adjust_threshold("light")
elif ir_key == 0xFF7A85: # Number 6 Key (Adjust Temp Threshold)
adjust_threshold("temp")
elif ir_key == 0xFF10EF: # Number 7 Key (Save Settings)
if save_settings():
oled.fill(0)
oled.text("Settings Saved!", 0, 24)
oled.show()
time.sleep(1)
def adjust_threshold(threshold_type):
if threshold_type == "light":
current_value = system_state["light_threshold"]
min_val, max_val, step, title, unit = 0, 4095, 100, "Light Threshold", ""
else: # Temperature
current_value = system_state["temp_threshold"]
min_val, max_val, step, title, unit = 0.0, 50.0, 0.5, "Temp Threshold", "°C"
oled.fill(0)
oled.text(title, 0, 0)
while True:
oled.fill_rect(0, 12, 128, 12, 0) # Clear Value Line
oled.text(f"Current: {current_value}{unit}", 0, 12)
oled.text("+/-: Adjust MODE: Save", 0, 48)
oled.show()
# Wait for IR Input
while system_state["ir_code"] == 0:
time.sleep(0.01)
ir_key = system_state["ir_code"]
system_state["ir_code"] = 0
if ir_key == 0xFFE01F: # MINUS Key
current_value = max(min_val, current_value - step)
elif ir_key == 0xFFA857: # PLUS Key
current_value = min(max_val, current_value + step)
elif ir_key == 0xFF629D: # MODE Key (Confirm)
if threshold_type == "light":
system_state["light_threshold"] = current_value
else:
system_state["temp_threshold"] = current_value
break
def save_settings():
try:
with open("settings.txt", "w") as f:
f.write(f"{system_state['light_threshold']}\n")
f.write(f"{system_state['temp_threshold']}\n")
return True
except:
return False
def load_settings():
try:
with open("settings.txt", "r") as f:
lines = f.readlines()
if len(lines) >= 2:
system_state["light_threshold"] = int(lines[0].strip())
system_state["temp_threshold"] = float(lines[1].strip())
return True
except:
return False
# Main Program
def main():
display_boot_info()
if not load_settings():
print("Using Default Settings")
last_display_time = time.ticks_ms()
while True:
sensor_data = read_sensor_data()
control_system(sensor_data)
handle_ir_input()
current_time = time.ticks_ms()
if current_time - last_display_time > SCREEN_DISPLAY_TIME * 1000:
last_display_time = current_time
if system_state["display_mode"] == 0:
oled.fill(0)
oled.text("Smart Home System", 0, 0)
oled.text(get_current_time(), 0, 12)
oled.text(f"Uptime: {time.ticks_ms()//1000}s", 0, 24)
oled.text("Press MODE for Data", 0, 48)
oled.show()
elif system_state["display_mode"] == 1:
display_sensor_data(sensor_data)
elif system_state["display_mode"] == 2:
display_settings_menu()
time.sleep(0.1)
if __name__ == "__main__":
main()