admin 4cb8ea32d5 Helligkeitsregelung (LDR -> Stufe/Prozent) ergaenzt
- 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>
2026-07-18 09:13:02 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00
2026-07-16 09:05:56 +02:00

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.53.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/L und CHK-H/L nicht mitgesendet werden.
  • Prüfsumme = Low-Byte der Summe aus DA, SA, FC, LEN-H, LEN-L und 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 0100 %
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.py steht MOUNT_HOST noch 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.py sind bewusst abhängigkeitsfrei; nur transport (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 ruler misst 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_dec wählt automatisch die breiteste Form, die in CHARS_PER_LINE passt.
  • Zyklische Updates flimmerfrei: show_lines löscht nicht bei jeder Aktualisierung, sondern überschreibt die Zeilen an Ort und Stelle (auf volle Breite aufgefüllt). clear=True nur beim ersten Bild. Wichtig: Zeilen dürfen nicht breiter als CHARS_PER_LINE aufgefü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, 04095: 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 schmale 1 wirkt dadurch etwas luftig — Font-Eigenschaft, nur per eigenem Font (microSYST-PC-Software) änderbar.
S
Description
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.
Readme 510 KiB
Languages
Python 99%
Shell 1%