from machine import Pin, I2C, time_pulse_us, PWM, SPI
from ssd1306 import SSD1306_I2C
import time
from mfrc522 import MFRC522
# ==========================================
# 1. PIN CONFIGURATION
# ==========================================
# Ultrasonic
TRIG_PIN = 23
ECHO_PIN = 22
# Servo
SERVO_PIN = 32
# LED
LED_PIN = 21
# Buzzer
BUZZER_PIN = 5
# OLED
SDA_PIN = 18
SCL_PIN = 19
# MFRC522 Setup
spi = SPI(
2,
baudrate=2000000,
polarity=0,
phase=0,
sck=Pin(16),
mosi=Pin(4),
miso=Pin(0)
)
cs = Pin(17, Pin.OUT)
# ==========================================
# 2. MAIN SETTINGS
# ==========================================
# animals_database data
animals_database = {
"Max": {
"name": "Max",
"type": "Dog",
"breed": "German Shepherd",
"age": 3,
"gender": "Male",
"weight": 28,
"food": "Dry Food",
"feeding_times": ["08:00", "18:00"],
"card": "01:03:04:00"
},
"Luna": {
"name": "Luna",
"type": "Cat",
"breed": "Persian",
"age": 2,
"gender": "Female",
"weight": 4,
"food": "Wet Food",
"feeding_times": ["09:00", "19:00"],
"card": "11:22:33:44"
},
"Rocky": {
"name": "Rocky",
"type": "Dog",
"breed": "Labrador",
"age": 5,
"gender": "Male",
"weight": 32,
"food": "Dry Food",
"feeding_times": ["08:30", "18:30"],
"card": "55:66:77:88"
},
}
# ==========================================
# 3. COMPONENT SETUP
# ==========================================
# Ultrasonic
trig = Pin(TRIG_PIN, Pin.OUT)
echo = Pin(ECHO_PIN, Pin.IN)
# LED
led = Pin(LED_PIN, Pin.OUT)
# Buzzer
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.duty(0)
# OLED
i2c = I2C(
0,
scl=Pin(SCL_PIN),
sda=Pin(SDA_PIN),
freq=400000
)
oled = SSD1306_I2C(128, 64, i2c)
# ==========================================
# 4. SERVO SETUP
# ==========================================
servo = PWM(Pin(SERVO_PIN), freq=50)
def servo_angle(angle):
min_duty = 26
max_duty = 128
duty = int(
min_duty +
(angle / 180) * (max_duty - min_duty)
)
servo.duty(duty)
# ==========================================
# 5. ULTRASONIC FUNCTION
# ==========================================
def get_distance():
# Send trigger pulse
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10)
trig.value(0)
# Wait for Echo HIGH
start = time.ticks_us()
while echo.value() == 0:
if time.ticks_diff(
time.ticks_us(),
start
) > 30000:
return -1
start = time.ticks_us()
# Wait for Echo LOW
while echo.value() == 1:
if time.ticks_diff(
time.ticks_us(),
start
) > 30000:
return -1
end = time.ticks_us()
duration = time.ticks_diff(
end,
start
)
distance = (duration * 0.0343) / 2
return distance
# ==========================================
# 6. OLED FUNCTIONS
# ==========================================
def display_message(line1, line2="", line3=""):
oled.fill(0)
oled.text(line1, 0, 10)
oled.text(line2, 0, 30)
oled.text(line3, 0, 50)
oled.show()
# ==========================================
# 7. BUZZER FUNCTIONS
# ==========================================
def buzzer_on():
buzzer.freq(1000)
buzzer.duty(512)
def buzzer_off():
buzzer.duty(0)
# ==========================================
# 8. FEEDING FUNCTION
# ==========================================
dtime = "18:00"
def feed_pet(animal):
if dtime in animal["feeding_times"]:
print("Feeding started")
display_message(
"Feeding...",
"Food is being",
"dispensed"
)
# LED ON
led.value(1)
# Buzzer ON
buzzer_on()
# Open food gate
servo_angle(90)
time.sleep(2)
# Close food gate
servo_angle(0)
time.sleep(1)
# Buzzer OFF
buzzer_off()
# LED OFF
led.value(0)
display_message(
"Feeding done!",
"Gate closed"
)
print("Feeding finished")
time.sleep(3)
def find_animal(card_UID):
for animal in animals_database.values():
if animal["card"] == card_UID:
return animal
return None
# ==========================================
# 9. INITIAL STATE
# ==========================================
servo_angle(0)
led.value(0)
buzzer_off()
display_message(
"Smart Pet",
"Feeding System",
"Ready!"
)
print("================================")
print("Smart Pet Feeding System Started")
print("================================")
rfid = MFRC522(spi, cs)
# ==========================================
# 10. MAIN LOOP
# ==========================================
while True:
status, tag_type = rfid.request(rfid.REQIDL)
distance = get_distance()
if distance > 0:
print(
"Distance:",
round(distance, 1),
"cm"
)
# Pet detected
if distance < 30:
print("Pet detected!")
display_message(
"Pet detected!",
"Please wait..."
)
# LED indicates detection
led.on()
# Wait 3 seconds
time.sleep(3)
if status == rfid.OK:
status, UID = rfid.anticoll()
if len(UID) >= 4:
card_UID = "%02X:%02X:%02X:%02X" % (
UID[0],
UID[1],
UID[2],
UID[3]
)
animal = find_animal(card_UID)
print(card_UID)
print(animal)
# Check distance again
if animal is not None:
new_distance = get_distance()
if new_distance > 0 and new_distance < 30:
print("Pet stayed near feeder")
display_message(
"Pet is near",
"Starting feeding"
)
time.sleep(1)
feed_pet(animal)
# Prevent immediate re-feeding
time.sleep(5)
else:
print("Pet left")
display_message(
"Pet left",
"Waiting..."
)
led.value(0)
time.sleep(2)
else:
print("Card error")
else:
# No pet detected
led.value(0)
display_message(
"Smart Pet",
"Waiting for pet..."
)
else:
print("Ultrasonic error")
display_message(
"Sensor Error",
"Check ultrasonic"
)
led.value(0)
time.sleep(1)