- brightness.py: BrightnessController + CLI, portiert aus DoDimmen_V/main.h (gleitender Mittelwert, Hysterese). Schwellen 300/2500 aus altem Code, Prozente 5/15/50/100 - verallgemeinert auf 4 Stufen: 100% jetzt erreichbar (alter Code max 50%); neue obere Grenze HELL_MAX=3500 (anpassbar), Rest wie im Original - run_display: --ldr bindet die Regelung in die Hauptschleife ein (sendet nur bei Stufenwechsel) - test_brightness.py: Schwellen, Hysterese, Mittelung - README dokumentiert die Regelung; .gitignore: Hardware/ Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Großanzeige
Ansteuerung einer microSYST migra SC/MC Seriell LED-Großanzeige mit den Koordinaten (Rektaszension / Deklination) einer 10Micron GM4000 HPS II.
Endziel ist ein XIAO ESP32-C3, der die Montierung per WLAN abfragt und die Koordinaten über UART/RS232 auf die Anzeige schreibt. Phase 1 (dieser Stand) ist das Testprogramm auf dem Mac: Koordinaten von Hand übergeben, Ausgabe über einen USB-RS232-Wandler.
Benutzung
# Phase 1 -- Koordinaten von Hand:
python3 show_coords.py 12h34m56s +45d12m30s # Koordinaten anzeigen
python3 show_coords.py 12:34:56 -07:15:00 # Trennzeichen sind egal
python3 show_coords.py --clear # Anzeige löschen
python3 show_coords.py 12h34m56s +45d12m30s --dry-run # nur Telegramm als Hex
# Phase 2 -- Koordinaten von der Montierung (10Micron GM4000):
python3 run_display.py # Montierung aus config.py pollen
python3 run_display.py --host 10.0.0.42 # andere IP
python3 run_display.py --mock --move # ohne Teleskop: lokaler Mock, RA läuft
python3 run_display.py --mock --move --ldr 2000 # zusätzlich mit Helligkeitsregelung
python3 mount_mock.py --move # Mock separat starten
# Helligkeit aus einem LDR-Wert setzen:
python3 brightness.py --ldr 1500 # LDR-Rohwert -> Stufe/Prozent -> senden
python3 -m unittest test_migra test_lx200 test_brightness # alle Tests
python3 probe.py ruler # Geometrie der Anzeige ausmessen
Einzige Abhängigkeit auf dem Mac ist pyserial.
Aufbau
| Datei | Zweck |
|---|---|
migra.py |
Protokoll: Telegrammrahmen, Prüfsumme, ESC-Sequenzen. Ohne Abhängigkeiten, läuft unverändert unter MicroPython. |
transport.py |
UART: pyserial (Mac), machine.UART (ESP32-C3), FakeTransport (Trockenlauf). |
display.py |
Treiber: Telegramm senden, Antwort auswerten. |
coords.py |
Koordinaten einlesen und auf die Zeilenbreite formatieren. |
config.py |
Port, Adresse, Geometrie, Helligkeit — alles an einer Stelle. |
show_coords.py |
Das Testprogramm (Koordinaten von Hand). |
brightness.py |
Helligkeitsregelung: LDR-Wert → Stufe/Prozent (portabel + CLI). |
run_display.py |
Hauptschleife Phase 2: Montierung pollen, anzeigen, Helligkeit regeln. |
mount_client.py / mount_mock.py |
TCP-Client zur GM4000 bzw. Simulator (LX200). |
lx200.py |
LX200-Kommandorahmen. |
probe.py |
Testmuster zum Ausmessen von Zeilenbreite und Zeilenposition. |
test_migra.py / test_lx200.py / test_brightness.py |
Tests. |
Protokoll (Kurzfassung)
Referenz: Benutzerhandbuch X-M31-9AXX5X-006 (V4.20), Kapitel 3.5–3.9.
Schnittstelle: 19200 Baud, 8 Datenbits, Even Parity, 1 Stopbit. 9-pol. Sub-D: Pin 2 = RxD, Pin 3 = TxD, Pin 5 = GND.
Telegramm:
STX | DA | SA | FC | [LEN-H LEN-L] | Data-Unit | [CHK-H CHK-L] | ETX
02 81 80 81 03
DA/SA: Adressen mit gesetztem Bit 7 → Anzeige = 1 (0x81), Host = 0 (0x80).FC: Bit 7 fest 1, Bit 1 = Prüfsumme, Bit 0 = Antwort anfordern.0x81= ohne Prüfsumme, mit Antwort (so fuhr auch das alte MSP430-Programm).- Ohne Prüfsumme dürfen
LEN-H/LundCHK-H/Lnicht mitgesendet werden. - Prüfsumme = Low-Byte der Summe aus
DA, SA, FC, LEN-H, LEN-Lund allen Datenbytes, als zwei Nibbles mit gesetztem High-Nibble (0xF0 | nibble).
Antwort: 02 80 81 80 <Fehlercode> 03, Fehlercode '0' = kein Fehler.
Nach Erhalt der Antwort darf sofort das nächste Telegramm folgen — das ist die
Flusskontrolle. Ohne Antwort muss zwischen den Telegrammen gewartet werden
(Empfangstimeout + ca. 150 ms).
ESC-Sequenzen (alle Zahlen ASCII-codiert, Position 123 → '1' '2' '3'):
| Sequenz | Bedeutung |
|---|---|
ESC z NN / ESC Z NN |
Zeichensatz NN (z = Sperrschrift, gleiche Zeichenbreite) |
ESC C xxxyyy |
Cursor auf Pixelposition x/y, 0/0 ist links oben |
ESC A <fg><bg><blink> |
Attribute; Farbe 0 = schwarz, 1 = grün, 2 = rot, 3 = gelb |
ESC F <Farbe> |
Anzeige füllen; ESC F 0 = löschen |
ESC H <Farbe><ppp> |
Helligkeit 0–100 % |
ESC T <+/-><nnn> |
gespeicherten Text ein-/ausblenden |
Folgt auf eine ESC-Sequenz ein Online-Text, muss 0x1F als Trennzeichen
dazwischen. Data-Unit max. 230 Zeichen. migra.DataUnit setzt das Trennzeichen
selbst.
Offene Punkte
- Echte Montierungs-IP: In
config.pystehtMOUNT_HOSTnoch als Platzhalter. Sobald die GM4000 im Netz erreichbar ist, dort die IP eintragen (Port 3490 ist Vorgabe). Bis dahin läuft alles gegen den Mock (run_display.py --mock). - Portierung auf den XIAO ESP32-C3 (MicroPython):
migra.py,lx200.py,mount_client.pysind bewusst abhängigkeitsfrei; nurtransport(UART) und das WLAN-Setup kommen hinzu.
Gradzeichen
Der Standard-Zeichensatz 0 der Anzeige hat kein °. Der von der Sternwarte
geladene Zeichensatz 1 enthält an Position / (0x2F) ein hochgestelltes
Gradzeichen (deckt sich mit dem alten Programm, asciitaf.h: Code 0xAF → per
& 0x7F = 0x2F in Zeichensatz 1). Zur Ausgabe wird für dieses eine Zeichen kurz
auf Zeichensatz 1 umgeschaltet und wieder zurück (config.DEGREE_*, display._emit_degree).
Fallstrick: Ein Zeichensatzwechsel mitten im Telegramm beschädigt die Home-Zelle
(0,0) — das erste Zeichen der obersten Zeile wird zerstört. Deshalb zeichnet
show_lines die Zeilen von unten nach oben (oberste Zeile zuletzt), damit sie
diese Zelle überschreibt.
Geometrie und Darstellung
- 9 Zeichen pro Zeile in Sperrschrift (
CHARSET_SPACED = True, am Gerät ausgemessen).probe.py rulermisst es nach. - Die Deklination wird deshalb als 9-Zeichen-Form ohne abschließendes
"ausgegeben (+38°47'01) — Gradzeichen und Bogenminuten bleiben, die Bogensekunden stehen als Ziffern da.coords.format_decwählt automatisch die breiteste Form, die inCHARS_PER_LINEpasst. - Zyklische Updates flimmerfrei:
show_lineslöscht nicht bei jeder Aktualisierung, sondern überschreibt die Zeilen an Ort und Stelle (auf volle Breite aufgefüllt).clear=Truenur beim ersten Bild. Wichtig: Zeilen dürfen nicht breiter alsCHARS_PER_LINEaufgefüllt werden, sonst bricht das Füll-Leerzeichen um und beschädigt die andere Zeile.
Helligkeitsregelung
Portiert aus dem alten MSP430-Programm (DoDimmen_V, Werte aus main.h). Ein
LDR-Rohwert (12-Bit-ADC, 0–4095: je heller die Umgebung, desto höher der Wert)
wird über einen gleitenden Mittelwert (8 Werte) geglättet und auf eine
Helligkeitsstufe mit Hysterese abgebildet:
| Stufe | Helligkeit | erreicht ab (hoch / runter) |
|---|---|---|
| 0 | 5 % | < 270 |
| 1 | 15 % | ≥ 330 / < 270 |
| 2 | 50 % | ≥ 2650 / < 2350 |
| 3 | 100 % | ≥ 3650 / < 3350 |
Schwellen-Mitten 300 / 2500 / 3500, Hysterese ±30 / ±150 / ±150. 300 und 2500
stammen aus dem alten Code; die obere Grenze HELL_MAX = 3500 für 100 % ist neu
(der alte Code hatte keine 4. Stufe) und in brightness.py anpassbar, sobald der
reale LDR-Wertebereich feststeht. Ein Helligkeitstelegramm wird nur bei
Stufenwechsel gesendet (ESC H 2 <ppp>), wie im Original.
Der LDR-Wert kommt derzeit per Kommandozeile (--ldr); auf dem ESP32-C3 liefert
ihn später der ADC. run_display.py --ldr <wert> bindet die Regelung in die
Hauptschleife ein (BrightnessController).
Antwortleitung (RX)
Der Rückkanal ist verdrahtet und verifiziert (2026-07-16): Anzeige Pin 3 (TxD) →
MAX232-Empfängereingang (R_IN) → R_OUT → Adapter RxD. Die Anzeige quittiert jedes
Telegramm mit 02 80 81 80 30 03 (Fehlercode 0 = kein Fehler). WANT_RESPONSE = True
ist damit aktiv: Nach der Antwort darf sofort das nächste Telegramm folgen, der
Fehlercode wird ausgewertet. resp_test.py prüft den Rückweg (sendet mit Antwort-
Anforderung und zeigt die empfangenen Antworten).
Wichtig: SerialTransport.write leert vor jedem Senden den Empfangspuffer, damit
read_response nur die frische Antwort sieht (sonst können Störbytes zwischen den
Telegrammen das Parsen stören). run_display fängt Anzeige-Fehler ab und zeichnet
beim nächsten Durchlauf neu, statt abzustürzen.
Diagnose-Historie: Der Rückweg war anfangs falsch verdrahtet — Pin 3 lag an einem
MAX232-Senderausgang statt einem Empfängereingang; zwei Ausgänge trieben
gegeneinander (verschliffener ~3-V-Pegel am Oszi). loopback.py grenzt so etwas ein.
Erledigt
- Phase 1 + 2 am Gerät bestätigt (2026-07-15/16): Koordinaten erscheinen korrekt,
inkl. echtem Gradzeichen; im
run_display-Betrieb aktualisieren beide Zeilen laufend, sauber und ohne Flimmern, mit Antwort-Handshake der Anzeige. Protokoll, 19200 8E1, Zeichensatz und Zeilengeometrie stimmen. - Schrift: Sperrschrift (
ESC z,CHARSET_SPACED = True), 10 Zeichen/Zeile. Die schmale1wirkt dadurch etwas luftig — Font-Eigenschaft, nur per eigenem Font (microSYST-PC-Software) änderbar.