FedPet - Use your Raspberry Pi to feed your pet
Everybody likes technology, even pets do!
We thought it would be great if you could setup a Raspberry Pi to feed a pet at certain times of day, and a controlled amount. Thanks to Tristan Linnell for the idea :)
We will use a PicoBorg to control a 6 wire stepper motor, which when driven will rotate a fixed amount for each step (the angle is specific to the stepper).
For your pets delight we present FedPet.py, a Python script which watches the time and rotates a stepper when scheduled
Here's the code, you can download the FedPet script file as text here
Save the text file on your pi as FedPet.py
Make the script executable using
chmod +x FedPet.py
and run using
You will probably want to change
feedSchedule, lines 6-10, to your appropriate feed schedule and amounts.
#!/usr/bin/env python # coding: Latin-1 # Schedule for pet feeding, list of tupples for feed times # formatted as ('HH:MM', c) where HH:MM is the time of day and c is the feed count (steps) feedSchedule = [ ('08:30', 25), ('14:00', 10), ('21:00', 25) ] pollPeriod = 20 # Number of seconds to wait between polls, should be < 60 holdWhenWaiting = False # True to keep the stepper powered when not rotating, false to stop powering # Import libary functions we need import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) import time # Set which GPIO pins the drive outputs are connected to DRIVE_1 = 4 # Black DRIVE_2 = 18 # Green DRIVE_3 = 8 # Red DRIVE_4 = 7 # Blue # Yellow and White are +ve centre taps # Tell the system how to drive the stepper sequence = [DRIVE_1, DRIVE_3, DRIVE_2, DRIVE_4] # Order for stepping (see data sheet for the stepper motor) stepDelay = 0.002 # Delay between steps # Set all of the drive pins as output pins GPIO.setup(DRIVE_1, GPIO.OUT) GPIO.setup(DRIVE_2, GPIO.OUT) GPIO.setup(DRIVE_3, GPIO.OUT) GPIO.setup(DRIVE_4, GPIO.OUT) # Function to set all drives off def MotorOff(): global step GPIO.output(DRIVE_1, GPIO.LOW) GPIO.output(DRIVE_2, GPIO.LOW) GPIO.output(DRIVE_3, GPIO.LOW) GPIO.output(DRIVE_4, GPIO.LOW) step = -1 # Function to perform a sequence of steps as fast as allowed def MoveStep(count): global step # Choose direction based on sign (+/-) if count < 0: dir = -1 count *= -1 else: dir = 1 # Loop through the steps while count > 0: # Set a starting position if this is the first move if step == -1: GPIO.output(DRIVE_4, GPIO.HIGH) step = 0 else: step += dir # Wrap step when we reach the end of the sequence if step < 0: step = len(sequence) - 1 elif step >= len(sequence): step = 0 # For this step turn one of the drives off and another on if step < len(sequence): GPIO.output(sequence[step-2], GPIO.LOW) GPIO.output(sequence[step], GPIO.HIGH) time.sleep(stepDelay) count -= 1 # Function to save the stepper state and disable all drive def MoveStandby(): global savedState savedState = [ GPIO.input(DRIVE_1), GPIO.input(DRIVE_2), GPIO.input(DRIVE_3), GPIO.input(DRIVE_4), ] GPIO.output(DRIVE_1, GPIO.LOW) GPIO.output(DRIVE_2, GPIO.LOW) GPIO.output(DRIVE_3, GPIO.LOW) GPIO.output(DRIVE_4, GPIO.LOW) # Function to resume the stepper state def MoveResume(): global savedState if savedState: GPIO.output(DRIVE_1, GPIO.HIGH) else: GPIO.output(DRIVE_1, GPIO.LOW) if savedState: GPIO.output(DRIVE_2, GPIO.HIGH) else: GPIO.output(DRIVE_2, GPIO.LOW) if savedState: GPIO.output(DRIVE_3, GPIO.HIGH) else: GPIO.output(DRIVE_3, GPIO.LOW) if savedState: GPIO.output(DRIVE_4, GPIO.HIGH) else: GPIO.output(DRIVE_4, GPIO.LOW) # Make a list of fed times to avoid double feedings fedAlready =  for feedTime in feedSchedule: fedAlready.append([feedTime, feedTime, False]) print 'At %s feed %d' % (feedTime, feedTime) hasResetAtMidnight = False try: # Start by turning all drives off MotorOff() raw_input('You can now turn on the power, press ENTER to continue') # Move to initial position, then either hold or let go as needed MoveStep(1) if not holdWhenWaiting: MoveStandby() # Loop forever while True: # Get the current time formatted as HH:MM now = time.strftime('%H:%M') # See if we have reached midnight (reset fed list) if now == '00:00': # Reset all times to unfed if not done already if not hasResetAtMidnight: for feedTime in fedAlready: feedTime = False hasResetAtMidnight = True elif now == '00:01': # Past midnight, rest latch as we will reset all feeds tomorrow hasResetAtMidnight = False # Check to see if any feed time matches the current time for feedTime in fedAlready: if feedTime == now: # Check if this feed has beed done, if not feed if not feedTime: print '%s feeding %d' % (feedTime, feedTime) if not holdWhenWaiting: MoveResume() MoveStep(feedTime) if not holdWhenWaiting: MoveStandby() feedTime = True # Wait for pollPeriod time.sleep(pollPeriod) except KeyboardInterrupt: # CTRL+C exit, turn off the drives and release the GPIO pins print 'Terminated' MotorOff() raw_input('Turn the power off now, press ENTER to continue') GPIO.cleanup()