from machine import Pin, I2C, PWM
from time import sleep, ticks_ms, localtime
from ssd1306 import SSD1306_I2C
from hcsr04 import HCSR04
# -------------------- 初始化 --------------------
# LED
led1 = Pin(0, Pin.OUT) # 早餐
led2 = Pin(1, Pin.OUT) # 晚餐
led3 = Pin(2, Pin.OUT) # 食物剩余
led4 = Pin(3, Pin.OUT) # 水位状态
# 舵机
servo = PWM(Pin(4))
servo.freq(50)
# 超声波传感器
sensor_food = HCSR04(trigger_pin=8, echo_pin=9)
sensor_water = HCSR04(trigger_pin=10, echo_pin=11)
# OLED
i2c = I2C(0, scl=Pin(27), sda=Pin(26))
oled = SSD1306_I2C(128, 64, i2c)
# 控制变量
breakfast_done = False
dinner_done = False
daily_reset_done = False
led3_state = False
led4_state = False
led3_last_toggle = ticks_ms()
led4_last_toggle = ticks_ms()
led_blink_interval = 500 # ms
# -------------------- 函数 --------------------
def feed_pet():
servo.duty_u16(7000) # 打开
sleep(1.5)
servo.duty_u16(3000) # 关闭
sleep(0.5)
def check_food_eaten():
distance = sensor_food.distance_cm()
if distance is None:
return True
return distance > 5
def check_water_level():
distance = sensor_water.distance_cm()
if distance is None:
return False
return distance < 4
def update_oled(message):
oled.fill(0)
oled.text("Auto Feeder", 0, 0)
oled.text(message, 0, 16)
oled.show()
def reset_daily():
global breakfast_done, dinner_done, daily_reset_done
breakfast_done = False
dinner_done = False
daily_reset_done = True
led1.value(0)
led2.value(0)
print("Daily reset.")
update_oled("Daily reset")
# -------------------- 主循环 --------------------
while True:
now = localtime()
hour, minute, second = now[3], now[4], now[5]
# 0点重置
if hour == 0 and minute == 0 and not daily_reset_done:
reset_daily()
if hour != 0:
daily_reset_done = False
current_ms = ticks_ms()
# -------------------- 水位检查 & LED --------------------
water_ok = check_water_level()
if not water_ok:
if current_ms - led4_last_toggle >= led_blink_interval:
led4_state = not led4_state
led4.value(led4_state)
led4_last_toggle = current_ms
else:
led4.value(1)
# -------------------- 食物检查 & LED --------------------
food_eaten = check_food_eaten()
if not food_eaten:
if current_ms - led3_last_toggle >= led_blink_interval:
led3_state = not led3_state
led3.value(led3_state)
led3_last_toggle = current_ms
update_oled("Food NOT eaten!")
sleep(0.1) # 避免闪烁太快
continue
else:
led3.value(0)
# -------------------- 投喂 --------------------
if hour == 9 and not breakfast_done:
feed_pet()
led1.value(1)
breakfast_done = True
update_oled("Breakfast OK")
print("Fed breakfast")
if hour == 21 and not dinner_done:
feed_pet()
led2.value(1)
dinner_done = True
update_oled("Dinner OK")
print("Fed dinner")
# -------------------- OLED 显示 --------------------
if breakfast_done and dinner_done:
update_oled("All meals OK\n" + ("Water OK" if water_ok else "Water LOW"))
sleep(0.1)