Grenzen verschoben: 30 FPS Video auf SSD1106 OLED mit Arduino Nano
Komponenten & Materialien
| Arduino Nano R3 | ×1 |
| 0,96″ OLED Display 128×64 (SSD1106, SPI) | ×1 |
Software & Tools
- Arduino IDE
- OpenCV (Python) – für Video-Capture & Vorverarbeitung auf PC
Projektbeschreibung
Ein Experiment an der Leistungsgrenze: Echtzeit-Video (30 FPS) auf einem monochromen 128×64 OLED (SSD1106) via Arduino Nano. Die Haupt-Herausforderung: Bandbreite. SPI wurde auf 2 MHz übertaktet, eine hochoptimierte Bibliothek genutzt. PC-seitig liest OpenCV Webcam-Bilder, skaliert, dithert (Floyd-Steinberg) auf 1-Bit, sendet per UART (1 Mbps) an Nano. Der Nano schiebt die Frames per SPI auf das Display.
Hardware-Verkabelung (SPI)
| OLED Pin | Arduino Nano Pin |
|---|---|
| VCC | 3,3V / 5V (je nach Modul) |
| GND | GND |
| SCL (SCK) | D13 (SCK) |
| SDA (MOSI) | D11 (MOSI) |
| RES (RST) | D9 |
| DC (A0) | D8 |
| CS | D10 (oder GND bei manchen Modulen) |
UART (PC → Nano): PC TX → Nano RX (D0), PC RX → Nano TX (D1), GND ↔ GND. Wichtig: Logic Level Shifter 5V↔3,3V für RX/TX wenn Nano 5V Logik nutzt!
Software-Architektur
PC-Seite (Python + OpenCV)
- Webcam-Capture (30 FPS)
- Resize auf 128×64
- Graustufen → Floyd-Steinberg Dithering → 1-Bit Bitmap (128×64 = 1024 Byte)
- Seriell (1 Mbps) an Nano senden
Nano-Seite (C++)
- Empfang per UART (1 Mbps = 125 kByte/s → 1024 Byte/Frame = 122 FPS theoretisch)
- SPI @ 2 MHz an SSD1106 (Standard 1–4 MHz, 2 MHz stabil)
- Optimierte Bibliothek (kein Adafruit_GFX Overhead) – direkter Register-Zugriff
- Double-Buffering vermeiden – Stream direkt in Display-RAM
Code-Repository
Vollständiger Code (Arduino + Python): GitHub: SaadOjo/SSD1106_monitor
Herausforderungen & Lösungen
| Problem | Lösung |
|---|---|
| SPI Bandbreite | Übertaktung auf 2 MHz, optimierte Lib (kein Overhead) |
| UART Bandbreite | 1 Mbps (Serial.begin(1000000)), rohe Bytes, kein Protokoll-Overhead |
| Nur 2 Farben (An/Aus) | Floyd-Steinberg Dithering → Illusion von Graustufen |
| RAM Limit (2 KB) | Kein Framebuffer – Stream direkt an Display |
| CPU Last | Minimaler Code im Loop, nur SPI-Transfer |
Dithering-Beispiel (Python)
import cv2
import numpy as np
def floyd_steinberg_dither(img):
# img: 128x64 uint8 (0-255)
h, w = img.shape
out = np.zeros((h, w), dtype=np.uint8)
for y in range(h):
for x in range(w):
old = img[y, x]
new = 255 if old > 127 else 0
out[y, x] = new
err = old - new
if x + 1 < w: img[y, x+1] += err * 7/16
if x-1>=0 and y+1
Ergebnis & Bewertung
- 30 FPS erreicht – flüssige Video-Wiedergabe erkennbar
- Dithering erzeugt überraschend gute Tiefenwahrnehmung
- Monochrom limitiert, aber für Silhouetten/Bewegung ausreichend
- Latenz: ~100ms (Capture→Display), dominiert durch Python-Verarbeitung
Verbesserungspotenzial
- ESP32 statt Nano: Dual-Core, 80 MHz, integriertes WLAN/BT, mehr RAM, schneller SPI → PC-frei möglich
- Hardware-Dithering (Display-Controller) – SSD1106 unterstützt nicht
- Komprimierung (RLE, Delta-Frames) für höhere Auflösung/FPS
- Direkter Kamera-Anschluss (OV2640/OV7670) an ESP32/STM32
Fazit
Ein beeindruckender "Proof of Concept", der zeigt, was mit 8-Bit-AVR & kleinen OLEDs möglich ist, wenn man Protokolle & Bibliotheken bis an die Hardware-Grenzen optimiert. Der Dithering-Trick macht monochrome Displays für Video nutzbar. Für echte Anwendungen: ESP32 + Kamera + LVGL/ebmp – aber der Lerneffekt hier ist maximal.
Herstellungsprozess
- Flüssigkristall-Display (LCD): Technologie, Fertigung und Zukunftsaussichten
- Methodenüberladung in C# meistern: Konzepte, Beispiele und Best Practices
- Neuer HDMI-APIX3 Konverter ermöglicht Automotive Video & ADAS Testing
- Primal Display: Raspberry Pi LCD-Temperaturmonitor mit DHT11 bauen
- Kuman 3,5″ TFT Display auf RetroPie installieren – Schritt-für-Schritt-Anleitung
- Verilog Tasks verstehen: Functions vs. Tasks, Syntax und Verwendung
- Klassisches Pong-Spiel auf Arduino UNO mit OLED-Display bauen – Schritt-für-Schritt-Tutorial
- Automatisierter Gaming-Assistent: Servo drückt Controller-Tasten (Arduino)
- ATmega328P Alien-Slot-Machine Kit – Selbstbau-Spielautomat
- Echtzeit-Zelluläre Automaten auf Arduino mit 128x64 OLED-Display