admin e8a5b5d5e3 LDR-Schwellen am realen Aufbau gemessen statt vom MSP430 uebernommen
Gemessen am XIAO ESP32-C3 mit dem LDR an GPIO2, je 200 Werte, Median
(Angaben nach raw_to_ldr, also in Zaehlrichtung "gross = hell"):

    abgedeckt      roh 4095 (ADC-Anschlag)  ->    0
    Raumlicht      roh 1642                 -> 2453
    angeleuchtet   roh  543                 -> 3552

Zwei Fehler in den alten Werten, die erst die Messung zeigt:

- Stufe 3 (100 %) war unerreichbar. Sie begann bei 3650, selbst eine Taschenlampe
  direkt auf dem Sensor kam nur auf 3552. Die Anzeige haette nie voll aufgedreht.
- Die Hysterese von 30 am untersten Uebergang lag unter dem Rauschen. Der Rohwert
  streut bei Raumlicht um +/-270, nach dem gleitenden Mittel bleiben rund +/-32
  (1 Sigma) -- die unterste Stufe haette geflattert.

Neu: Mitten 1200/2400/3200, Hysterese einheitlich 150. Die Aufteilung haelt den
5-%-Bereich bis 1200 (Nutzerwunsch "nachts laenger dunkel", schont die
Dunkeladaption der Beobachter). Die gestaffelten Hysteresen des alten Programms
entfallen -- die gemessene Streuung ist an allen Grenzen dieselbe.

Bekannte Grenzlage, in test_brightness festgehalten: Raumlicht (2453) liegt nur
53 Zaehler ueber HELL_HIGH und damit innerhalb der Hysterese, faellt also auf
Stufe 1 statt 2. Ob das so gewollt ist, entscheidet sich in der Sternwarte.

Am Geraet bestaetigt: Regelung laeuft stabil ohne Flattern, Abdecken schaltet
herunter, Freigeben wieder hoch, Helligkeitstelegramm wird quittiert. Die
Schwellen sind aber am Schreibtisch gemessen -- with_ldr bleibt deshalb auf
False, bis sie vor Ort bestaetigt sind. 101 Tests gruen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 16:21:08 +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.

Zielgerät ist ein XIAO ESP32-C3, der die Montierung per WLAN abfragt und die Koordinaten über UART/RS232 auf die Anzeige schreibt. Entwickelt und getestet wird auf dem Mac (Koordinaten von Hand bzw. von der Montierung, Ausgabe über einen USB-RS232-Wandler); dieselben Module laufen auf dem ESP32.

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 test_display test_esp32
python3 probe.py ruler                           # Geometrie der Anzeige ausmessen

Auf dem ESP32-C3 (siehe Abschnitt ESP32-C3):

cp wifi_config_example.py wifi_config.py         # WLAN-Zugangsdaten eintragen
./deploy.sh                                      # Dateien auf den ESP32 kopieren
mpremote repl                                    # dann:  import run_esp32
                                                 #        run_esp32.main()

Einzige Abhängigkeit auf dem Mac ist pyserial, fürs Übertragen zusätzlich mpremote. Auf dem ESP32 laufen die Module ohne jede Fremdbibliothek.

Aufbau

Alles, was auf beiden Plattformen läuft, ist bewusst abhängigkeitsfrei gehalten. Was sich unterscheidet, steckt in transport.py (UART) und in den beiden Startprogrammen.

Datei Zweck ESP32
migra.py Protokoll: Telegrammrahmen, Prüfsumme, ESC-Sequenzen.
transport.py UART: pyserial (Mac), machine.UART (ESP32-C3), FakeTransport (Trockenlauf).
ticks.py Timeouts, die unter CPython und MicroPython gleich funktionieren.
display.py Treiber: Telegramm senden, Antwort auswerten.
coords.py Koordinaten einlesen und auf die Zeilenbreite formatieren.
config.py Port/Pins, Adresse, Geometrie, Helligkeit, WLAN — alles an einer Stelle.
displayloop.py Die Poll-Schleife: abfragen, formatieren, anzeigen, Fehler abfangen.
brightness.py Helligkeitsregelung: LDR-Wert → Stufe/Prozent.
mount_client.py TCP-Client zur GM4000 (LX200).
lx200.py LX200-Kommandorahmen.
wifi.py WLAN-Anbindung des ESP32 (verbinden, Verbindung halten).
run_esp32.py Startprogramm auf dem ESP32: WLAN, Anzeige, Schleife.
wifi_config.py WLAN-Zugangsdaten, nicht im Git (Vorlage wifi_config_example.py).
run_display.py Startprogramm auf dem Mac: dieselbe Schleife mit Kommandozeile.
show_coords.py Testprogramm (Koordinaten von Hand).
mount_mock.py Simulator der Montierung (LX200) fürs Testen ohne Teleskop.
probe.py Testmuster zum Ausmessen von Zeilenbreite und Zeilenposition.
deploy.sh Kopiert die ESP32-Dateien per mpremote auf das Gerät.
test_migra.py / test_lx200.py / test_brightness.py / test_display.py / test_esp32.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.

ESP32-C3

Verdrahtung

Die Pins stammen aus dem Schaltplan (Hardware/KiCad/Grossanzeige) und stehen in config.py. Am XIAO ESP32-C3 ist UART1 frei zuordenbar; UART0 bleibt für die REPL-Konsole über USB reserviert.

XIAO GPIO Netz weiter zu
Pad 7 (D6) 21 TX MAX3232 T2INT2OUT → J5.3 → Anzeige RxD (Sub-D Pin 2)
Pad 8 (D7) 20 RX MAX3232 R2OUTR2IN ← J5.2 ← Anzeige TxD (Sub-D Pin 3)
Pad 1 (D0/A0) 2 LDR Spannungsteiler J2, siehe unten
Pad 12 3V3 MAX3232 VCC
Pad 13 GND gemeinsame Masse

Die Anzeige will RS232-Pegel, der ESP32-C3 kann nur TTL — der MAX3232 dazwischen ist zwingend.

Einrichten

MicroPython für den ESP32-C3 flashen (einmalig; Firmware von micropython.org/download/ESP32_GENERIC_C3):

pip install esptool mpremote
esptool.py --chip esp32c3 --port /dev/cu.usbmodem1101 erase_flash
esptool.py --chip esp32c3 --port /dev/cu.usbmodem1101 --baud 460800 \
           write_flash -z 0x0 ESP32_GENERIC_C3-*.bin

Dann die Zugangsdaten anlegen und alles übertragen:

cp wifi_config_example.py wifi_config.py     # SSID und Passwort eintragen
./deploy.sh                                  # oder ./deploy.sh /dev/cu.usbmodem1101

wifi_config.py steht in .gitignore — das WLAN-Passwort gehört nicht ins Repository.

Starten

mpremote repl
>>> import run_esp32
>>> run_esp32.main()              # ohne Helligkeitsregelung
>>> run_esp32.main(with_ldr=True) # mit LDR über den ADC

Bewusst kein main.py: MicroPython startet eine Datei dieses Namens nach jedem Reset von selbst, und solange am Aufbau gearbeitet wird, ist der manuelle Start angenehmer. Für den Dauerbetrieb in der Sternwarte reicht später eine main.py mit den zwei Zeilen von oben.

Was auf beiden Seiten gleich läuft

displayloop.poll_loop ist die gemeinsame Hauptschleife — Mac und ESP32 fahren denselben Ablauf, drumherum liegt nur die Kommandozeile (run_display.py) bzw. das WLAN-Setup (run_esp32.py). Fällt das WLAN aus, zeigt die Anzeige NOWIFI_LINES, fällt die Montierung aus, NOLINK_LINES; in beiden Fällen läuft die Schleife weiter und verbindet sich neu.

Stolpersteine, die beim Portieren aufgefallen sind und in den Tests festgehalten sind (test_esp32.py, test_display.py):

  • MicroPython hat kein str.ljust (auch kein rjust/center/zfill). Das fiel erst am Gerät auf — auf dem Mac gibt es die Methode, alle Tests waren grün. display._emit_line füllt jetzt von Hand auf. TestMicropythonVertraeglichkeit sucht solche Aufrufe seitdem statisch.
  • time.ticks_ms() läuft nach ~12 Tagen über. Ein einfaches „jetzt + Timeout" ließe eine Warteschleife danach tagelang hängen. ticks.py rechnet deshalb über ticks_diff, das den Überlauf richtig behandelt.
  • Der UART braucht denselben Puffer-Flush wie pyserial. UartTransport.write leert den Empfangspuffer vor jedem Senden, sonst sieht read_response alte Störbytes statt der frischen Antwort.
  • Feste Anzeigetexte müssen in CHARS_PER_LINE passen. NOLINK_LINES hieß zuerst „MONTIERUNG" (10 Zeichen) und erschien als „MONTIERUN"; _emit_line schneidet stillschweigend ab. test_display.py prüft die Breite jetzt. (Seit CHARS_PER_LINE = 10 würde „MONTIERUNG" wieder passen — die Texte sind aber bei „KEIN LINK"/„TELESKOP" geblieben.)

Was MicroPython 1.28 entgegen der Erwartung doch kann (am Gerät nachgeprüft): %0*d mit dynamischer Feldbreite, %-11s, bytes.hex(), str.strip/lstrip, str.isdigit.

Ohne Hardware lässt sich der ESP32-Teil trotzdem weitgehend prüfen: test_esp32.py hängt Attrappen für machine und network ein und fährt die ganze Kette gegen einen echten Mock — UART-Transport, WLAN, ADC-Auswertung, Zeitrechnung und die Poll-Schleife samt Ausfallverhalten.

Gegen den Mock auf dem Mac testen

Solange die Montierung nicht erreichbar ist, spielt der Mock ihre Rolle. Er muss dafür auf allen Schnittstellen lauschen, sonst kommt der ESP32 nicht heran:

python3 mount_mock.py --lan --move        # gibt die IP aus, die einzutragen ist

Auf dem ESP32 dann:

import run_esp32
run_esp32.selftest(host="192.168.178.26")                  # Bring-up prüfen
run_esp32.main(host="192.168.178.26", fake_display=True)   # Dauerschleife

selftest geht die drei Stufen einzeln durch — WLAN, Montierung, Telegrammbau — und sagt, an welcher es klemmt. fake_display=True schreibt die Telegramme nur als Hex in die REPL, es braucht also weder Pegelwandler noch Anzeige.

Wenn keine Verbindung zustande kommt, obwohl der Mock lauscht: macOS fragt beim ersten Mal, ob python3 eingehende Verbindungen annehmen darf — das muss erlaubt sein.

Am Gerät bestätigt (2026-07-26)

XIAO ESP32-C3 mit MicroPython 1.28.0 (ESP32_GENERIC_C3), gegen den Mock auf dem Mac:

  • Alle zwölf Module importieren auf dem Gerät.
  • Telegrammbau und Koordinaten-Formatierung sind byte-identisch zum Mac, inklusive Gradzeichen über den Zeichensatzwechsel.
  • WLAN verbindet sich, selftest geht durch alle drei Stufen.
  • Die Poll-Schleife lief 20 s im Sekundentakt, 22 Abfragen ohne Aussetzer.
  • Ausfall und Erholung: Mock gestoppt → „KEIN LINK / TELESKOP" erscheint, die Schleife läuft weiter; Mock zurück → automatischer Reconnect, und der erste Wiedereinstieg löscht einmal das Vollbild, sodass kein Rest stehen bleibt.
  • UART1 öffnet auf GPIO21/20 mit 19200 8E1, sendet, und der Lese-Timeout greift sauber (kein Hänger) — allerdings noch ohne Gegenstelle.
  • ADC auf GPIO2 mit 11 dB Dämpfung liefert Werte.

Offene Punkte

  • LDR-Schwellen in der Sternwarte gegenprüfen. Die Grenzen sind am realen Aufbau gemessen (2026-07-27, siehe Helligkeitsregelung), aber am Schreibtisch. Vor Ort bei Tag und Nacht die Rohwerte ablesen und HELL_LOW/HELL_HIGH/ HELL_MAX bestätigen — besonders die Grenzlage bei 2400. Bis dahin läuft die Anzeige mit fester Helligkeit (run_esp32.main() ohne with_ldr).
  • Netzwerk zur echten Montierung. Die GM4000 steht in 192.168.1.115, das Heimnetz des ESP32 ist 192.168.178.x — der Mac erreicht sie per VPN, der ESP32 so nicht. Muss geklärt werden, bevor es an die echte Montierung geht.
  • Dauerbetrieb: Autostart (main.py) und ein Watchdog fehlen noch bewusst.

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 beschädigt die Home-Zelle (0,0) — das erste Zeichen der obersten Zeile wird zerstört. Deshalb schreibt show_lines die Zeilen von unten nach oben (oberste Zeile zuletzt), damit sie diese Zelle überschreibt. Das gilt weiterhin, seit jede Zeile ihr eigenes Telegramm bekommt: dann entscheidet die Reihenfolge der Telegramme statt der Reihenfolge innerhalb eines Telegramms.

Geometrie und Darstellung

  • 10 Zeichen pro Zeile zu 6 px (CHARS_PER_LINE = 10, CELL_WIDTH = 6), am Gerät entschieden mit probe.py pitch 6 (2026-07-27).

    Vorher stand hier 9 — das war am Zeilenumbruch abgezählt und maß etwas anderes, als es zu messen schien. probe.py pitch stellt den Auto-Vorschub der Anzeige gegen feste Pixelpositionen x = i·cell und trennt damit beides:

    • Der Auto-Vorschub der Sperrschrift ESC z ist 7 px. Eine Zeile in einem Stück geschrieben bricht deshalb nach 9 Zeichen um (9·7 = 63 von 64 px).
    • Die Zeichenmatrix ist aber nur 6 px breit. Zehn Ziffern, einzeln auf x = i·6 gesetzt, stehen sauber getrennt nebeneinander (60 von 64 px).

    Deshalb positioniert display._emit_line jedes Zeichen selbst, statt den Auto-Vorschub laufen zu lassen. Der Preis sind längere Telegramme (rund 10 Byte je Zeichen statt 1), der Gewinn ein volles Zeichen mehr pro Zeile.

    python3 probe.py pitch 6     # stehen beide Zeilen untereinander -> 6 px/Zelle
    python3 probe.py pitch 7     # ... -> 7 px/Zelle
    
  • Ein Telegramm je Zeile. Früher gingen beide Zeilen in einem Telegramm raus. Mit Einzelpositionierung kämen sie mit Gradzeichen und Vollbild-Löschen auf 224 der erlaubten 230 Bytes (migra.MAX_DATA_UNIT) — zu wenig Reserve für ein Gerät, das monatelang durchläuft. Getrennte Telegramme halten jedes bei rund der Hälfte; die Flusskontrolle über das Antworttelegramm macht die zweite Sendung unproblematisch. Die Reihenfolge bleibt unten vor oben (Home-Zelle).

  • Die Deklination passt damit in voller Form mit abschließendem " (+38°47'01", 10 Zeichen). coords.format_dec wählt automatisch die breiteste Form, die in CHARS_PER_LINE passt — bei Niedrigpräzision entsprechend +38°47' ohne Sekunden.

  • Zeilen werden zentriert (CENTER_LINES = True). Das wirkt auf zwei Ebenen: LINE_X rückt den Zeichenblock in die Mitte (10·6 = 60 px lassen je 2 px Rand), und kürzere Texte werden beidseitig mit Leerzeichen aufgefüllt. Der Block bleibt dabei immer gleich breit und an derselben Stelle — so überschreibt er bei jedem Durchlauf denselben Bereich und lässt keine Reste stehen. Ein pixelgenau mitwandernder Offset könnte das nicht; dafür ist die Zentrierung nur auf eine halbe Zelle (3 px) genau, wenn die Restbreite ungerade ist.

  • 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.

Präzision (Low / High)

Die GM4000 läuft standardmäßig in Niedrigpräzision und sendet keine Sekunden: RA als HH:MM.T (Zehntel-Minuten), DEC als sDD°MM (ganze Bogenminuten). Das Gradzeichen kommt als Byte 0xDF — auf der Anzeige korrekt als Gradring dargestellt; in der Terminal-Konsole erscheint der Rohwert dieses Bytes als ß (rein kosmetisch).

config.HIGH_PRECISION steuert die DEC-Darstellung:

  • False (Vorgabe): DEC ohne Sekunden (-00°55').
  • True: DEC mit Sekunden (+38°47'01) — erst sinnvoll, wenn die Montierung per :U# auf Hochpräzision gestellt ist (schreibendes Kommando, hier bewusst nicht automatisch gesendet).

Die RA wird immer mit Sekunden gezeigt (11h36m54s); bei Niedrigpräzision kommen die Sekunden aus den Zehntel-Minuten und springen daher in 6-Sekunden-Schritten (kein Dezimalpunkt — der wirkt in der Sperrschrift zu luftig).

coords.format_ra/format_dec nehmen high_precision= als Parameter (Vorgabe aus config). Die Montierungs-Rohwerte werden im coords-Parser unverändert korrekt zerlegt (Trennzeichen :, *, 0xDF, ' sind alle egal).

Helligkeitsregelung

Portiert aus dem alten MSP430-Programm (DoDimmen_V). Ein LDR-Rohwert (12-Bit-ADC, 04095) wird über raw_to_ldr in die Zählrichtung „groß = hell" gebracht, über einen gleitenden Mittelwert (8 Werte) geglättet und auf eine Helligkeitsstufe mit Hysterese abgebildet:

Stufe Helligkeit erreicht ab (hoch / runter)
0 5 % < 1050
1 15 % ≥ 1350 / < 1050
2 50 % ≥ 2550 / < 2250
3 100 % ≥ 3350 / < 3050

Schwellen-Mitten 1200 / 2400 / 3200, Hysterese einheitlich ±150.

Am realen Aufbau gemessen (2026-07-27), XIAO ESP32-C3 mit LDR an GPIO2, je 200 Messwerte, Median — Werte nach raw_to_ldr:

Lichtsituation roh nach raw_to_ldr Stufe
abgedeckt 4095 (ADC-Anschlag) 0 0 → 5 %
Raumlicht 1642 2453 1 → 15 %
angeleuchtet (Taschenlampe) 543 3552 3 → 100 %

Die alten Werte 300 / 2500 / 3500 stammten vom MSP430-Aufbau und passten nicht: Stufe 3 begann bei 3650 und war unerreichbar — selbst eine Taschenlampe direkt auf dem Sensor kam nur auf 3552. Die Aufteilung ist jetzt so gewählt, dass der 5-%-Bereich bis 1200 reicht („nachts länger dunkel", schont die Dunkeladaption).

Auch die Hysterese war zu klein: Der Rohwert streut bei Raumlicht um ±270, nach der Mittelung bleiben rund ±32 (1σ). Die früheren ±30 am untersten Übergang lagen darunter — die unterste Stufe hätte geflattert. Jetzt einheitlich ±150 (≈4,7σ) und damit weit unter dem Stufenabstand von 800.

Ein Helligkeitstelegramm wird nur bei Stufenwechsel gesendet (ESC H 2 <ppp>), wie im Original. Am Gerät bestätigt: Abdecken schaltet herunter, Freigeben wieder hoch, ohne Flattern.

Bekannte Grenzlage: Der gemessene Raumlichtwert 2453 liegt nur 53 Zähler über HELL_HIGH (2400) und damit innerhalb der Hysterese — Raumlicht landet deshalb auf Stufe 1 (15 %), nicht auf 50 %. Ob das so gewollt ist, entscheidet sich erst an den Lichtverhältnissen in der Sternwarte. test_brightness.py hält das Verhalten fest.

Im Dunkeln steht der ADC am Anschlag (4095). Der Teiler treibt A0 über den Messbereich, „Dämmerung" und „stockdunkel" sind daher nicht unterscheidbar. Für die Regelung unkritisch — nachts ist ohnehin die dunkelste Stufe gewollt. Eine feinere Nachtabstufung ginge nur über den Vorwiderstand: sättigungsfrei wäre R2 ≥ R_LDR(dunkel) × (3,3 V U_max)/U_max, also grob R2 ≥ 0,32 × R_LDR(dunkel). Bei einem typischen LDR (0,51 MΩ im Dunkeln) liefe das auf 160330 kΩ hinaus — dann lägen Tag und Raumlicht aber bei ADC-Werten unter 15 und damit in der Totzone. Der LDR überstreicht rund Faktor 4500; ein einzelner Teiler bildet davon nur etwa zwei Dekaden ab. 1022 kΩ wäre der Kompromiss, wenn mehr Nachtauflösung gewünscht ist.

Auf dem Mac kommt der LDR-Wert per Kommandozeile (run_display.py --ldr <wert>), auf dem ESP32-C3 vom ADC an GPIO2 (run_esp32.main(with_ldr=True)).

Die Kennlinie ist auf der Platine umgekehrt. Der Teiler lautet 3V3 —[R2 2k]— A0 —[LDR]— GND; der LDR wird bei mehr Licht niederohmiger, die Spannung an A0 sinkt also mit steigender Helligkeit — genau andersherum als beim alten MSP430-Aufbau, auf den die Schwellen oben zugeschnitten sind. Der Rohwert wird deshalb gespiegelt: config.LDR_INVERTED = True, angewendet in brightness.raw_to_ldr. Wer die Hardware lieber umbaut (LDR nach 3V3, R2 nach GND), setzt das Flag auf False.

Die Schwellen sind am Aufbau gemessen, aber am Schreibtisch, nicht in der Sternwarte. Vor dem Echteinsatz dort bei Tag und Nacht gegenprüfen — deshalb bleibt with_ldr in run_esp32.main vorerst auf False.

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

  • RS232-Strecke ESP32 → MAX3232 → Anzeige bestätigt (2026-07-27). Das war das letzte ungetestete Kettenglied. Die Anzeige quittiert jedes Telegramm mit Fehlercode 0, die volle Kette (Mock → WLAN → ESP32 → UART1 → MAX3232 → Anzeige) läuft im Sekundentakt ohne Aussetzer. Damit ist die Portierung funktional komplett; offen sind nur noch Betriebsthemen (LDR, Netzwerk, Autostart).
  • 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 bei fester Positionierung auf 6 px (gemessen 27.07., siehe Geometrie und Darstellung). Zwischenzeitlich stand hier 9 — das war am Umbruch abgezählt und traf den Auto-Vorschub (7 px), nicht die Zeichenbreite. Die schmale 1 wirkt 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%