This repository contains a high-performance Python port of the popular RoboEyes C++/Arduino animation library. It is engineered specifically to bring expressive, fluid, robotic eye animations to the Raspberry Pi and other Linux-based Single Board Computers (SBCs).
If you are building a companion robot, smart display, or interactive prop using a Raspberry Pi and an SPI TFT screen (like the ST7789), this library provides a plug-and-play solution for animated faces instead of relying on heavy GUI frameworks.
- 🤖 Familiar API: Uses the exact same object-oriented logic and state management (
DEFAULT,TIRED,ANGRY,HAPPY) as the original Arduino RoboEyes, making it incredibly easy to port robotic projects. - 🐍 Pure Python Translation: Eliminates the need for low-level C++ hardware libraries (like Adafruit_GFX/TFT_eSPI) natively binding to the Raspberry Pi GPIO.
- 🚀 Two Rendering Engines:
roboeyes_fast.py(Recommended): A high-performance iteration using NumPy arrays instead of PIL. This manipulates raw pixel memory directly, achieving a massive 10x performance boost for butter-smooth 60FPS animations and fluid eye interpolations on low-powered boards.roboeyes.py: The standard port utilizing Python PIL (Pillow) to draw to a frame buffer. Best for broader compatibility outside of numpy architectures.
graph TD
subgraph Traditional Approach ["The Problem (Slow / High Overhead)"]
A1["Python Logic: 'Move Eye'"] --> B1["Pillow/PIL Library"]
B1 --> C1["Construct Image Object"]
C1 --> D1["Serialize Pixel by Pixel"]
D1 --> E1["Hardware SPI Driver"]
E1 --> F1["TFT Screen"]
style D1 fill:#ffcccc,stroke:#cc0000,stroke-width:2px
end
subgraph Custom Engine ["The Solution (Fast / Direct)"]
A2["Python Logic: 'Move Eye'"] --> B2["DeltaTime / Lerp Math"]
B2 --> C2["NumPy Raw Array Manipulation"]
C2 --> D2["Direct Byte-Buffer Transfer"]
D2 --> E2["Hardware SPI Driver"]
E2 --> F2["TFT Screen"]
style C2 fill:#ccffcc,stroke:#009900,stroke-width:2px
style D2 fill:#ccffcc,stroke:#009900,stroke-width:2px
end
To use this library natively, you will need a typical SPI TFT display (like an ST7789 240x240 or 240x320) connected to the Raspberry Pi GPIO pins.
Here is the standard wiring configuration for an SPI screen:
| Raspberry Pi GPIO | TFT Display Pin | Description |
|---|---|---|
| Pin 1 / 17 (3.3V) | VCC | Board Power |
| Pin 6 (GND) | GND | Ground |
| Pin 23 (GPIO 11) | SCK / SCL | SPI Clock |
| Pin 19 (GPIO 10) | MOSI / SDA | SPI Data (Master Out) |
| Pin 21 (GPIO 9) | MISO | SPI Data (Master In) (Optional, screens usually only receive) |
| Pin 24 (CE0 / GPIO 8) | CS | Chip Select |
| Pin 22 (GPIO 25) | DC / RS | Data/Command |
| Pin 18 (GPIO 24) | RST / RES | Reset |
| Pin 1 / 17 (3.3V) | BLK / LED | Backlight Power |
(Note: Depending on your specific display hat/breakout, you may use different CE/CS pins, which can be defined in the software initialization).
You will need an ST7789 display (or similar) wired to your Raspberry Pi via SPI.
Ensure you have the following installed:
# Install Pillow for standard RoboEyes
pip3 install Pillow
# Install NumPy for FastRoboEyes (Recommended)
pip3 install numpy
# For Adafruit ST7789 displays
pip3 install adafruit-circuitpython-st7789To use the FastRoboEyes version with 60FPS smooth lerping interpolation:
import time
import board
import digitalio
from adafruit_st7789 import ST7789
from roboeyes_fast import FastRoboEyes, HAPPY, ANGRY, TIRED, DEFAULT
# Initialize your display (example ST7789 setup)
cs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D25)
reset = digitalio.DigitalInOut(board.D24)
spi = board.SPI()
display = ST7789(spi, cs=cs, dc=dc, rst=reset, baudrate=64000000, width=240, height=320)
# Initialize Fast RoboEyes
eyes = FastRoboEyes(display, width=320, height=240)
eyes.set_auto_blinker(True, interval=3)
# Main Loop
while True:
eyes.update() # Renders the frame automatically based on deltatime
# Change mood example:
# eyes.mood = HAPPYTo use the standard Pillow implementation:
from roboeyes import RoboEyes, DEFAULT
# ... initialize display ...
eyes = RoboEyes(display, width=240, height=320)
eyes.set_auto_blinker(True)
eyes.mood = DEFAULT
while True:
eyes.update()This project is licensed under the GNU General Public License v3.0 (GPLv3).
This is a ported derivative work. Proper attribution and immense thanks goes to:
- Dennis Hoelscher (FluxGarage) - Creator of the original Arduino RoboEyes version.
- Meurisse Dominique - Creator of the MicroPython translation.
If you use this library in an open-source robotic project, you must also open-source your code under GPLv3.