No description
  • C 64.1%
  • C++ 35.4%
  • Python 0.5%
Find a file
rene 04cb81d3c8 ePaper-Tarnbild bei Daueraufnahme: Behaglichkeitsfeld aus dem SHTC3
Temperatur gegen relative Feuchte im Behaglichkeitsfeld nach Frank
(Leusden/Freymark), Eckpunkte aus Dentel/Dietrich, HCU 2005, Abb. 7
ausgemessen. Punkt mit Spur der letzten Stunde, Urteil (behaglich / noch
behaglich / zu kalt / zu warm / zu feucht / zu trocken) und Taupunkt.
Teilbild einmal je Minute, eigene Task auf Kern 0 wie die Kugel am LCD-Board.

Eigenerwaermung: Der Sensor misst die Platine, waehrend einer Aufnahme bis
6,5 K ueber dem Raum. climateRoom() zieht sie ab, gemessen am 27.09.2026
(Raum konstant 21,7 C, 65 Werte ueber 32 min):
  dT(t) = 6,46 - 1,71 e^(-t/65 s) - 3,20 e^(-t/666 s)
Die Feuchte wird ueber den Taupunkt auf die Raumtemperatur umgerechnet.

Stand: Anzeige und Urteil am Geraet gesehen (Foto), kein hoerbares Knacken
in der Aufnahme. Die Korrektur ist nur an der eigenen Messreihe angepasst,
eine Gegenprobe steht aus. VORLAEUFIG drin: die Messreihe nach /klima.csv
(Portal /klima.csv) -- wird nach der Gegenprobe entfernt.
2026-09-27 21:16:10 +02:00
bringup-lcd154 Zwei Geraete: Doku aufgeteilt und das ePaper-Geraet in Betrieb genommen 2026-09-25 19:28:44 +02:00
case V1.0 Ausgangsstand Pala Note v1.0 (Firmware + Gehäuse) von Paul Lagier importieren, README ergänzen 2026-09-04 10:45:56 +02:00
firmware 1.0 ePaper-Tarnbild bei Daueraufnahme: Behaglichkeitsfeld aus dem SHTC3 2026-09-27 21:16:10 +02:00
geraete Doku: Hardware stammt von Waveshare, nicht von Paul; Stand ePaper nachgezogen 2026-09-27 21:14:39 +02:00
tools Tag bestaetigen dunkelte das Display ab; dritte Taste belegen 2026-09-11 16:40:43 +02:00
.gitignore Ausgangsstand Pala Note v1.0 (Firmware + Gehäuse) von Paul Lagier importieren, README ergänzen 2026-09-04 10:45:56 +02:00
README.md Doku: Hardware stammt von Waveshare, nicht von Paul; Stand ePaper nachgezogen 2026-09-27 21:14:39 +02:00
START HERE.pdf Ausgangsstand Pala Note v1.0 (Firmware + Gehäuse) von Paul Lagier importieren, README ergänzen 2026-09-04 10:45:56 +02:00

Pala Note

Dokumentation und Weiterentwicklungs-Basis für Pala Note von Paul Lagier — ein ESP32-S3-basiertes Sprachnotiz-Gerät mit E-Paper-Display: Aufnahme auf SD-Karte, Transkription im eigenen Netz, Anzeige/Verwaltung der Notizen auf dem Gerät.

Die Firmware bedient zwei Geräte aus einem Quellbaum. Was nur eines davon betrifft — gemessene Hardware, Pins, Bedienung, Stromsparen — steht in geraete/; hier steht, was für beide gilt.

Herkunft & Lizenz

  • Design und Firmware v1.0 stammen von Paul Lagier (gekauftes Projekt).
  • Offizielle, stets aktuelle Bauanleitung: https://paullagier.craft.me/PP8UjYeYGviIqj
  • Lizenz laut Anbieter: nur für den persönlichen Gebrauch ("For personal use only"). Details dazu stehen im Abschnitt „Safety & License“ der Online-Anleitung — vor jeder Weitergabe oder Veröffentlichung dort nachlesen.
  • Dieses Repo liegt privat auf eigener Infrastruktur (Forgejo hinter VPN) und dient der eigenen Dokumentation, Reparatur und Weiterentwicklung — keine Weitergabe der Originaldateien vorgesehen.

Die zwei Geräte

Seit 25.09.2026 liegen beide vor. Sie sind nicht austauschbar: gleicher SoC, gleiche Audio-Chips, gleiches SD-Interface — aber kein gemeinsamer Pin.

ePaper v1.0 Waveshare LCD-1.54
Rolle das vorgesehene Zielgerät Ersatz, um überhaupt entwickeln zu können
Profil pio run -e epaper pio run -e lcd154
SoC ESP32-S3-PICO-1 (LGA56) ESP32-S3 (QFN56)
Flash 8 MB eingebettet 16 MB
MAC 70:04:1d:d8:20:cc 28:84:85:91:c0:8c
Display E-Paper 200×200 ST7789 240×240
Taster zwei drei
Extras RTC, SHTC3, getrennte Abschaltpfade Beleuchtung, Lagesensor, Power-Latch

Beide melden sich als /dev/cu.usbmodem1101 — der Portname sagt nicht, welches Gerät hängt. Unterschieden werden sie an der MAC, auszulesen mit esptool flash-id. Das ist keine Kleinigkeit: ein mit dem falschen Profil geflashtes Gerät kann Schaden nehmen (das ePaper-Profil treibt GPIO 42 und 17 als Ausgang; auf dem LCD-Board sind das I²C-SDA und SD-D0).

Ordnerstruktur

README.md                 dieses Dach: beide Geräte, Bauen, gemeinsame Funktionen
geraete/epaper.md         Pala Note v1.0 — Messwerte, Eigenheiten, Stand
geraete/lcd154.md         Waveshare LCD-1.54 — dito
firmware 1.0/pala_note/   Arduino-Sketch (.ino) + Board-Support-Code (src/)
firmware 1.0/werks-backup/  Werks-Firmware des ePaper-Geräts (nicht im Git)
bringup-lcd154/           eigenständiges Messprojekt für das LCD-Board
case V1.0/                Pauls 3D-Druckdateien (.3mf) und Assembled.step --
                          am Geraet nicht verbaut, es steckt im Waveshare-Gehaeuse
START HERE.pdf            Anbieter-Einstiegsblatt mit Link zur Bauanleitung

secrets.h ist per .gitignore ausgeschlossen und wird nie committet. Vor dem ersten Bauen secrets.h.example nach secrets.h kopieren und ausfüllen.

Darin stehen nur noch die WLAN-Daten, und auch die bloß als Rückfall: Im Betrieb werden WLAN (Settings → wifi) und WireGuard (Settings → vpn) am Gerät eingerichtet und liegen im NVS. Der OpenAI-Schlüssel ist entfallen — die Transkription läuft im eigenen Netz.

Board-Profile

Umgeschaltet wird an einer Stelle, in firmware 1.0/pala_note/config.h:

#define PALA_BOARD  PALA_EPAPER   // oder PALA_LCD154

Die Pins und Fähigkeiten stehen in boards/board_epaper.h und boards/board_lcd154.h. Das ePaper-Profil ist Wert für Wert identisch mit dem Auslieferungsstand — nachgeprüft, indem der Präprozessor beide Stände expandiert und alle 48 Makros verglichen wurden.

Warnung: Ein mit dem falschen Profil geflashtes Gerät kann Schaden nehmen. Das ePaper-Profil treibt GPIO 42 und 17 als Ausgang; auf dem LCD-Board sind das I²C-SDA und SD-D0.

Bauen und Flashen

Die Firmware baut mit PlatformIO, ohne Arduino IDE — der Sketch-Ordner bleibt daneben unverändert als Arduino-Sketch nutzbar.

cd "firmware 1.0/pala_note"
pio run -e epaper                 # Pala Note v1.0 (E-Paper)
pio run -e lcd154 -t upload       # Waveshare-Board, bauen und flashen
pio device monitor -b 115200

Das Environment setzt PALA_BOARD, in config.h muss dafür nichts geändert werden.

Status

  • ePaper-Gerät: geflasht und in Betrieb. Display, I²C, Codec, SD-Karte, Aufnahme, Transkription (übers Heim-WLAN) und Portal sind am Gerät bestätigt; der Tunnel mit einer echten Notiz noch nicht. Offene Punkte in geraete/epaper.md.
  • LCD-Board: die weiter entwickelte Basis — Bedienung, Statuszeile, Portal, WireGuard, Whisper und Energiesparen laufen dort. Siehe geraete/lcd154.md.
  • Firmware und Gehäuse des Auslieferungsstands v1.0 bleiben inhaltlich unverändert erhalten; alles Neue kommt als Board-Profil-Schicht dazu.

Funktionen der Firmware

Alles in diesem Abschnitt gilt für beide Geräte. Was nur eines betrifft, steht in geraete/.

Einstellungen: seitenweise

Mit sechs Einträgen wurden die Zeilen so flach, dass die Schrift kaum noch Luft hatte. Die Liste zeigt jetzt vier je Seite; jeder weitere Eintrag öffnet automatisch eine neue. Der Cursor läuft wie bisher zyklisch durch alle Einträge, die Seite folgt ihm — die Seitenzahl steht in der Kopfzeile hinter dem Titel (einstellungen 1/2). Weitere Einträge brauchen also keine Anpassung der Geometrie mehr.

Sprache

Die Oberfläche war ein Mischmasch: Das Original war englisch, die späteren Ergänzungen deutsch. Jetzt laufen alle Anzeigetexte über T() aus src/app/lang.cpp — eine Tabelle je Sprache, Vorgabe Deutsch, umschaltbar unter Settings → sprache und im NVS gemerkt.

Umlaute: Die GFX-Zeichensätze enthalten nur ASCII. Statt einen eigenen Satz zu pflegen, bildet utf8ToInternal() die UTF-8-Folgen auf freie Steuercodes ab; gezeichnet wird die Glyphe des Grundbuchstabens, die zwei Punkte kommen aus drawGlyphFont() dazu — Größe und Abstand aus der Glyphenbreite, damit es in jeder Schriftgröße stimmt. Das kostet kein Flash. Das scharfe S wird zu ss: Es bräuchte eine eigene Glyphe und kommt in den Oberflächentexten nicht vor.

Nicht übersetzt werden bewusst: die Tags (Nutzerdaten, stehen so auf der Karte und in jeder Notiz — übersetzte Tags würden bestehende Notizen von ihrem Tag trennen), die Wortmarke „pala“, die Sprachkürzel de/en und die kurzen Fehlermeldungen (NO WIFI, SD ERR …), die eher Diagnosecodes als Sätze sind.

Einen neuen Text aufzunehmen heißt: ID in lang.h ans Ende der Aufzählung (vor S_COUNT), beide Fassungen in lang.cpp an dieselbe Stelle in beiden Tabellen.

Ruhebildschirm: der Ring zeigt die Karte

Der große Ring zeigte den Ladezustand — den nennt inzwischen die Statuszeile. Jetzt zeigt er den freien Platz auf der SD-Karte: Der Bogen läuft im Uhrzeigersinn und wird kürzer, je weniger frei ist — voller Ring heißt leere Karte. Bewusst ohne Zahlenwert; der Ring ist die Anzeige.

Der Wert wird gepuffert: usedBytes() liest die Belegungstabelle und dauert auf großen Karten spürbar, das gehört nicht in jeden Bildschirmaufbau.

WLAN einrichten am Gerät

Bis hierher waren SSID und Passwort fest einkompiliert (secrets.h) — das Gerät lief also nur dort, wo es gebaut wurde. Jetzt: Settings → wifi.

Das Gerät sucht die Netze in Reichweite und zeigt sie nach Signalstärke sortiert; ein Stern markiert gesicherte Netze. Nach der Auswahl:

  • offenes Netz oder Passwort schon gespeichert → verbindet sofort.
  • sonst → das Gerät macht für die Dauer der Einrichtung einen eigenen Access Point PalaNote-Setup auf. Telefon damit verbinden, im Browser 192.168.4.1 öffnen, Passwort eintippen. Das Gerät speichert es im NVS, schaltet den Access Point ab und verbindet sich.

Warum das Passwort nicht am Gerät eingegeben wird: Mit drei Tasten bliebe nur, sich durch ein Alphabet zu blättern. Bei ~70 möglichen Zeichen und einem üblichen Passwort sind das mehrere hundert Tastendrücke — für etwas, das man bei jedem Ortswechsel neu braucht. Der Umweg übers Telefon dauert zwanzig Sekunden.

Gespeichert wird ein Netz (Preferences, Namespace palawifi). Solange nichts gespeichert ist, greifen weiterhin die Werte aus secrets.h — bestehende Installationen ändern ihr Verhalten also nicht.

Notizportal — im WLAN oder als eigener Access Point

Settings → transfer startet die Weboberfläche: Notizen lesen, Tags vergeben und löschen, Aufnahmen anhören, alles als Text exportieren.

Das Gerät versucht zuerst das bekannte WLAN. Findet es keines — unterwegs der Normalfall —, macht es einen eigenen Access Point auf, statt abzubrechen:

Netz PalaNote (TRANSFER_AP_NAME)
Passwort notizbuch (TRANSFER_AP_PASS)
Adresse 192.168.4.1

Die mittlere Taste schaltet zwischen beiden um, ohne das Portal zu verlassen. Im WLAN bleibt das Tablet nebenbei online, als Access Point funktioniert es überall.

Das AP-Passwort steht im Quelltext und auf dem Bildschirm. Es schützt nicht vor jemandem, der das Gerät in der Hand hält — es verhindert nur, dass ein offenes Netz mit den eigenen Notizen in der Gegend steht.

iOS-Eigenheit: iPads verlassen Netze ohne Internetzugang mitunter von selbst. Falls die Verbindung abreißt, im WLAN-Menü beim Heimnetz „Automatisch verbinden“ vorübergehend abschalten.

Transkription im eigenen Netz

v1.0 schickte die Aufnahmen an die OpenAI-Whisper-API. Jetzt gehen sie an einen eigenen whisper.cpp-Dienst auf der DS1621 (10.47.11.10:8095, Endpunkt /inference) — im Heimnetz direkt, unterwegs durch den WireGuard-Tunnel. Damit verlässt keine Sprachnotiz mehr das eigene Netz, und es braucht keinen API-Schlüssel im Gerät.

Der Dienst antwortet in derselben Form wie OpenAI ({"text": "..."}), deshalb blieb die Auswertung unverändert. Unterschiede: kein TLS (eigenes Netz), und statt eines Modellnamens die Felder response_format und language — welches Modell geladen ist, entscheidet der Dienst.

Am Dienst gemessen (ggml-small-q5_1): Die Dauer hängt nicht an der Audiolänge, sondern an der Zahl der 30-Sekunden-Fenster. Die Steigung ist allerdings steiler als am 11.09.2026 angenommen — nachgemessen am 26.09.2026 mit erzeugten Tönen:

Audio Fenster Dauer je Fenster
Testton 1 s 1 19,2 / 21,2 / 18,6 s ~20 s
Testton 90 s 3 60,5 s 20,2 s
echte Notiz 0,6 s 1 25,8 s 25,8 s
echte Notiz 2,2 s 1 34,9 s 34,9 s
dichte Sprache 241 s 8 325,8 s 40,7 s

Der Inhalt entscheidet, nicht nur die Fensterzahl. Ein Ton ohne Sprache kostet rund 20 s je Fenster, dichte Sprache ohne Pausen das Doppelte. Die frühere Angabe „alle rund 12–13 s“ blieb an kurzen Proben hängen.

Daraus folgt die Zeitgrenze: REC_MAX_MS erlaubt zehn Minuten je Abschnitt, das sind zwanzig Fenster und damit rund 814 s. WHISPER_TIMEOUT_MS steht deshalb auf 1200 s — vorher 240 s, was eine Notiz in voller Länge unbemerkt hätte scheitern lassen.

Offene Frage, die die Messung aufwirft: Eine Notiz in voller Länge macht das Gerät rund 14 Minuten unbedienbar, weil autoSyncTick() die Schleife blockiert. Ob REC_MAX_MS deshalb kürzer sein sollte, ist noch nicht entschieden.

Über WHISPER_LOCAL 0 in config.h lässt sich der alte Weg zu OpenAI reaktivieren.

Funk und Tunnel: bei Bedarf, nicht auf Vorrat

Das Gerät ist im Leerlauf nicht im WLAN — Funk ist nach dem Display der größte Verbraucher. Es schaltet ihn ein, wenn er gebraucht wird: beim Auto-Sync, beim Notizportal, beim Zeitabgleich.

Solange WLAN steht, hält autoVpnTick() den Tunnel selbsttätig aufrecht; ohne WLAN wird der Funk dafür nicht eigens geweckt. Beide Abgleichswege — der automatische wie der über Menü → abgleich — bauen den Tunnel vor dem Transkribieren auf. Vor dem Transkribieren wird der Tunnel sichergestellt, weil der Whisper-Dienst unterwegs nur darüber erreichbar ist.

Damit ist das Schloss die meiste Zeit offen — nicht weil etwas kaputt wäre, sondern weil nichts läuft. Deshalb zeigt die Statuszeile in diesem Fall ein Zz an Stelle von Funkbalken und Schloss: ruhend, nicht gestört.

WireGuard

Settings → vpn. Da für den Tunnel ohnehin WLAN stehen muss, läuft das Einrichtungsformular im WLAN statt über einen eigenen Access Point — das Gerät zeigt seine IP, das Telefon muss das Netz nicht wechseln. Endpunkt, Port, eigene VPN-Adresse und der öffentliche Schlüssel des Servers sind vorbelegt (config.h, nichts davon ist geheim); einzutippen sind nur privater Schlüssel und Preshared Key. Beide landen im NVS, nie im Quelltext.

Ist bereits ein Schlüssel hinterlegt, verbindet das Gerät direkt, ohne das Formular zu zeigen. Das Schloss in der Statuszeile schließt sich, sobald der Tunnel steht.

Die Bibliothek liegt als Kopie unter lib/WireGuard-ESP32/ statt in lib_deps — ihr Arduino-Wrapper setzt den Preshared Key hart auf NULL, obwohl der Kern ihn unterstützt. Begründung und die eigenen Änderungen stehen in lib/WireGuard-ESP32/HERKUNFT.md.

Kosten im Speicher, am Board gemessen: +1,0 KB RAM, +26,3 KB Flash.

Der Tunnel steht (verifiziert 11.09.2026, Handshake gegen den realen Peer). Die Probe zielt auf 10.13.13.1 im VPN-Subnetz und wertet die Antwortzeit aus: Eine sofortige Ablehnung beweist, dass Pakete hin und zurück laufen — auch wenn dort kein Dienst lauscht. Ein Ziel im Heimnetz taugt dafür nicht, weil ein direkt verbundenes Netz die Standardroute durch den Tunnel schlägt.

Drei Fallen lagen auf dem Weg, alle in lib/WireGuard-ESP32/HERKUNFT.md bzw. im Projekt-Memory festgehalten: ein Absturz der Bibliothek (Zufallsgenerator zu spät eingerichtet), eine Gegenprobe, die sich selbst betrog, und ein fehlendes [Peer] in wg0.conf, das zwei Server-Einträge verschmolz.

Automatisches Transkribieren

Einen Stapel Notizen von Hand zu synchronisieren dauert Minuten und blockiert solange die Bedienung. Deshalb arbeitet das Gerät sie im Ruhezustand selbst ab — eine je Durchgang, nach 30 s ohne Eingabe. Ein Durchgang dauert rund 13 s, danach ist das Gerät wieder frei; die nächste Notiz folgt im nächsten Durchlauf. Nach einem Fehlschlag (Dienst weg, kein WLAN) legt es fünf Minuten Pause ein.

Der Sync wartet auf eine eigene Zeitmarke (lastInputMs), die nur echte Tastendrücke zurücksetzen — lastActivityMs wird vom Abdunkeln zurückgesetzt und hätte den Sync dauerhaft ausgebremst.

Schalter: AUTO_SYNC in config.h.

Noch offen:

  1. Laufzeit messen. Bisher nur geschätzt.