My Account

Wish List (0)

PiBorg is still open and we are still shipping orders.
We expect orders may be delayed by a day or two due to COVID-19.


Written by in Build, PicoBorg - Build on .

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, 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 Make the script executable using chmod +x and run using sudo ./ 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
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

# 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
        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
            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)
        count -= 1

# Function to save the stepper state and disable all drive
def MoveStandby():
    global savedState
    savedState = [
    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[0]:
        GPIO.output(DRIVE_1, GPIO.HIGH)
        GPIO.output(DRIVE_1, GPIO.LOW)
    if savedState[1]:
        GPIO.output(DRIVE_2, GPIO.HIGH)
        GPIO.output(DRIVE_2, GPIO.LOW)
    if savedState[2]:
        GPIO.output(DRIVE_3, GPIO.HIGH)
        GPIO.output(DRIVE_3, GPIO.LOW)
    if savedState[3]:
        GPIO.output(DRIVE_4, GPIO.HIGH)
        GPIO.output(DRIVE_4, GPIO.LOW)

# Make a list of fed times to avoid double feedings
fedAlready = []
for feedTime in feedSchedule:
    fedAlready.append([feedTime[0], feedTime[1], False])
    print 'At %s feed %d' % (feedTime[0], feedTime[1])
hasResetAtMidnight = False

    # Start by turning all drives off
    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
    if not holdWhenWaiting:
    # 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[2] = 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[0] == now:
                # Check if this feed has beed done, if not feed
                if not feedTime[2]:
                    print '%s feeding %d' % (feedTime[0], feedTime[1])
                    if not holdWhenWaiting:
                    if not holdWhenWaiting:
                    feedTime[2] = True
        # Wait for pollPeriod

except KeyboardInterrupt:
    # CTRL+C exit, turn off the drives and release the GPIO pins
    print 'Terminated'
    raw_input('Turn the power off now, press ENTER to continue')
Last update: Nov 05, 2017

Related Article

Related Products


Leave a Comment

Leave a Reply

The product is currently Out-of-Stock. Enter your email address below and we will notify you as soon as the product is available.