# Animated Snake Eyes Bonnet for Raspberry Pi

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/038/351/medium800/raspberry_pi_eyes-800x800.jpg?1484183629)

The _ **Snake Eyes Bonnet** _ is a **Raspberry Pi accessory** for driving **two** &nbsp;small OLED or TFT LCD displays, and also provides four **analog inputs** for sensors.

It's fantastic for making cosplay masks, props, spooky sculptures for Halloween, animatronics, robots...anything where you want to add a pair of animated eyes!

![](https://cdn-learn.adafruit.com/assets/assets/000/038/347/medium800/raspberry_pi_3356_iso_demo_02_ORIG.jpg?1484173549)

It’s a follow-on of sorts to another project:&nbsp;**_[Electronic Animated Eyes Using Teensy 3.2](../../../animated-electronic-eyes-using-teensy-3-1)._&nbsp;**The Teensy 3.2 is a _very_ capable microcontroller, and the code for that project squeezed every bit of space and performance from it. I had been experimenting with the Raspberry Pi as an alternative…though still somewhat experimental, why not make that work available to others?

The Raspberry Pi offers&nbsp;some potential **benefits:**

- Hardware-accelerated **3D graphics** (OpenGL), including **antialiasing**.
- A **faster CPU** , ample **RAM** and dual SPI buses could&nbsp;yield faster frame rates.
- Standard graphics formats like **JPEG** , **PNG** and **SVG** can be decoded on the fly; **no preprocessing step**.
- The eye rendering code is&nbsp;written in a **high-level language** &nbsp;—&nbsp;Python&nbsp;— making it&nbsp;easier to customize.

And some&nbsp;possible **downsides&nbsp;** to the Pi:

- Raspberry&nbsp;Pi takes time to boot an operating system off an SD card, whereas&nbsp;Teensy is **instant-on** with all code in flash memory, . The Pi also requires an explicit **shutoff procedure** &nbsp;([usually](../../../../read-only-raspberry-pi)).
- The Raspberry Pi is **not as suitable** for **wearable** applications…it’s larger, uses more power, and the SD card makes it less&nbsp;rugged.

This is a somewhat technical and not-inexpensive project. **Please read through everything first before commiting.** If it seems daunting, the original _[Teensy Eyes](../../../animated-electronic-eyes-using-teensy-3-1)_ are more “Arduino-like” to build and customize, or other guides like [_Animating Multiple LED Backpacks_](../../../animating-multiple-led-backpacks) provide a more approachable introduction to code and electronics with less of an investment.

 **A Raspberry Pi 2 or greater is highly recommended.** The code _will_ run on a Pi Zero or other single-core Raspberry Pi boards, but performance lags quite a bit. _Pi 4 and Pi 5 now work._

# Animated Snake Eyes Bonnet for Raspberry Pi

## Hardware Assembly

Warning: 

Info: 

### Compatible&nbsp;Devices

- The code for this project works **only** with our **[128x128 pixel OLED](https://www.adafruit.com/product/1431)**&nbsp;and **[TFT](https://www.adafruit.com/product/2088)**&nbsp;displays and **[240x240 pixel IPS TFT](https://www.adafruit.com/product/3787)** displays. Other&nbsp;displays such as our&nbsp;160x128 TFT or various PiTFT displays **ARE NOT SUPPORTED AT ALL** , period, not even sorta.
- Any recent Raspberry Pi board with the **40-pin GPIO header** should work. The very earliest Pi boards — Model A and B, with the 26-pin GPIO header — are not compatible.
- **A Raspberry Pi 2 or greater is highly recommended.** &nbsp;The code&nbsp;_will_&nbsp;run on a Pi Zero or other single-core Raspberry Pi boards, but performance lags quite a bit. _Pi 4 works now, which was previously incompatible._

# Plan a Head

Before committing to any particular hardware, think your project through. There are some decisions to be made…

- **One** display or **two**? You don’t _have_ to connect two displays…some of the most creative variants of the “Teensy eyes” [had only a _single_ eye](../../../../purple-people-eater).
- **[OLED](https://www.adafruit.com/product/1431)**, **[TFT LCD](https://www.adafruit.com/product/2088)**&nbsp;or **[IPS TFT](https://www.adafruit.com/product/3787)** displays? OLEDs have&nbsp;a **wide viewing angle** and **excellent contrast** and **color saturation** , but they’re somewhat&nbsp; **pricey** , and have a **finite lifespan** (albeit _many thousands_ of hours). **TFTs** make good **economy** displays if you’re okay with the slightly **washed-out** appearance. **IPS TFT** displays are in-between in cost and _super_ sharp!
- What model of **Raspberry Pi** to drive it? The latest **multi-core** boards&nbsp;have enough performance for **buttery&nbsp;smooth animation** …but their **size** and **power draw** &nbsp;might make them best for stationary displays, like maybe a Halloween window prop. Costume and portable installations may fare better with the diminutive **Pi Zero** , though the animation will be much less smooth.
- Will the animation&nbsp;be running **autonomously** , or do you plan to control the eyes&nbsp;with a **joystick** and **buttons**? Will the pupils react to **light**? These require additional&nbsp;components.

There’s one more factor to consider: **how do you want everything connected?** &nbsp;Think about your intended installation. Is it temporary or permanent? Is space at a premium or do you have ample working room? These can influence your choice of wiring and connectors.

The breakout pins along the edge of each display board are&nbsp;wired up to matching pins&nbsp;on the bonnet boards. But you need the _correct_&nbsp;row for each display type…

**If using OLED display(s):** use the “upper” rows&nbsp;(with the word “OLED” between them).

There are **11 pins** on the OLED breakout boards, which map directly to the 11 pins on the bonnet board.

**Make absolutely certain the wires are in the same order.** “SI” and “G” on the display board should go to “SI” and “G” on the bonnet, and each pin in-between…no wires should cross.

![raspberry_pi_bonnet-oled-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/037/983/medium640/raspberry_pi_bonnet-oled-pins.png?1481651918)

![raspberry_pi_OLEDs.png](https://cdn-learn.adafruit.com/assets/assets/000/037/984/medium640/raspberry_pi_OLEDs.png?1481651947)

**If using TFT or IPS display(s):**&nbsp;use the “lower” rows&nbsp;(with the word “TFT” between them).

There are&nbsp; **11 pins** &nbsp;on the TFT&nbsp;breakout boards, which map directly to the 11 pins on the bonnet board.

**Make absolutely certain the wires are in the same order.** &nbsp;“Vin” and “Lite” on the display board should go to “Vin” and “Lite” on the bonnet, and each pin in-between…no wires should cross.

![raspberry_pi_bonnet-tft-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/037/986/medium640/raspberry_pi_bonnet-tft-pins.png?1481652002)

![raspberry_pi_TFTs.png](https://cdn-learn.adafruit.com/assets/assets/000/037/987/medium640/raspberry_pi_TFTs.png?1481652018)

Warning: 

There’s a common trope in science fiction stories: that there is no “up” or “down” in space. Wiring these displays is a little like that…it doesn’t matter if the wires or headers&nbsp;come out the _front_ or _back_ of the display breakout board, or use _straight_ or _right-angle_ pins…as long as those wires get from the display to the bonnet in the **same positions and order** , everything’s good.

(As for up and down: right now the software assumes the displays are oriented&nbsp;with the **breakout pins along the top edge** ; other rotations are not currently handled.)

Here’s a probable layout for a non-portable installation. **Straight header pins** have been soldered to the bonnet board and the displays, projecting “up” and “back,” respectively.&nbsp;Two 11-pin **female-to-female** ribbon cables then join&nbsp;everything.

This might be easiest to assemble (and disassemble), and the straight header pins on the displays make them easy to **re-use** in&nbsp;breadboard projects later.

![raspberry_pi_OLED-straight-pins.jpg](https://cdn-learn.adafruit.com/assets/assets/000/038/048/medium640/raspberry_pi_OLED-straight-pins.jpg?1481928190)

…but that’s not the only option.

This TFT display has **right-angle header pins** &nbsp;on the front of the board (front, back, doesn’t matter as long as the wires connect in the same order). This makes it very slim, but also a fair bit taller.

And this OLED has an 11-pin ribbon cable **directly soldered** to the board, no header pins at all. Again…front or back, ribbon could go straight out or can double back across the board…it all depends on your construction and space needs, as long as the pin order is followed. This is the most space-efficient, but requires patience and ace soldering skills, and isn’t easily re-used in other projects.

![raspberry_pi_alt-connections.jpg](https://cdn-learn.adafruit.com/assets/assets/000/038/049/medium640/raspberry_pi_alt-connections.jpg?1481928728)

 **If using “rainbow” ribbon cables:** these have 10 colors, while the displays use 11 wires…this means the cables will have the **same color** &nbsp;wire along both edges. Therefore, **DO NOT rely on a visual mnemonic** like “black wire is ground” or “red wire is Vin,” because your cable may have **two** black wires, or two reds, or two _anything._ Instead, make sure to **manually follow the first wire all the way from the bonnet to the display** , make sure they line up right, then install the remaining wires in order.

If you’re _really_ economizing for space, here’s a secret: only 7 wires are really _needed…_it’s just easier and less error-prone to solder a header at each end and plug all 11&nbsp;wires straight through. If using the OLED display, the SC, SO, CD and 3V pins can optionally be skipped. If using TFT, the 3v3 SO, CCS and Lite pins can be skipped. Make certain the exact same pins are skipped at the bonnet end, don’t mix them up!

To ensure a clean signal from bonnet to displays, aim&nbsp;to keep your wiring **short and tidy.** Electrical interference can lead to animation glitches…we’ll explain on the next page how to dial that back if needed. It’s _possible_ to use long ribbon cables (even a couple meters), but it invites problems with interference or signal reliability.

 **For optional features like joysticks, light sensors, blink and halt&nbsp;buttons, see the&nbsp;“Customizing the Hardware” page.**

![raspberry_pi_bonnet-analog-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/038/070/medium640/raspberry_pi_bonnet-analog-pins.png?1482116005)

![raspberry_pi_bonnet-gpio-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/038/071/medium640/raspberry_pi_bonnet-gpio-pins.png?1482116016)

When finished&nbsp;soldering, you can **peel the clear plastic covering off the displays.** It’s meant to protect them in shipping and during soldering. But unlike the screen protector on a phone or tablet, it’s not optically pure and&nbsp;makes the display look cloudy.

The project thumbnail image shows lenses and&nbsp; **3D-printed enclosures**. These were a carry-over from [an earlier project that used 1.5" acrylic cabochons](https://learn.adafruit.com/animated-electronic-eyes/3d-printing), before we started carrying proper&nbsp;[lenses](https://www.adafruit.com/product/3917) which provide better optics and have a mounting flange…but we don’t have enclosure designs for those, you’d need to model something yourself.

# Animated Snake Eyes Bonnet for Raspberry Pi

## Software Installation

We’ll start by installing a suitable version of **Raspberry Pi OS** onto a SD card. If this is your first time or you need a refresher, [we have a separate guide explaining the process](https://learn.adafruit.com/adafruit-raspberry-pi-lesson-1-preparing-and-sd-card-for-your-raspberry-pi/overview)&nbsp;(opens in new window).

## Pi OS Release
Recommended Raspberry Pi boards (Pi 3B, Pi 4, Pi 5)

Raspberry Pi OS Trixie

Desktop 32-bit is required.

Lite versions are not&nbsp;supported. Do not select the 64-bit variant.

 **If your target system is a Raspberry Pi Zero, you may find the setup process easier with a spare full-size Raspberry Pi board with Ethernet and/or USB, then move the card over to the Pi Zero when finished.&nbsp;** If this is not an option, see&nbsp;[this guide](../../../../turning-your-raspberry-pi-zero-into-a-usb-gadget)&nbsp;for steps to make the Pi Zero act as a “USB Ethernet gadget,” and also create a file called “ssh” in the boot volume to enable ssh login.

## Enable SSH

It’s usually easiest to set up and install this project remotely over a network, so you can copy-and-paste commands from this page to the command line.

If using the **Raspberry Pi Imager** application: before writing the card, press Control+Shift+X (Windows) or Command+Shift+X (Mac) to open the Advanced Options menu. Here you can **Enable SSH** for remote access. If you want to set up WiFi instead of a wired Ethernet connection, those options are also in this menu. _Now_ you can write the card!

If using **Balena Etcher** or other application: after writing the card, don’t eject! Create an empty file called **ssh** in the **/boot** partition. This will enable SSH over a wired Ethernet connection. If you want WiFi, you’ll have to connect temporarily with Ethernet and configure wireless through **raspi-config** …or see below.

A third option—and required if you only have WiFi but no Ethernet—is to do this on the Raspberry Pi after first boot, with monitor and keyboard connected. The **raspi-config** utility includes options for enabling WiFi and SSH. Then the rest of this installation can be done remotely.

Once your Raspberry Pi is powered up and connected to a network you can follow the steps below to install the Pi Eyes software.

If you're familiar with connecting to the [Raspberry Pi&nbsp;over SSH](../../../../adafruits-raspberry-pi-lesson-6-using-ssh/overview)&nbsp;you can use an SSH terminal application to connect and skip down to the [install commands section below](../../../../raspberry-pi-video-looper/installation#install-commands).

![](https://cdn-learn.adafruit.com/assets/assets/000/107/770/medium800/pi_a___b___2__3_raspberry_pi_Screenshot_from_2015-02-11_14_33_16.png?1641925712)

# Install Commands

Run the following at the command line:

```auto
cd
curl https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/pi-eyes.sh >pi-eyes.sh
sudo bash pi-eyes.sh
```

This downloads and runs a script which installs all the prerequisite software and does some system configuration. It will ask a few questions along the way…

- Is the target system a Pi 4-type board, or something else? _Target system_ is an important distinction here — this refers to the Pi board where this SD card will ultimately be used, if it’s different from the one where you’re currently installing.

- Will you be connecting **OLED** (128x128), **TFT** (128x128) or **IPS** (240x240)&nbsp;displays? Can’t mix and match; must be one or the other. (There’s also an HDMI option — see the “[Using Just the Software](../../../../animated-snake-eyes-bonnet-for-raspberry-pi/using-just-the-software)” page for guidance.)

These are the screen types:

Select **TFT** if you have Product #2088

&nbsp;

The 1.44" 128x128 plain TFT

![pi_a___b___2__3_2088-01.jpg](https://cdn-learn.adafruit.com/assets/assets/000/059/089/medium640/pi_a___b___2__3_2088-01.jpg?1534190892)

Select **IPS** if you have Product #3787

&nbsp;

The 1.54" 240x240 IPS TFT

![pi_a___b___2__3_3787-02.jpg](https://cdn-learn.adafruit.com/assets/assets/000/059/090/medium640/pi_a___b___2__3_3787-02.jpg?1534190954)

Select **OLED** if you have Product #1431

&nbsp;

The 1.5" 128x128 color OLED

![pi_a___b___2__3_1431-07.jpg](https://cdn-learn.adafruit.com/assets/assets/000/059/091/medium640/pi_a___b___2__3_1431-07.jpg?1534191030)

- The GPIO-halt utility performs an **orderly shutdown** using a momentary pushbutton between an unused GPIO pin and ground, no login required. If you don’t have a button and plan to shutdown the system the usual way, answer “ **n** ”.
- Will you be connecting **ANALOG** input devices like a **JOYSTICK** or **LIGHT SENSOR**? If so,&nbsp; **answer “y” when asked “Install ADC support?”**

There’s one final confirmation before installation, explaining the steps that will be taken and making it extra clear that the Pi will be _dedicated to this one task,_ it should not be installed on a “daily driver” computer that you use for real work.

Warning: 

The installer has to collect software packages from all over the world. Very infrequently, a server or connection might be unreachable. If this happens, or the script “hangs” mid-download, set the project aside for a couple hours and try again later.

# Dry Run

Reboot when prompted by the software installer. When the system restarts, after a minute or so, you should see some activity on the display(s).

_The eyes run automatically on every startup; it is a dedicated system.&nbsp;If you don’t want that, you’ll need to edit /etc/rc.local and remove or comment out the line&nbsp;that includes “python3 eyes.py”, typing the full command that appears there manually each time you want to start the code._

Danger: 

 **If everything seems to be working well, you can skip ahead to the next page and ignore the steps below.**

If the eyes are experiencing glitches (video snow, tearing, dropped frames or weird inverted colors), here’s what to do…

Log into the Pi remotely using ssh. Then type the following commands:

```auto
cd /boot/Pi_Eyes
sudo killall fbx2
```

The displays will stop updating. This is normal.

Then, if you have **OLED** displays, type the following:

```auto
sudo ./fbx2 -o -b 8000000
```

Or, for **TFT** displays, try:

```auto
sudo ./fbx2 -t -b 10000000
```

The first argument ( **-o** ,&nbsp; **-t** &nbsp;or **-i** ) sets the display type in use; OLED, TFT or IPS, respectively. Second argument ( **-b** ) sets the **maximum bitrate** for the displays. The higher the bitrate, the smoother the animation…_ **but** _…there’s a limit to how fast this can go, and it can vary with wire lengths, connections, environment (such as interference from other nearby devices) and even slight manufacturing variances from one display to the next.

For **OLED** displays, the default bitrate is **10000000** (10 MHz). For **TFT** displays, default is **12000000** (12 MHz). **IPS** uses **96000000** (96 MHz) by default. But if there’s trouble, we have to dial these back.

Try a lower value, like the 8 MHz or 10 MHz examples above. Watch the output for a minute…does it seem to have stabilized now? If only _one_ of the two displays glitches, you’ll still need to work the speed down until _both_ run reliably.

Press **Control+C** to kill the program and test again with&nbsp;a different bitrate…maybe work down 4 MHz at a time, then up 1 MHz at a time until you find the “sweet spot” between speed and reliability. Once you find it, Control+C again and let’s make the change permanent…

```auto
sudo nano /etc/rc.local
```

A couple lines from the bottom you’ll find this:

```auto
/boot/Pi_Eyes/fbx2 -o &
```

(or “-t” if using TFT displays)

Insert the additional **-b** and **bitrate value** before the **&** character:

```auto
/boot/Pi_Eyes/fbx2 -o -b 8000000 &
```

 **Save changes** and **exit** the editor. Then:

```auto
sudo reboot
```

After a minute or so the eyes should come up again, glitch-free this time. If not, repeat these steps again, trying a lower bitrate until you find a setting that works reliably.

Another way to reduce glitches is to **solder ribbon cables _directly_ between the bonnet and displays, with no headers or plugs in-between;** every intermediary part is an opportunity for noise or connection problems.&nbsp;Consider this&nbsp;if you plan on permanent installation.

# Animated Snake Eyes Bonnet for Raspberry Pi

## Customizing the Hardware

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&nbsp; **5 Volts** ,&nbsp; **3.3 Volts** &nbsp;and&nbsp; **ground** , if you have a circuit that needs them. These are OK for&nbsp; **small loads** &nbsp;like ICs or a few LEDs, but&nbsp;_not_&nbsp;for big things like servos, which will need their own power source.

To the left are four&nbsp; **analog input pins** &nbsp;(along with four more 3.3V and ground points). You can use these to interface analog circuits such as a&nbsp; **joystick** &nbsp;to steer the eyes,&nbsp; **photocell** &nbsp;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).

![raspberry_pi_bonnet-analog-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/038/067/medium640/raspberry_pi_bonnet-analog-pins.png?1482114795)

Info: 

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

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

![raspberry_pi_bonnet-gpio-pins.png](https://cdn-learn.adafruit.com/assets/assets/000/038/068/medium640/raspberry_pi_bonnet-gpio-pins.png?1482114812)

# Analog Controls

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

 **XOUT** &nbsp;and&nbsp; **YOUT** &nbsp;from a joystick can connect to analog pins&nbsp; **A0** &nbsp;and&nbsp; **A1**.

**The eyes move autonomously by default** &nbsp;— 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&nbsp;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.

![raspberry_pi_analog-joystick.png](https://cdn-learn.adafruit.com/assets/assets/000/038/110/medium640/raspberry_pi_analog-joystick.png?1482355393)

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&nbsp; **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.

![raspberry_pi_iris-photocell.png](https://cdn-learn.adafruit.com/assets/assets/000/038/113/medium640/raspberry_pi_iris-photocell.png?1482355447)

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

![raspberry_pi_iris-pot.png](https://cdn-learn.adafruit.com/assets/assets/000/038/112/medium640/raspberry_pi_iris-pot.png?1482355427)

# Buttons

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&nbsp; **GND** , and the opposite leg to a digital pin:

- GPIO&nbsp; **Pin 22** &nbsp;is the&nbsp; **left** &nbsp;eye wink.
- GPIO **Pin 23** &nbsp;blinks&nbsp; **both** &nbsp;eyes.
- GPIO **Pin 24** &nbsp;winks the&nbsp; **right** &nbsp;eye.

If using our analog joystick breakout board, that stick includes&nbsp;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).

![raspberry_pi_blink-gpio.png](https://cdn-learn.adafruit.com/assets/assets/000/038/111/medium640/raspberry_pi_blink-gpio.png?1482355410)

# 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/eyes.py**. 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/eyes.py”).

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:

```auto
# 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.

# Animated Snake Eyes Bonnet for Raspberry Pi

## Customizing the Look

# Changing the Python Code

The installer script places the code and data in the directory **/opt/Pi\_Eyes**.&nbsp;

If using TFT or OLED screens on a Snake Eyes Bonnet board, the Python script of interest is **eyes.py**. If using HDMI output (with or without the bonnet), look for **cyclops.py** &nbsp;(so named because it only renders&nbsp;one eye).

After making changes to the code, rather than tracking down and killing processes, it’s often easier just to reboot the Pi. After a minute or so, the&nbsp;revised code will run on startup.

This section near the top of the code&nbsp;(previously mentioned on the Hardware page) includes a couple of&nbsp;items&nbsp;that are relevant to the appearance of the eyes:

```auto
# 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
```

Most relevant here are AUTOBLINK and TRACKING. If **AUTOBLINK** is changed&nbsp;to **False** , the eyes will stop their automatic blinking (responding only to button presses, if you have something like that wired up). If **TRACKING** is changed to **False** , the eyelids will no longer follow the pupils as they move around (this is an interesting thing that real eyes actually do, but sometimes you want a continuous wide-eyed stare).

Sometimes you may want no eyelids at all…just a full unblinking hemisphere. You can achieve this by simply commenting out the two lines that render the eyelids (put a “#” character at the start of each line). This is much later in the code, near&nbsp;line 430:

```auto
        upperEyelid.draw()
        lowerEyelid.draw()
```

The other settings above are mostly related to hardware stuff.

# Changing Graphics

Certain aspects (such as iris&nbsp;color) can be changed by substituting different graphics files. These are in the directory **/opt/Pi\_Eyes/graphics**. One&nbsp;could just overwrite the files that are there, but I prefer to keep the originals around for reference and assign new names to the changed files. To make the code load these changed files, look for this section&nbsp;starting around line 122:

```auto
# Load texture maps --------------------------------------------------------

irisMap   = pi3d.Texture("graphics/iris.jpg"  , mipmap=False,
              filter=pi3d.GL_LINEAR)
scleraMap = pi3d.Texture("graphics/sclera.png", mipmap=False,
              filter=pi3d.GL_LINEAR, blend=True)
```

Most common graphics formats (JPG, GIF, PNG — the latter with or without transparency) are supported. The images are square to make the OpenGL library happy.

The graphics are stored flat and unrolled, like a map projection. The horizontal (X) axis works like&nbsp;the longitude, or angle around the eye, while the vertical (Y) axis is the latitude.

![raspberry_pi_mapping.jpg](https://cdn-learn.adafruit.com/assets/assets/000/046/706/medium640/raspberry_pi_mapping.jpg?1506027462)

The **iris** (file iris.jpg) is what we think of as the “color” of the eye and is most often what you’ll want to edit. Sometimes you just need to edit the hue & saturation in a program like Photoshop, or you can make something totally custom if you’re after a particular look.

![raspberry_pi_iris.jpg](https://cdn-learn.adafruit.com/assets/assets/000/046/707/medium640/raspberry_pi_iris.jpg?1506027835)

The **sclera** (file sclera.png) is the “white” of the eye…which really isn’t that white at all. There’s veins and blotches and gross stuff!

This file&nbsp;is a **transparent** PNG to simulate the transition where the sclera meets the lens…it’s not an abrupt transition, there’s a slight “fuzziness” to it. When editing, try to preserve that transparency (and note the couple of transparent rows at the bottom, necessary because of the way OpenGL interpolates these images).

![raspberry_pi_sclera.jpg](https://cdn-learn.adafruit.com/assets/assets/000/046/708/medium640/raspberry_pi_sclera.jpg?1506027965)

(The third file, lidMap, probably shouldn’t be changed. It’s complicated.)

Around line 79 in the code is this:

```auto
# Load SVG file, extract paths & convert to point lists --------------------

dom               = parse("graphics/eye.svg")
```

 **eye.svg** &nbsp;(or **cyclops-eye.svg** for the single-eye code) is a Scalable Vector Graphics (SVG) file that determines the size and shape of various elements. Suppose you want Krampus eyes, with that freaky horizontal goat pupil? Or dragon eyes with a vertical slit pupil? (In fact there’s an example file there for that — dragon-eye.svg.)

InkScape and Adobe Illustrator (among others) can both load and save SVG files. **But** …editing / substituting this file is fairly tricky, as the **_names_** of individual paths are used in the Python code. If your graphics editor of choice does not maintain these element names _exactly_ when changing or saving the file, the Python code will fail to run.

In Illustrator, you can see the path names by toggling “Layer 1”&nbsp;open:

![](https://cdn-learn.adafruit.com/assets/assets/000/038/114/medium800/raspberry_pi_EyePaths.png?1482692898)

The largest blue circle there, which extends to the edges of the document, can mostly be ignored…it’s there for reference and represents the outer bounds of the eye ball (which can’t be changed).

The **iris** path (which needs to remain a circle, though you can change its size) determines the size of the outer edge of the iris relative to the whole eye.

**pupilMin** and **pupilMax** are the size and shape of the pupil in its most contracted and most dilated positions, as it responds to light. This doesn’t need to be a circle! Have a look at dragon-eye.svg for example.

Two additional&nbsp;blue circles — **scleraFront** and **scleraBack** — are used in determining the “sweep” of the white of the eye. Notice it overlaps the outer edge of the iris slightly, and is open at the back (we have no need for the back of the eye, so it’s not modeled or rendered).

**Red** paths are used for animating the eyelids. **upperLidOpen** and **upperLidClosed** are the shape of the upper eyelid in its fully-open and fully-closed positions. **lowerLidOpen** and **lowerLidClosed** are the same for the lower eyelid.&nbsp; **upperLidEdge** and **lowerLidEdge** are used by the software to generate the other edge&nbsp;of the eyelid mesh geometry, which is really a 2D polygon that occludes the eye behind it.

You’ll notice the default eye is **not symmetrical**. Eyes are interesting things and have a unique shape left and right! Looking at the SVG graphics, the other eye (and nose, if we had one) would be to the left. cyclops-eye.svg _is_ left/right symmetrical…it’s designed for the Pi’s single HDMI output, which might be split to two identical displays…the asymmetrical eye would look weird and lopsided in that case, so we go for the naïve “football shape.”

(At some point I hope to add a translucent _nictitating&nbsp;membrane_ to the dragon eye, but this hasn’t happened yet.)

# Replacing Everything

Well, almost everything.

Our Python code generates OpenGL animation&nbsp;that goes&nbsp;to the Pi’s normal HDMI video framebuffer, whether or not there’s actually an HDMI display attached. A separate program — **fbx2** — continuously copies two sections of the framebuffer to the TFT or OLED displays attached to the Snake Eyes Bonnet.

This means, if you really want, the _entire eye-animating program_&nbsp;could be replaced with code&nbsp;of your own design in whatever language you like. As long as&nbsp;your code positions graphics in the right places, fbx2 will present that on the TFT/OLED screens. (I’ve even tried installing&nbsp;fbx2 over RetroPie — yes, you can play Doom on these eyes!)

The pi-eyes.sh installer script configures the Pi’s video output resolution to either 640x480 pixels (for OLED or TFT) or 1280x720 pixels (for IPS). It could be nearly any resolution, but these sizes were chosen for a reason, explained in a moment…

Picture the screen split evenly; two rectangular regions side-by-side. The eyes will be centered within these regions, regardless their size or aspect ratio. The _size_ of the rendered eyes is specified on the command line to the Python code using the --radius option, for example:

```auto
python eyes.py --radius 128
```

The _fbx2_ program performs repeated screen captures, scaling it by 50% (providing a smooth 2:1 downsampling in the process) and then copying two squares centered on these regions to the connected SPI screens. For OLED or TFT, the screens are 128x128 pixels, so the sections of the screen copied are 256x256 pixels, and the eyes have a radius of 128 pixels. IPS screens are 240x240 pixels, so the copied sections are 480x480 pixels and the eyes have a radius of 240 pixels.

![pi_a___b___2__3_eye-diagram-640-480.png](https://cdn-learn.adafruit.com/assets/assets/000/053/165/medium640/pi_a___b___2__3_eye-diagram-640-480.png?1524540506)

![pi_a___b___2__3_eye-diagram-1280x720.png](https://cdn-learn.adafruit.com/assets/assets/000/053/212/medium640/pi_a___b___2__3_eye-diagram-1280x720.png?1524587874)

There’s a lot of unused blank space around the eyes; this is normal and by design. If developing your own code, this allows you to put debugging or status information in the margins of the HDMI display, but not have it copied to the SPI screens. Also, the eyelids are rendered by dynamically generating 2D meshes, and these need to be a little larger than the eyes to fully block things out. If the eyes were right up against each other, these would overlap.

# Animated Snake Eyes Bonnet for Raspberry Pi

## Using Just the Software

The pair of TFT displays or OLEDs are great for life-size props or costumes. If you’re looking for something _larger than life,_ you can use the Raspberry Pi’s video output to feed an **HDMI** monitor, video projector…or we’ve been having fun with the _Gakken WorldEye,_ a 10 inch hemispherical display from Japan…

![](https://cdn-learn.adafruit.com/assets/assets/000/046/702/medium800/raspberry_pi_WorldEyeOnDesk.jpg?1506011983)

Using HDMI video out **doesn’t require the Bonnet board** , unless you want **analog inputs** for a joystick control or a light sensor.

Follow the steps on the “[**Software Installation**](../../../../animated-snake-eyes-bonnet-for-raspberry-pi/software-installation)” page — start with Legacy Raspbian Lite for a Pi 2 or 3, do some first-time configuration and get the system on your network. For Pi 4, start with 32-bit Legacy Raspberry Pi Desktop.

Download and run the **pi-eyes.sh** installer script as explained there.

- When prompted for a screen type, select **HDMI**.
- Install GPIO-halt if you want a single-button shutdown option. This requires wiring up a&nbsp;button&nbsp;between one of the GPIO header pins and ground.
- Install ADC support _only_ if you have the Snake Eyes Bonnet and want analog inputs for a joystick or light sensor.
- Install USB Ethernet gadget support _only_ if using a Raspberry Pi Zero (or Zero W) and want a direct USB connection from your main computer. [It’s explained a bit in this guide](../../../../turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget).

After rebooting (about 30 seconds to one minute), you’ll be greeted with a **single large eye** centered on the screen.

Use an **HDMI splitter** to feed the same&nbsp;image to multiple screens…

![](https://cdn-learn.adafruit.com/assets/assets/000/046/705/medium800/raspberry_pi_two-eyes-on-desk.jpg?1506018444)

In order to work with the WorldEye display (or other HDMI devices), the code and graphics for this version are slightly different. The TFT/OLED code (eyes.py), designed for&nbsp;two separate&nbsp;physically-wired screens, provides a **distinct shape** for the&nbsp;left and right eyes to approximate&nbsp;the&nbsp;_caruncle_ (the inner corner of the eyes). The HDMI code (cyclops.py) generates a single **symmetrical** eye (no carnucle), so it can be fed to an HDMI splitter and not look lopsided on two screens.

![](https://cdn-learn.adafruit.com/assets/assets/000/046/704/medium800/raspberry_pi_HDMI-Eye-Diagram.png?1506015982)

If using something _other_ than a WorldEye display, and if the eye image looks oddly stretched and not round, this probably has to do with the screen **aspect ratio**. We can adjust the Pi’s video output resolution to match your display’s native HDMI resolution:

```auto
sudo nano /boot/config.txt
```

(Or substitute your editor of choice for “nano”)

Look for this line near the end of the file:

```auto
hdmi_cvt=640 480 60 1 0 0 0
```

Change the first two numbers — 640 and 480 — to the desired&nbsp;resolution. Save the changes and then **reboot**.

# Animated Snake Eyes Bonnet for Raspberry Pi

## Downloads

# Files

- [EagleCAD PCB files on GitHub](https://github.com/adafruit/Adafruit-Animated-Eyes-Bonnet-PCB)
- [Fritzing object in Adafruit Fritzing library](https://github.com/adafruit/Fritzing-Library)

# Schematic
![](https://cdn-learn.adafruit.com/assets/assets/000/038/349/medium800/raspberry_pi_schem.png?1484174067)

# Fab Print

Dims. in mm

![](https://cdn-learn.adafruit.com/assets/assets/000/038/350/medium800/raspberry_pi_fabprint.png?1484174086)


## Featured Products

### Adafruit Animated Eyes Bonnet for Raspberry Pi Mini Kit

[Adafruit Animated Eyes Bonnet for Raspberry Pi Mini Kit](https://www.adafruit.com/product/3356)
The&nbsp; **Snake Eyes Bonnet** &nbsp;is a&nbsp; **Raspberry Pi accessory** &nbsp;for driving&nbsp; **two 128x128 pixel OLED** &nbsp;or&nbsp; **TFT LCD** &nbsp;displays&nbsp;and also provides four&nbsp; **analog inputs** &nbsp;for sensors....

In Stock
[Buy Now](https://www.adafruit.com/product/3356)
[Related Guides to the Product](https://learn.adafruit.com/products/3356/guides)
### Adafruit 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD

[Adafruit 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD](https://www.adafruit.com/product/3787)
We've been looking for a display like this for a long time - it's only 1.5" diagonal but has a high density 220 ppi, 240x240 pixel display with full-angle viewing. It _looks_ a lot like our 1.44" 128x128 display, but has 4x as many pixels and looks great at any angle....

In Stock
[Buy Now](https://www.adafruit.com/product/3787)
[Related Guides to the Product](https://learn.adafruit.com/products/3787/guides)
### OLED Breakout Board - 16-bit Color 1.5" w/microSD holder

[OLED Breakout Board - 16-bit Color 1.5" w/microSD holder](https://www.adafruit.com/product/1431)
We love our black and white monochrome displays but we also like to dabble with some color now and then. Our big 1.5" color OLED displays are perfect when you need a small display with vivid, high-contrast 16-bit color. The visible portion of the OLED measures 1.5" diagonal and...

Out of Stock
[Buy Now](https://www.adafruit.com/product/1431)
[Related Guides to the Product](https://learn.adafruit.com/products/1431/guides)
### Adafruit 1.44" Color TFT LCD Display with MicroSD Card breakout

[Adafruit 1.44" Color TFT LCD Display with MicroSD Card breakout](https://www.adafruit.com/product/2088)
This lovely little display breakout is the best way to add a small, colorful and bright display to any project. Since the display uses 4-wire SPI to communicate and has its own pixel-addressable frame buffer, it can be used with every kind of microcontroller. Even a very small one with low...

In Stock
[Buy Now](https://www.adafruit.com/product/2088)
[Related Guides to the Product](https://learn.adafruit.com/products/2088/guides)
### Raspberry Pi 3 - Model B - ARMv8 with 1G RAM

[Raspberry Pi 3 - Model B - ARMv8 with 1G RAM](https://www.adafruit.com/product/3055)
Did you really think the Raspberry Pi would stop getting better? At this point, we sound like a broken record, extolling on the new Pi’s myriad improvements like we’re surprised that the folks at the Raspberry Pi Foundation are continuously making their flagship board better.&nbsp;...

In Stock
[Buy Now](https://www.adafruit.com/product/3055)
[Related Guides to the Product](https://learn.adafruit.com/products/3055/guides)
### Raspberry Pi Zero WH (Zero W with Headers)

[Raspberry Pi Zero WH (Zero W with Headers)](https://www.adafruit.com/product/3708)
If you didn't think that the Raspberry Pi Zero W could possibly get any better, then boy do we have a pleasant surprise for you!&nbsp;The new **Raspberry Pi Zero WH&nbsp;** offers all the benefits of the Pi Zero W, but with one big difference – a **pre-soldered GPIO...**

Out of Stock
[Buy Now](https://www.adafruit.com/product/3708)
[Related Guides to the Product](https://learn.adafruit.com/products/3708/guides)
### Photo cell (CdS photoresistor)

[Photo cell (CdS photoresistor)](https://www.adafruit.com/product/161)
CdS cells are little light sensors. As the squiggly face is exposed to more light, the resistance goes down. When it's light, the resistance is about ~1KΩ, when dark it goes up to ~10KΩ.

To use, connect one side of the photocell (either one, it's symmetric) to power...

In Stock
[Buy Now](https://www.adafruit.com/product/161)
[Related Guides to the Product](https://learn.adafruit.com/products/161/guides)
### Analog 2-axis Thumb Joystick with Select Button + Breakout Board

[Analog 2-axis Thumb Joystick with Select Button + Breakout Board](https://www.adafruit.com/product/512)
This mini-kit makes it easy to mount a PSP/Xbox-like thumb joystick to your project. The thumbstick is an analog joystick - more accurate and sensitive than just 'directional' joysticks - with a 'press in to select' button. Since it's analog, you'll need two analog...

In Stock
[Buy Now](https://www.adafruit.com/product/512)
[Related Guides to the Product](https://learn.adafruit.com/products/512/guides)

## Related Guides

- [Adafruit 1.44" Color TFT with Micro SD Socket](https://learn.adafruit.com/adafruit-1-44-color-tft-with-micro-sd-socket.md)
- [CircuitPython Display Support Using displayio](https://learn.adafruit.com/circuitpython-display-support-using-displayio.md)
- [Adafruit Arcade Bonnet for Raspberry Pi](https://learn.adafruit.com/adafruit-arcade-bonnet-for-raspberry-pi.md)
- [Adafruit EYESPI Pi Beret](https://learn.adafruit.com/eyespi-pi-beret.md)
- [JOY Controller for Adafruit Feather](https://learn.adafruit.com/joy-controller-feather.md)
- [Unicorn Hat with Moving Ears](https://learn.adafruit.com/unicorn-hat-with-moving-ears.md)
- [Adafruit 1.3" and 1.54" 240x240 Wide Angle TFT LCD Displays](https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays.md)
- [Electronic Animated Eyes for ARM Microcontrollers](https://learn.adafruit.com/animated-electronic-eyes.md)
- [Cupcade: the Raspberry Pi Micro Arcade Cabinet](https://learn.adafruit.com/cupcade-raspberry-pi-micro-mini-arcade-game-cabinet.md)
- [Kitty Toe Bean Keypad with Color TFT](https://learn.adafruit.com/kitty-toe-bean-paw-keypad-color-tct.md)
- [Adafruit 1.27" and 1.5" Color OLED Breakout Board](https://learn.adafruit.com/adafruit-1-5-color-oled-breakout-board.md)
- [Animated Scrolling "Mario Clouds" TFT Jewelry](https://learn.adafruit.com/scrolling-mario-clouds-tft-jewelry.md)
- [Hallowing Minotaur Maze](https://learn.adafruit.com/hallowing-minotaur-maze.md)
- [Purple People Eater](https://learn.adafruit.com/purple-people-eater.md)
- [Pro Trinket as a USB HID Mouse](https://learn.adafruit.com/pro-trinket-usb-hid-mouse.md)
- [1.8" TFT Display Breakout and Shield](https://learn.adafruit.com/1-8-tft-display.md)
