A dynamic, scene-based clock for the Pimoroni Interstate 75W LED matrix display
Transform your Interstate 75W into a living canvas that combines beautiful pixel art with time display. Whether you're nostalgic for 8-bit classics, love cyberpunk aesthetics, or want cozy winter scenes, this clock brings your LED matrix to life with smooth scrolling backgrounds, animated vector graphics, and a fully customizable scene system.
Classic ZX Spectrum game scenes with smooth scrolling
Vibrant pixel art landscapes that slowly scroll across the display
- 🎬 Multiple Scene Types: Static images, scrolling backgrounds, animated vector graphics, and more
- 🌓 Day/Night Modes: Automatic brightness control with dimmed night variants
- ⏰ Smart Scheduling: Configure when your display is on, in normal mode, or night mode
- 🎮 Built-in Scenes: Retro gaming scenes, cyberpunk landscapes, 3D cubes, Tetris, and Asteroids
- 🎨 Easy Customization: Add your own pixel art with simple configuration
- 💾 Memory Efficient: Designed for MicroPython's limited resources
- 📅 Flexible Date/Time: Customizable date and time formats with 12/24-hour support
Rotating 3D wireframe cubes with color-cycling animation. Perfect for a hypnotic, geometric display.
("CubeScene", (), {"num_cubes": 3})Watch Tetris pieces fall, rotate, and stack up automatically. Features all 7 classic Tetris shapes with random movements and automatic grid resets.
("TetrisScene", (), {"fall_speed": 0.1, "reset_interval": 60.0})Experience the classic Asteroids arcade game with an automated ship that thrusts, rotates, and fires lasers. Asteroids split into smaller pieces when destroyed, creating dynamic retro gameplay.
("AsteroidsScene", (), {"num_asteroids": 5})Features:
- Vector-based wireframe graphics (ship, asteroids, lasers)
- Automated ship with 70% thrust frequency and 50% rotation frequency
- Asteroids split on destruction: Large → Medium → Small
- Fast-moving laser projectiles with collision detection
- Screen-wrapping physics for authentic arcade feel
- Perfect for night mode with cyan ship, gray asteroids, and yellow lasers
Perfect for wide pixel art landscapes. Your image scrolls continuously across the display.
("ScrollingImageScene", ("images/scene_neon_city.png",), {"scroll_speed": 1})Display your favorite pixel art without animation, great for detailed scenes you want to appreciate.
("StaticImageScene", ("images/spectrum_dizzy.png",), {})The project includes several gorgeous pixel art scenes:
- 🎮 Retro Gaming: Classic ZX Spectrum game scenes (Dizzy, Jetpac, Jet Set Willy, Sabrewulf)
- 🌃 Cyberpunk: Neon city and purple sunset landscapes
- 🚀 Sci-Fi: Future family scenes with vibrant colors
- 🎄 Seasonal: Christmas-themed scenes (snow animals, winter bridge, cozy fireplace)
Each image includes a night variant that automatically activates in night mode!
- Pimoroni Interstate 75W board
- 2× HUB75 LED panels (128×64 pixels each, arranged horizontally)
- Total display resolution: 256×64 pixels
- WiFi connection (for automatic time synchronization via NTP)
- MicroPython firmware installed on the Interstate 75W
Follow Pimoroni's guide to install MicroPython on your Interstate 75W: https://learn.pimoroni.com/article/getting-started-with-interstate-75
Create a secrets.py file in the src/ directory:
# src/secrets.py
WIFI_SSID = "YourNetworkName"
WIFI_PASSWORD = "YourPassword"
⚠️ Note:secrets.pyis gitignored by default to protect your credentials.
Copy all files from the src/ directory to the root of your Interstate 75W:
Using Thonny IDE:
- Open Thonny and connect to your Interstate 75W
- Navigate to the
src/directory - Select all files and "Upload to /"
Using mpremote:
mpremote connect /dev/ttyACM0 cp -r src/* :Using rshell:
rshell -p /dev/ttyACM0
> cp -r src/* /pyboard/Press the reset button on your Interstate 75W or power cycle it. The clock will:
- Connect to WiFi
- Sync time via NTP
- Start displaying scenes with date/time overlay
Create or find pixel art that fits the display:
- Format: PNG
- Dimensions: 256×64 pixels (exact)
- Style: High contrast works best on LED matrices
- Tip: Use 2× or 4× scale during creation, then resize to 256×64 for crisp pixels
For automatic night mode dimming, create a darker version:
# Using ImageMagick
convert my_scene.png -modulate 30 my_scene_night.png
# Or with slight desaturation for a warmer night look
convert my_scene.png -modulate 40,80,100 my_scene_night.pngPlace your images in src/images/:
src/images/
├── my_scene.png
├── my_scene_night.png (optional)
Edit src/config.py and add your scene to the SCENES list:
SCENES = [
# Scrolling scene (great for wide landscapes)
("ScrollingImageScene", ("images/my_scene.png",), {"scroll_speed": 1}),
# Static scene (for detailed artwork)
("StaticImageScene", ("images/my_scene.png",), {}),
# Day-only scene (9am-6pm)
("ScrollingImageScene", ("images/daytime_scene.png",), {}, "day"),
# Night-only scene (6pm-9pm)
("StaticImageScene", ("images/stars.png",), {}, "night"),
# ... other scenes
]Each scene is defined as a tuple with 4 elements:
- Scene Type (required):
"ScrollingImageScene","StaticImageScene","CubeScene","TetrisScene" - Arguments (required): Positional args like image path
- Keyword Arguments (required): Dictionary of options (can be empty
{}) - Time Preference (optional):
"day","night", orNone(both)
Examples:
# Basic scrolling scene
("ScrollingImageScene", ("images/city.png",), {})
# Faster scrolling
("ScrollingImageScene", ("images/city.png",), {"scroll_speed": 2})
# Static night-only scene
("StaticImageScene", ("images/stars.png",), {}, "night")
# Multiple cubes
("CubeScene", (), {"num_cubes": 5})
# Faster Tetris with quick reset
("TetrisScene", (), {"fall_speed": 0.05, "reset_interval": 30.0})Configure when your display is active in src/config.py:
MODE_SCHEDULE = {
9: "normal", # 9am: Full brightness, show "day" scenes
21: "night", # 9pm: Dimmed mode, show "night" scenes
23: "off" # 11pm: Display off
}Modes:
- normal: Full brightness, shows scenes marked "day" or None
- night: Dimmed colors (30% by default), shows scenes marked "night" or None
- off: Display turns off completely
Control how scenes transition:
SCENE_DURATION = 60 # Seconds per scene
SCENE_SELECTION = "sequential" # or "random"Customize how date and time are displayed:
TIME_FORMAT = "HH:MM" # 24-hour: "14:30"
# TIME_FORMAT = "hh:MM AP" # 12-hour: "02:30 PM"
# TIME_FORMAT = "HH:MM:SS" # With seconds: "14:30:45"
DATE_FORMAT = "DDD DD/MM/YYYY" # "Mon 15/01/2024"
# DATE_FORMAT = "DDDD, MMMM D, YYYY" # "Monday, January 15, 2024"
# DATE_FORMAT = "MM/DD/YYYY" # US format: "01/15/2024"Adjust the dimming factor for night mode:
NIGHT_MODE_DIM_FACTOR = 0.3 # 30% brightness (range: 0.0-1.0)Want to create your own animated scenes? It's easy!
Create a new file src/scenes/my_scene.py:
from .base import Scene
import config
class MyCustomScene(Scene):
def __init__(self, display, png_decoder, display_mode=None):
super().__init__(display, png_decoder)
self.display_mode = display_mode if display_mode is not None else "normal"
# Your initialization code here
self.x = 0
self.color = (255, 100, 0)
def update(self, delta_time):
"""Update animation state"""
self.x += 1
if self.x > self.width:
self.x = 0
def render(self):
"""Draw to the display"""
r, g, b = self.color
# Dim colors in night mode
if self.display_mode == "night":
r, g, b = config.dim_color(r, g, b)
pen = self.display.create_pen(r, g, b)
self.display.set_pen(pen)
self.display.circle(self.x, 32, 10)
def cleanup(self):
"""Clean up resources when scene ends"""
passAdd to src/scenes/__init__.py:
from .my_scene import MyCustomSceneIn src/config.py:
SCENES = [
("MyCustomScene", (), {}),
# ... other scenes
]pixelart-clock/
├── src/ # MicroPython code (deploy this to board)
│ ├── main.py # Entry point
│ ├── config.py # Configuration
│ ├── secrets.py # WiFi credentials (gitignored)
│ ├── scene_manager.py # Scene transitions
│ ├── hud.py # Time/date overlay
│ ├── time_utils.py # Time formatting utilities
│ ├── images/ # Your pixel art scenes
│ └── scenes/ # Scene modules
│ ├── base.py # Base Scene class
│ ├── scrolling_image.py
│ ├── static_image.py
│ ├── cube.py
│ └── tetris.py
├── docs/ # Documentation and photos
├── examples/ # Example code
├── CLAUDE.md # Developer documentation
└── README.md # This file
- Double-check
secrets.pycredentials - Ensure your network is 2.4GHz (5GHz not supported by Pico W)
- Check that your WiFi SSID and password don't have special characters
- Verify HUB75 panels are properly connected
- Check that power supply can handle both panels (5V, 2-4A recommended)
- Ensure panels are configured for 256×64 total resolution
- Confirm images are exactly 256×64 pixels
- Use PNG format (JPEG not supported)
- Reduce color count for better LED rendering
- Try increasing contrast for better visibility
- Check that the image path in
config.pymatches your file - Verify the scene tuple has all required elements
- Look for errors in Thonny's REPL console
Looking for more pixel art for your clock?
- Pixilart - Community pixel art gallery
- OpenGameArt - Free game assets
- Lospec - Pixel art gallery with color palette tools
- itch.io - Free pixel art assets
Tips for finding good pixel art:
- Search for "256x64 pixel art" or "pixel art landscape"
- Look for high contrast art (works better on LEDs)
- Retro game screenshots often work great
- Consider creating your own with tools like Aseprite or Piskel
The included pixel art scenes come from various talented artists:
- Snow Animals: Pixilart
- Winter Bridge: Pixilart
- Xmas Fireplace: Pixilart
- Retro Game Scenes: Screenshots from classic ZX Spectrum games
- Cyberpunk Landscapes: Various pixel art sources
This project is released under the GNU General Public License. See LICENSE for details.
Contributions are welcome! Feel free to:
- Add new scene types
- Create new pixel art scenes
- Improve documentation
- Report bugs or request features
Made with ❤️ for the Interstate 75W
Turn your LED matrix into art