from machine import Pin, PWM, I2C, time_pulse_us
from time import sleep, sleep_us, sleep_ms
import ssd1306
# Configuring input and output ports
trig = Pin(26, Pin.OUT)
echo = Pin(27, Pin.IN)
led = Pin(4, Pin.OUT)
buzzer_pin = Pin(15, Pin.OUT) #We will dynamically apply PWM to it to generate musical tones.
servo = PWM(Pin(32), freq=50)
# Configuring the OLED screen
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Settings and control thresholds
pet_distance = 20 # المسافة الآمنة للكشف (20 سم)
feed_interval = 10 # الفاصل الزمني لجدول التغذية المحاكى
counter = 0 # عداد لمحاكاة مرور الوقت
meal_due = False # متغير يوضح هل حان موعد الوجبة
pet_present = False # هل الأليف موجود؟
sleep_timer = 0 # عداد خمول الشاشة لتوفير الطاقة
is_sleeping = False # حالة نوم شاشة OLED
# مولد النغمات الإبداعي باستخدام الـ PWM المتغير التردد
def play_tone(frequency, duration_ms):
if frequency == 0:
buzzer_pin.off()
sleep_ms(duration_ms)
return
try:
bz_pwm = PWM(Pin(15), freq=frequency, duty=512)
sleep_ms(duration_ms)
bz_pwm.deinit() # إيقاف النغمة فور انتهاء المؤقت
except:
pass
# إعادة المنفذ للحالة الرقمية المنخفضة لضمان الهدوء
buzzer_pin.init(Pin.OUT)
buzzer_pin.off()
# معزوفات مخصصة مبدعة
def play_happy_meal_melody():
# نغمة مبهجة صاعدة للإطعام (C5 -> E5 -> G5 -> C6)
notes = [523, 659, 784, 1047]
for note in notes:
play_tone(note, 150)
sleep_ms(30)
def play_chirp_melody():
# نغمة زقزقة ترحيبية ثنائية سريعة ولطيفة عند كشف الأليف
play_tone(880, 80)
sleep_ms(30)
play_tone(1200, 100)
# تحريك محرك السيرفو لزاوية محددة بدقة
def move_servo(angle):
pulse = int(500000 + (angle / 180) * 2000000)
servo.duty_ns(pulse)
# قياس المسافة بدقة عبر الحساس فوق الصوتي [
def get_distance():
trig.off()
sleep_us(2)
trig.on()
sleep_us(10)
trig.off()
duration = time_pulse_us(echo, 1, 1000000)
if duration < 0:
return 999.0 # في حال عدم كشف أي جسم
distance = duration * (0.0343 / 2) # حساب المسافة [112, 116]
return distance
# تحديث شاشة OLED بلمسات تصميمية مميزة [124, 125]
def show_oled(state, distance, feed_counter, sleeping):
oled.fill(0)
# ميزة إبداعية: وضع توفير الطاقة
if sleeping:
oled.text("Zzz...", 50, 15)
oled.text("[POWER SAVING]", 10, 40)
oled.show()
return
# تصميم ترويسة الشاشة بصرياً
oled.text("=== PET FEEDER ===", 0, 0)
# عرض الحالات بأشكال مميزة وجذابة
if state == "READY":
oled.text("State: READY [ ]", 0, 16)
elif state == "PET-DETECTED":
oled.text("State: HELLO! ^_^", 0, 16)
elif state == "FEEDING":
oled.text("State: FEEDING!!!", 0, 16)
oled.text(f"Dist: {int(distance)}cm", 0, 32)
oled.text(f"Schedule: {feed_counter}/{feed_interval}", 0, 44)
# حالة الوجبة [125]
if meal_due:
oled.text("Meal: DUE", 0, 56)
else:
oled.text("Meal: WAIT", 0, 56)
oled.show()
# تعيين الحالة الابتدائية عند بدء التشغيل
move_servo(0) # البوابة مغلقة
led.off()
buzzer_pin.off()
show_oled("READY", 999, 0, False)
# الحلقة اللانهائية للمراقبة
while True:
distance = get_distance()
# تتبع جدول الوجبات تلقائياً [
if not meal_due:
counter += 1
if counter >= feed_interval:
meal_due = True
# التحقق من وجود الأليف وإدارة وضع توفير الطاقة لشاشة OLED
if distance <= pet_distance:
pet_present = True
sleep_timer = 0 # تصفير مؤقت الخمول بمجرد استشعار حركة
if is_sleeping:
is_sleeping = False
play_chirp_melody() # تغريدة ترحيبية عند إيقاظ النظام
else:
pet_present = False
sleep_timer += 1
# تفعيل وضع توفير الطاقة للشاشة بعد 10 ثوانٍ من عدم النشاط
if sleep_timer >= 10 and not meal_due and not pet_present:
is_sleeping = True
# منطق اتخاذ القرار الذكي بالإستعانة بالمعامل المنطقي and
if meal_due and pet_present:
# حالة تقديم الطعام (FEEDING)
is_sleeping = False
show_oled("FEEDING", distance, counter, False)
# تفعيل المعزوفة الموسيقية للإطعام وتفعيل المؤشر الضوئي
play_happy_meal_melody()
led.on()
# فتح بوابة الطعام بمحرك السيرفو [128]
move_servo(90)
# ميزة إبداعية: شاشة تحميل متحركة تبين عملية توزيع الأكل
for pct in range(0, 101, 20):
oled.fill(0)
oled.text("== FEEDING PET ==", 0, 0)
oled.text("Dispensing food...", 0, 20)
oled.text("[", 10, 40)
oled.text("]", 110, 40)
bars = "=" * (pct // 10)
oled.text(bars, 20, 40)
oled.text(f"{pct}% Completed", 15, 54)
oled.show()
sleep(1) # يعادل إجمالي 3 ثوانٍ وهي فترة بقاء البوابة مفتوحة
move_servo(0) # إغلاق البوابة تلقائياً
# إعادة تعيين النظام وبدء دورة جدول جديدة
led.off()
counter = 0
meal_due = False
# رسالة ختامية لطيفة للأليف
oled.fill(0)
oled.text("== PET FEEDER ==", 0, 0)
oled.text("Dispenser CLOSED", 0, 25)
oled.text("Enjoy your meal!", 0, 45)
oled.show()
sleep(2)
elif pet_present:
# حالة اكتشاف الأليف دون وصول موعد الطعام
led.on()
if counter % 5 == 0: # إصدار تغريدة لطيفة بشكل متقطع لجلب انتباهه
play_chirp_melody()
show_oled("PET-DETECTED", distance, counter, False)
else:
# حالة الجاهزية والانتظار [129]
led.off()
show_oled("READY", distance, counter, is_sleeping)
sleep(0.5)