By default the eyes will animate on their own, looking around randomly. With some minor additional hardware (and enabling corresponding lines in the code), the eyes’ direction, blinks and pupil dilation can be controlled manually or with sensors…

At the bottom-right of the bonnet are a few extra connection points for 5 Volts3.3 Volts and ground, if you have a circuit that needs them. These are OK for small loads like ICs or a few LEDs, but not for big things like servos, which will need their own power source.

To the left are four analog input pins (along with four more 3.3V and ground points). You can use these to interface analog circuits such as a joystick to steer the eyes, photocell to make the pupils react to light, or perhaps to monitor battery voltage (use a voltage divider in this case, since the analog input must be 0 to 3.3 Volts).

Woops, we swapped SDA and SCL on the silkscreen - apologies! SCL is the left-most pin, and SDA is the pin to the right of it!

Additionally, most of the GPIO pins are broken out in a single row across the bonnet. Some of these serve special purposes and should be avoided, but technical users still have access to them if really needed…

  • TX and RX are available as GPIO14 and 15 if the serial console is disabled with raspi-config.
  • SPI0 (SPI bus used for the right eye) uses GPIO8-11 (CE0, MISO, MOSI and SCLK, respectively). Steer clear!
  • SPI1 (second SPI bus used for left eye) uses GPIO16 (CE2) and 19-21 (MISO, MOSI, SCLK). Avoid! Also, I2S audio devices can’t be used because the pins overlap.
  • GPIO5 and 6 connect to the DC and RESET pins of both displays, so these too should be avoided unless you have some special situation.

Analog Controls

Any analog controls that are added should include connections to the 3.3V and GND pins. Do not use the 5V pins or there will be…trouble.

XOUT and YOUT from a joystick can connect to analog pins A0 and A1.

The eyes move autonomously by default — settings in the code enable the joystick instead.

If you need to mount the joystick in a different orientation, there are also settings to invert each axis. Swap the X and Y pins in the code to use the joystick sideways.

This thumb stick has a click feature, which could be used to control eye blinks if desired. The smaller “mini” stick doesn’t have this, but is extra tiny for working into a costume or puppet.

To have the pupils contract or expand in response to light, connect a photocell and 10K resistor in series. The midpoint connects to analog pin A2.

Analog input for the pupils (either photocell or the dial below) are enabled in the code by default. You can comment out IRIS_PIN in the code to have this move autonomously.

For manual control of pupil dilation (instead of responding to light) a 10K potentiometer can be used. The center leg connects to analog pin A2 (same input as the photocell, just substituting a different analog control).


The eyes normally blink autonomously, but you can also add one or more buttons to make them blink (or even wink individually) on command.

For all buttons, connect one leg of each to GND, and the opposite leg to a digital pin:

  • GPIO Pin 22 is the left eye wink.
  • GPIO Pin 23 blinks both eyes.
  • GPIO Pin 24 winks the right eye.

If using our analog joystick breakout board, that stick includes a clicky button when you press down on it (on the SEL pin). This can optionally be used for manual blink control, or you can use a separate button for this (I find the joystick button a bit hamfisted).

Software Changes

Adjustments to the code must be made to use any of the above features. You’ll find the code in /boot/Pi_Eyes/ It’s located in /boot to simplify “offline” editing on another system…if editing on the same Pi where it runs, you may need to edit as root (e.g. “sudo nano /boot/Pi_Eyes/”).

After making changes, you could hunt down the background Python process that was run at startup, kill and restart…but it’s usually easiest just to reboot.

Hardware config settings can be found near the top of the code:

# INPUT CONFIG for eye motion ----------------------------------------------

JOYSTICK_X_IN   = -1    # Analog input for eye horiz pos (-1 = auto)
JOYSTICK_Y_IN   = -1    # Analog input for eye vert position (")
PUPIL_IN        = -1    # Analog input for pupil control (-1 = auto)
JOYSTICK_X_FLIP = False # If True, reverse stick X axis
JOYSTICK_Y_FLIP = False # If True, reverse stick Y axis
PUPIL_IN_FLIP   = False # If True, reverse reading from PUPIL_IN
TRACKING        = True  # If True, eyelid tracks pupil
PUPIL_SMOOTH    = 16    # If > 0, filter input from PUPIL_IN
PUPIL_MIN       = 0.0   # Lower analog range from PUPIL_IN
PUPIL_MAX       = 1.0   # Upper "
WINK_L_PIN      = 22    # GPIO pin for LEFT eye wink button
BLINK_PIN       = 23    # GPIO pin for blink button (BOTH eyes)
WINK_R_PIN      = 24    # GPIO pin for RIGHT eye wink button
AUTOBLINK       = True  # If True, eyes blink autonomously

For example, to enable analog joystick input and a photocell, set JOYSTICK_X_IN, JOYSTICK_Y_IN and/or PUPIL_IN to analog channel numbers (0 to 3). If the response from the stick or sensor is backwards, set JOYSTICK_X_FLIP, JOYSTICK_Y_FLIP and/or PUPIL_IN_FLIP to “True” as needed.

This guide was first published on Jan 11, 2017. It was last updated on Mar 08, 2024.

This page (Customizing the Hardware) was last updated on Mar 08, 2024.

Text editor powered by tinymce.