No description
  • C++ 93.1%
  • Makefile 6.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Lukas Anders d2e15f61a8 Bilder der Example-Demo als SVG ergänzen und im README einbinden
images/ enthält die 10 Einträge von DEMO[] aus examples/Eyes72x40
(01-05 normal, 06-10 übermüdet), pixelgenau aus Eyes.cpp mit der
U8g2-C-Bibliothek und dem 72x40-Treiber gerendert. Zusätzlich die
Roll-Varianten (roll_cw, roll_ccw, roll_converge) und das Blinzeln
(blink) als SMIL-Animation.

Das README zeigt die Bilder im Abschnitt "Beispiel".
2026-10-19 09:30:36 +02:00
examples Übermüdete Augen über Eyes::setTired() ergänzen 2026-06-02 12:47:09 +00:00
images Bilder der Example-Demo als SVG ergänzen und im README einbinden 2026-10-19 09:30:36 +02:00
src BROW_NEUTRAL zeichnete keine Brauen 2026-06-02 15:34:25 +02:00
.gitignore .gitignore: Vim-Swap- und Backup-Dateien ignorieren 2026-10-19 09:14:02 +02:00
library.properties Version 1.1.0 2026-06-02 15:34:25 +02:00
LICENSE Initial commit: Eyes-Library (animiertes Cartoon-Augenpaar für U8g2) 2024-11-07 18:20:11 +02:00
LICENSE.de Initial commit: Eyes-Library (animiertes Cartoon-Augenpaar für U8g2) 2024-11-07 18:20:11 +02:00
LIZENZEN.md Initial commit: Eyes-Library (animiertes Cartoon-Augenpaar für U8g2) 2024-11-07 18:20:11 +02:00
Makefile Initial commit: Eyes-Library (animiertes Cartoon-Augenpaar für U8g2) 2024-11-07 18:20:11 +02:00
README.md Bilder der Example-Demo als SVG ergänzen und im README einbinden 2026-10-19 09:30:36 +02:00

Eyes – animiertes Cartoon-Augenpaar für U8g2-Displays

Zeichnet ein Augenpaar (Augapfel, Pupille, Lid, Augenbrauen) über die U8g2-Basisklasse – funktioniert damit mit jedem U8g2-Treiber, egal ob 128x64-SSD1306, das 72x40-Fensterpanel (U8G2_SSD1306_72X40_ER_F_HW_I2C) oder ein anderes u8g2-unterstütztes Display.

#include <U8g2lib.h>
#include <Eyes.h>

U8G2_SSD1306_72X40_ER_F_HW_I2C display(U8G2_R2, U8X8_PIN_NONE, /*SCL=*/6, /*SDA=*/5);
Eyes eyes(display);

void setup() {
  eyes.begin(0x3C);       // I2C-Adresse setzen + display.begin()
  eyes.setBrow(BROW_RAISED);
  eyes.setGaze(GAZE_UP);
  eyes.update();          // erster Aufruf: zeichnet + startet Auto-Blinzeln
}

void loop() {
  eyes.update();          // nicht-blockierendes Auto-Blinzeln am Laufen halten
}

Status: 1.1.0, aus einem früheren Einzel-Sketch (72x40-OLED-Projekt) herausgelöst und als eigenständige Library verpackt.

Konzept

  • Zustand + Rendering getrennt: Setter (setGaze, setBrow, setLid) ändern nur Zustand, render() zeichnet ihn. So lassen sich mehrere Setter aufrufen, bevor tatsächlich gezeichnet wird.
  • Nicht-blockierendes Auto-Blinzeln: update() in loop() aufrufen – hält eine kleine State-Machine am Laufen, ohne delay() zu benutzen.
  • Blockierende Spezialanimationen: blink() (ein sofortiges Blinzeln) und roll(dir, turns) (Augen rollen) nutzen bewusst delay(). Während sie laufen, pausiert update() faktisch – danach wird der vorherige Ausdruck automatisch wiederhergestellt.
  • Geometrie frei konfigurierbar: alle Masse stecken in Eyes::geo (EyeGeometry), Defaults sind für ein 72x40-Panel ausgelegt.

API

enum Gaze { GAZE_CENTER, GAZE_LEFT, GAZE_RIGHT, GAZE_UP, GAZE_DOWN,
            GAZE_UP_LEFT, GAZE_UP_RIGHT, GAZE_DOWN_LEFT, GAZE_DOWN_RIGHT };
enum Brow { BROW_ANGRY, BROW_NEUTRAL, BROW_RAISED, BROW_SAD, BROW_NONE };
enum Roll { ROLL_CW, ROLL_CCW, ROLL_CONVERGE };

class Eyes {
public:
  explicit Eyes(U8G2& display);
  bool begin(uint8_t i2cAddr = 0);  // optional: I2C-Adresse (7 Bit) setzen + display.begin()

  void setGaze(Gaze g);
  void setGaze(int dx, int dy);     // freie Verschiebung in px (wird an eyeR/pupilR begrenzt)
  void setBrow(Brow b);
  void setLid(float l);             // 0.0 = offen ... 1.0 = ganz zu
  void setTired(bool t);            // übermüdet: Adern von der Pupille nach aussen
  void setRotation(const u8g2_cb_t* r);  // U8G2_R0 = normal, U8G2_R2 = 180°

  void render();                    // aktuellen Zustand zeichnen + anzeigen
  void blink();                     // EIN blockierendes Blinzeln
  void roll(Roll dir, int turns = 1);  // blockierendes Augenrollen

  void update();                    // nicht-blockierendes Auto-Blinzeln; in loop()

  EyeGeometry   geo;                // alle Masse, frei änderbar
  int           blinkSteps, blinkFrameMs;
  unsigned long blinkMinMs, blinkMaxMs;
  int           rollSteps, rollFrameMs;
};

EyeGeometry (Defaults für 72x40):

Feld Default Bedeutung
centerX 36 Bildmitte X
eyeR 13 Augapfel-Radius
eyeGap 23 Abstand Augenmitte <-> Bildmitte
eyeCY 25 Augenmitte Y
pupilR 5 Pupillen-Radius
gazeRange 5 max. Pupillen-Verschiebung je Achse (px)
browThick 3 Brauen-Balkendicke (px)
browTopY 2 höchster Brauen-Punkt (Y)
browSlant 5 Höhenunterschied innen/aussen (schräge Brauen)
browHalf 14 halbe Brauenlänge
veinCount 8 Anzahl Adern je Auge bei setTired(true)

Für ein anderes Panel (z.B. 128x64) einfach geo.* im Sketch nach dem Anlegen von Eyes eyes(display) überschreiben.

Beispiel

examples/Eyes72x40/ – Demo für ein ESP32-C3 SuperMini mit aufgelötetem 0,42"-OLED (72x40, SSD1306/SSD1315). Wechselt alle 3 s den Ausdruck und zeigt nach jedem Durchlauf alle drei Roll-Varianten.

Ausdrücke (DEMO[])

Pixelgenau aus src/Eyes.cpp auf 72x40 gerendert (Ordner images/).

böse, geradeaus böse, links unten Brauen hoch, oben neutral, rechts traurig, unten
böse, geradeaus böse, links unten Brauen hoch, oben neutral, rechts traurig, unten

Dieselben Ausdrücke mit setTired(true):

böse, geradeaus böse, links unten Brauen hoch, oben neutral, rechts traurig, unten
böse, geradeaus, übermüdet böse, links unten, übermüdet Brauen hoch, oben, übermüdet neutral, rechts, übermüdet traurig, unten, übermüdet

Animationen

Rollen im Uhrzeigersinn Rollen dagegen Rollen gespiegelt Blinzeln
Rollen im Uhrzeigersinn Rollen gegen den Uhrzeigersinn Rollen gespiegelt Blinzeln

Die Animationen sind SMIL-SVGs und laufen im Browser bzw. auf Gitea/Codeberg.

Build

make example                        # Kompiliert examples/Eyes72x40
make upload PORT=/dev/ttyACM0
make monitor
make upload-monitor

Default-Board ist esp32:esp32:esp32c3 (ESP32-C3 SuperMini) – für ein anderes Board BOARD= setzen, z.B. make example BOARD=esp32:esp32:esp32.

Installation als Arduino-Library

ln -s /pfad/zu/esp32-libEyes ~/Arduino/libraries/Eyes

arduino-cli findet die Library erst, wenn der Sketch #include <Eyes.h> direkt einbindet.

Abhängigkeiten

  • ESP32 Arduino Core (Wire.h, Arduino.h)
  • U8g2 (Library Manager: "U8g2" von oliver) – liefert die Treiberklassen, u.a. U8G2_SSD1306_72X40_ER_F_HW_I2C für das 72x40-Fensterpanel.
arduino-cli lib install "U8g2"

Stolperfallen

  • 72x40-Panel braucht den dedizierten Treiber: Das Panel ist nur ein sichtbares Fenster im 128x64-GDDRAM des Controllers. Ein generischer 128x64-Treiber zeichnet daher falsch – U8G2_SSD1306_72X40_ER_F_HW_I2C kennt den Offset.
  • I2C-Pins prüfen: beim ESP32-C3-SuperMini mit aufgelötetem OLED SDA=GPIO5/SCL=GPIO6 – NICHT die sonst übliche 8/9-Belegung des nackten SuperMini.
  • Verschobenes/abgeschnittenes Bild: abweichende Panel-Charge möglich – dann u8g2.getU8x8()->x_offset = 30; vor eyes.begin() bzw. u8g2.begin() setzen.
  • blink()/roll() sind blockierend (delay()) – während der Laufzeit reagiert der Sketch nicht auf andere Eingaben. Für reaktionsfreudige Sketches sparsam einsetzen bzw. in eigenem Task/Core auslagern.
  • Pupille kann den Augapfel nicht verlassen: setGaze(dx, dy) begrenzt automatisch auf eyeR - pupilR - 1.

Dateien

src/Eyes.h                        Klasse Eyes, Enums (Gaze/Brow/Roll), EyeGeometry
src/Eyes.cpp                      Implementierung (Zeichnen, Blinzeln, Rollen)
examples/Eyes72x40/               Demo für ein 72x40-OLED-Board
images/                           gerenderte Vorschau der Demo-Ausdrücke und Animationen (SVG)

Lizenz

Der Bibliotheks-Quelltext unter src/ steht unter der GNU Lesser General Public License v3 (oder später) – siehe LICENSE bzw. LICENSE.de (inoffizielle deutsche Übersetzung).

Die Beispiel-Sketches unter examples/ stehen unter der GNU General Public License v3 (oder später) – siehe examples/LICENSE bzw. examples/LICENSE.de.

Abhängigkeiten und deren Lizenzen: siehe LIZENZEN.md.