←  Übersicht

Wasserrakete · Funkstrecke · Telemetrie

Wie die Daten vom Himmel kommen

Die Rakete fliegt allein. Alles, was man von ihr erfährt, kommt über eine Funkstrecke, die langsam ist, in nur eine Richtung gleichzeitig arbeitet und keine Fehler meldet. Aus diesen Beschränkungen ergibt sich fast jede Entscheidung in diesem Kapitel.

Kapitel 1

Drei Beschränkungen, aus denen alles folgt

Bevor irgendein Protokoll Sinn ergibt, muss man wissen, womit man es zu tun hat. Das Funkmodul ist ein LoRa-Modul, und drei seiner Eigenschaften bestimmen den gesamten Entwurf:

EigenschaftBedeutung in der Praxis
Langsam Etwa 3,5 Pakete pro Sekunde. Jedes Byte kostet Sendezeit, also ist jedes Feld im Paket eine Entscheidung.
Halbduplex Das Modul kann entweder senden oder empfangen, nie beides. Wer zu viel sendet, hört nichts mehr — das war die Ursache von zwei Ausfällen an einem einzigen Tag.
Ohne eigene Fehlerprüfung Das Modul meldet CRC:0 — seine eingebaute Prüfsumme ist abgeschaltet und lässt sich laut Datenblatt nicht einschalten. Ein gestörtes Paket kommt also an, nur eben falsch. Die Prüfung muss die Anwendung selbst machen.

Warum LoRa und nicht WLAN oder Bluetooth?

LoRa tauscht Geschwindigkeit gegen Reichweite. WLAN überträgt millionenfach mehr Daten, aber nur über Meter. LoRa schafft je nach Bedingungen Kilometer — bei einer Datenrate, die man in Bytes pro Sekunde zählt.

Für eine Rakete ist das der richtige Handel: Man braucht keine Videoübertragung, sondern Position und Zustand — und man braucht sie auch dann noch, wenn die Rakete weit weg oder im Gebüsch gelandet ist.

Kapitel 2

Was gesendet wird

Über dieselbe Funkstrecke laufen drei verschiedene Arten von Nachrichten. Dass sie sich einen Kanal teilen, ist die Quelle fast aller Schwierigkeiten in diesem Kapitel.

1. Der Beacon — der Herzschlag

Mehrmals pro Sekunde sendet die Rakete ihren Zustand: Flugphase, Höhe, Geschwindigkeit, GPS-Position, Lage im Raum, eine laufende Nummer.

Zustand 1B Zeit 4B Höhe 4B Geschw. 4B GPS 8B Lage 16B Nr. 2B CRC 1B

50 Bytes im Flug — im Vorstart 54, weil dann zusätzlich der Füllstand des Flugspeichers mitgeschickt wird.

Warum die laufende Nummer wichtiger ist, als sie aussieht

Zwei Bytes für einen simplen Zähler wirken verschwenderisch. Sie sind aber das Einzige, womit sich Paketverlust überhaupt messen lässt: Kommt nach Nummer 41 die Nummer 43, weiß man, dass genau eines fehlt.

Ohne diesen Zähler könnte man nur sagen „es kommen weniger Pakete an, als ich erwarte“ — und wüsste nicht, ob sie verlorengingen oder ob die Rakete langsamer sendet. Diese Unterscheidung entscheidet, ob man ein Funkproblem oder ein Softwareproblem sucht.

2. Rohdatenrahmen — die Versicherung

Zusätzlich werden unverarbeitete Sensormessungen gesendet: Beschleunigung, Drehrate, Druck, Temperatur — genau so, wie die Sensoren sie geliefert haben, ohne jede Filterung.

Wozu? Der Flugspeicher zeichnet dasselbe in voller Auflösung auf — aber nur, wenn man die Rakete wiederfindet. Landet sie im Baum, im See oder im Nachbargrundstück, sind die per Funk übertragenen Stichproben das Einzige, was übrig bleibt. Und weil sie roh sind, kann man mit ihnen später auch ganz andere Algorithmen ausprobieren, als damals im Flugrechner liefen.

3. Kommandos — die einzige Richtung von unten nach oben

Vier Befehle: Lebenszeichen abfragen, Status abfragen, Flugspeicher löschen (zweistufig bestätigt), und die Rakete entschärfen.

Was es ausdrücklich NICHT gibt

Keinen Befehl zum Scharfschalten und keinen zum Zünden. Das ist eine festgehaltene Entscheidung, keine fehlende Funktion.

Entschärfen macht das System sicherer, Scharfschalten gefährlicher — also werden die beiden ungleich behandelt, obwohl sie technisch fast identisch wären. Ein Funkkanal kann nicht prüfen, ob ein Mensch neben der Rakete steht. Ein physischer Schalter beantwortet das von selbst.

Kapitel 3

Das schwierigste Problem: Wo hört ein Paket auf?

Ein Funkempfänger bekommt keinen Strom von Paketen, sondern einen Strom von Bytes. Die Pakete darin muss er selbst wiederfinden. Das klingt trivial und ist es nicht.

Der erste Ansatz: an Sendepausen erkennen

Ursprünglich wurden Pakete an Funkstille getrennt: 50 Millisekunden Ruhe bedeuten „Paket zu Ende“. Dieser Wert war gemessen, auf echter Hardware, und er funktionierte über ein Jahr lang zuverlässig.

Und dann brach er von einem Tag auf den anderen

Mit den zusätzlichen Rohdatenrahmen war der Kanal ausgelastet. Die Pakete kamen lückenlos hintereinander — die Pausen traten schlicht nicht mehr auf.

Eine echte 60-Sekunden-Aufnahme dekodierte null Pakete. Sie kam als zwei Klumpen von 5374 und 2746 Bytes an. Der Flugrechner sendete die ganze Zeit einwandfrei; die Bodenstation hätte eine tote Verbindung angezeigt.

Die Lehre: Eine Regel, die davon abhängt, dass der Sender Pausen macht, versagt genau dann, wenn es geschäftig wird — also wenn die Daten am wichtigsten sind.

Der zweite Ansatz: an der Struktur erkennen

Statt auf Stille zu warten, durchsucht der Empfänger den Bytestrom nach Struktur: bekannte Startbytes, bekannte Längen, stimmende Prüfsummen. Das hängt von keinem Zeitverhalten ab.

Dabei zeigte sich ein zweites, subtileres Problem — und es ist das lehrreichste dieser ganzen Seite.

Eine Prüfsumme ist kein Namensschild

Die Prüfsumme hier ist 8 Bit lang. Das heißt: Eine zufällige Bytefolge besteht sie mit einer Wahrscheinlichkeit von etwa 1 zu 256.

Prüft man sie einmal pro Paket, ist das völlig unerheblich. Durchsucht man aber einen Bytestrom und prüft an jeder Position, hat man hunderte Versuche — und Treffer werden zur Regel statt zur Ausnahme.

Gemessen: In einem Teststrom mit 6 echten Paketen wurden 33 Stellen als gültig erkannt, davon 27 falsch. Die erste Fassung des Scanners fand so 11 Beacons in einem Strom mit 6 — und danach war alles versetzt.

Die Lösung: die Aufteilung wählen, die am meisten erklärt

Der Empfänger nimmt nicht den ersten Treffer. Er betrachtet den ganzen Puffer und wählt diejenige Zerlegung in Pakete, die die meisten Bytes erklärt.

Warum das funktioniert: Ein Fehltreffer überlappt fast immer das nächste echte Paket. Er verhindert also, dass es erkannt wird, und verliert dadurch — er erklärt weniger Bytes als die richtige Zerlegung. Es braucht keine Regel darüber, welcher Kandidat „besser aussieht“; die Rechnung entscheidet.

Der Ansatz dazwischen, der auch falsch war

Zwischen den beiden stand noch ein dritter Versuch: „Akzeptiere ein Paket nur, wenn dahinter wieder ein gültiges beginnt.“ Das beseitigt die Fehltreffer zuverlässig.

Es wirft aber jedes Paket weg, das kurz vor einer Funkstörung ankommt — denn dahinter kommt dann nichts Gültiges mehr. Also genau die Pakete, die am wertvollsten sind: die letzten vor einem Verbindungsabriss, in großer Höhe, am Rand der Reichweite. Verworfen.

AnsatzFehltrefferPaket vor StörungErgebnis
Sendepausenbricht bei Auslastung völlig zusammen
erster gültiger Treffervielebehalten11 Beacons aus einem Strom mit 6
nur wenn eins folgtkeineverworfenverliert die wertvollsten Pakete
meiste Bytes erklärtkeinebehalteneingesetzt

Der Beweis, dass es stimmt

90 Sekunden echter Funk: 259 Beacons und 167 Rohdatenrahmen, null Prüfsummenfehler, null übrige Bytes. Entscheidend ist aber etwas anderes: Die laufenden Nummern gingen von 3649 bis 3907 — ohne eine einzige Lücke.

Das ist der stärkstmögliche Nachweis. Ein verlorenes Paket risse die Folge auf. Ein Fehltreffer schöbe eine zusätzliche Nummer ein. Weder noch.

Kapitel 4

Halbduplex: warum zu viel Senden das Hören verhindert

Das Funkmodul kann nicht gleichzeitig senden und empfangen. Es speichert zwischen, was es noch nicht abgestrahlt hat, und arbeitet das ab.

Flugrechnergibt Daten ab
Warteschlangeim Funkmodul
Senden
niemals
gleichzeitig
EmpfangenKommando von unten
Solange gesendet wird, ist Empfang unmöglich. Wer dem Modul dauerhaft mehr gibt, als es abstrahlen kann, kommt nie wieder in den Empfangsmodus.

Gibt man dem Modul dauerhaft mehr, als es abstrahlen kann, wächst die Warteschlange ohne Ende. Es sendet dann immer — und kommt nie wieder in den Empfangsmodus.

Genau das passierte

Im Vorstartzustand ist der Beacon absichtlich gedrosselt (gemessen 0,3 Pakete pro Sekunde). Die neuen Rohdaten mit 2 Hz wurden damit praktisch zur gesamten Sendelast.

Der Zähler im Flugrechner machte es eindeutig: „Kommandos empfangen = 10″ — und diese Zahl stand fest, während 150 Befehle gesendet wurden. Anfangs war die Warteschlange leer, deshalb kamen die ersten zehn durch. Danach nie wieder.

Die Lösung ist eine Aufteilung nach Flugphase

Sie ist deshalb kein Kompromiss, weil die beiden Bedürfnisse zeitlich getrennt sind und in entgegengesetzte Richtungen zeigen:

  • Am Boden zählt der Rückkanal — Log löschen, Status abfragen, entschärfen. Rohdaten per Funk sind hier fast wertlos, weil die Rakete vor einem liegt und der Speicher dasselbe in voller Auflösung aufzeichnet.
  • Im Flug ist der Rückkanal aus Sicherheitsgründen ohnehin abgeschaltet, und die Funk-Rohdaten werden zur einzigen Kopie, die einen Verlust der Rakete überlebt.

Also bekommt jede Phase genau das, was sie braucht. Zusätzlich wird am Boden ein festes Zeitfenster reserviert, in dem gar nichts gesendet wird — 400 von 2000 Millisekunden, in denen das Modul garantiert zuhört.

Nachtrag am selben Abend: das reservierte Fenster war nicht die Lösung

Der Absatz darüber beschreibt, was damals eingebaut wurde. Am Abend des 29. August wurde es nachgemessen, und es hält nicht. Warum, steht im nächsten Kapitel — es ist der sauberste Messfehler dieses Projekts.

Kapitel 5

Wie eine Messreihe drei Erklärungen stützte, die alle falsch waren

Der Rückkanal blieb unzuverlässig. Mal 100 %, mal 75 %, mehrfach 0 % — auf derselben Hardware, ohne dass sich etwas geändert hätte. Eine Messreihe über 45 Minuten zeigte sogar ein auffälliges Muster: etwa alle zwölf Minuten fiel die Quote auf exakt null und erholte sich wieder.

MinuteerfolgreichQuote
0,88/2040 %
6,90/200 %
12,613/2065 %
18,70/200 %
24,58/2040 %
30,70/200 %
36,216/2080 %

Nullstellen bei 6,9 / 18,7 / 30,7 Minuten — Abstände von 11,8 und 12,0 Minuten. Das sieht nach einer Uhr aus. Es war keine.

Die Vermutung, die naheliegend war und sich widerlegen ließ

Der Flugrechner schreibt sein Protokoll auf demselben Kern, der auch das Funkmodul ausliest, und er öffnet und schließt die Datei pro Zeile. Wenn das Dateisystem gelegentlich aufräumt, wäre der Kern für diese Zeit blockiert — und ein Kern, der nicht ausliest, hört keine Befehle.

Also wurde die Dauer jedes einzelnen Schreibvorgangs gemessen. Ergebnis: im schlimmsten Fall 180 Millisekunden, kein einziger über der 500-ms-Schwelle. Zu kurz, um auch nur ein Paket zu kosten. Die Vermutung war falsch, und die Messung hat sie in einem Durchlauf erledigt.

Der eigentliche Fehler: es gab gar keine Periode

Danach wurde systematisch verglichen — immer mit einer Ruhepause vor jedem Block, damit kein Block den Stau des vorherigen erbt. Zuerst die Frage, ob das reservierte Empfangsfenster größer sein muss:

FensterAnteil der ZeitQuote
800 ms40 %80 %
1200 ms60 %0 %
1600 ms80 %0 %
400 ms20 %0 %

Ein größeres Zuhörfenster kann nicht schlechter sein als ein kleineres. Die letzte Zeile ist der Kontrollpunkt und sie erledigt die ganze Tabelle: dieselbe Einstellung wie ein Block, der vorher 80 % erreicht hatte — jetzt null.

Gemessen wurde nicht das Fenster, sondern wie lange das Modul vorher Ruhe hatte. Der erste Block nach einer Pause funktioniert. Danach verklemmt sich das Modul und kommt von allein nicht zurück.

Damit fällt auch eine frühere Tabelle

Dieselbe Zerfallskurve erklärt die berühmte „nicht monotone“ Messreihe zur Beacon-Rate (2,00 Hz 32 %, 1,00 Hz 0 %, 0,67 Hz 0 %, 0,50 Hz 24 %, 0,33 Hz 80 %), die längere Zeit als ungelöstes Rätsel geführt wurde. Sie ist kein Rätsel. Jeder Punkt wurde gegen ein Modul in einem anderen Verklemmungsgrad gemessen. Der Kurvenverlauf ist der Fingerabdruck des Zerfalls, nicht der Beacon-Rate.

Das ist unangenehm, weil auf dieser Tabelle bereits eine Entscheidung aufgebaut worden war. Es ist aber auch der Grund, warum jede Messreihe hier inzwischen einen Kontrollpunkt am Ende hat, der die erste Einstellung wiederholt.

Was tatsächlich den Unterschied macht

Genau eine Größe ändert das Ergebnis reproduzierbar: ob vor dem Start überhaupt Rohdaten gefunkt werden.

PING-Erfolg, drei Blöcke mit Ruhepausen dazwischen
Rohfunk an, Block 1 47 %
Block 2 7 %
Block 3 0 %
Rohfunk aus, Block 1 83 %
Block 2 90 %
Block 3 83 %

Die obere Gruppe ist kein Rauschen um einen Mittelwert, sondern ein Zerfall in eine Richtung. Die untere ist stabil, über mehrere Minuten, mit einer Antwortzeit von 375 Millisekunden im Mittel.

Das Merkwürdige daran

Die Rechnung sagt, das dürfte gar nicht passieren. Auf der Rampe war der Rohfunk bereits auf 1 Paket pro Sekunde gedrosselt, dazu ein Beacon alle drei Sekunden — zusammen etwa 1,3 von rund 3,5 Paketen pro Sekunde, die der Kanal trägt. Das ist reichlich Luft.

Es verklemmt sich trotzdem. Die Auslastung allein erklärt es also nicht; es liegt am Verhalten des Funkmoduls, das sich nach einer Weile Dauerbetrieb nicht mehr in den Empfang zurückholt. Das ist bislang beobachtet, nicht erklärt.

Die Entscheidung: auf der Rampe gar kein Rohfunk

RAW_TELEMETRY_RATE_PREFLIGHT_HZ steht jetzt auf 0. Vor dem Abheben werden keine Rohdaten mehr gefunkt.

Verloren geht dabei nichts, was jemand haben will. Der Flugspeicher zeichnet die Rohdaten am Boden weiterhin in voller Auflösung auf — sie werden nur nicht zusätzlich an einen Empfänger gefunkt, der zwei Meter neben der Rakete liegt. Im Flug bleibt der Rohfunk unverändert, also auch die einzige Kopie, die einen Verlust der Rakete überlebt.

Der Grund, warum das keine Geschmacksfrage ist: Fernentschärfen ist eine Sicherheitsfunktion. Eine Sicherheitsfunktion, die nach ein paar Minuten Warten aufhört zu funktionieren, ist schlimmer als eine, die man nie versprochen hat.

Kapitel 6

Der Fehler, der eine funktionierende Verbindung tot aussehen ließ

Der lehrreichste Vorfall des Tages, weil er zeigt, wie man sich mit echten Messwerten selbst täuscht.

Nach dem Einbau des Entschärf-Befehls schien der Rückkanal völlig tot: 0 von 15 Versuchen, 0 von 25, der Entschärf-Befehl in 30 Versuchen unbeantwortet. Zwei ausführliche Erklärungen wurden auf diesen Zahlen aufgebaut. Beide waren falsch.

Der Schritt, der es aufklärte

Statt weiter am Boden zu messen, wurde der Flugrechner gefragt. Sein eigener Zähler sagte:

Kommandos empfangen = 117  ·  Antworten gesendet = 103

Die Rakete hatte die ganze Zeit geantwortet. Der Fehler lag in der Bodenstation.

Die Funktion, die eine Antwort im Puffer sucht, gab den ersten gültigen Rahmen zurück und hörte dann auf. Und wie in Kapitel 3: Bei 8-Bit-Prüfsumme und einem Puffer voller Telemetrie gibt es Zufallstreffer. Saß so einer vor der echten Antwort, verdeckte er sie — und zwar dauerhaft, weil jeder weitere Aufruf denselben Fehltreffer zuerst fand.

Nach der Korrektur — gezielt nach dem erwarteten Antworttyp suchen statt nach „irgendeinem Rahmen“ — ergaben dieselben 15 Versuche 11 Antworten, mit einer mittleren Laufzeit von 0,41 Sekunden.

Und das Werkzeug, das den Irrtum scheinbar bestätigte

Ein separates, seit Monaten bewährtes Prüfwerkzeug meldete ebenfalls „keine gültige Antwort“. Das wirkte wie eine unabhängige Bestätigung — war aber keine: Es enthielt eine Kopie derselben Funktion mit demselben Fehler.

Zwei Werkzeuge, die denselben Code teilen, sind eine Messung, nicht zwei.

Dieselbe Fehlerfamilie schlug an einem einzigen Tag dreimal zu: bei der Paketgrenzen-Erkennung, bei der Beacon-Erkennung und bei den Kommandoantworten. Deshalb steht sie jetzt als allgemeine Regel in den Projektnotizen: Eine kurze Prüfsumme ist kein Namensschild. Wer sucht, muss weitersuchen statt dem ersten Treffer zu glauben.

Kapitel 7

Wo es jetzt steht

GemessenWert
Beacons über 90 s, Sequenzlücken259 / 0
Prüfsummenfehler im selben Zeitraum0
Kommandos pro Versuch, 4 min nach Neustart100 %
Kommandos pro Versuch, nach 35 min Laufzeit43-63 % — ungeklaert
Antwortzeit, Median0,41 s
Paketverlust im Dauerlauf~5 %

Was offen bleibt

  • Die Kommandozuverlässigkeit sinkt mit der Laufzeit — ungeklärt. Vier Minuten nach einem Neustart kommen 100 % der Befehle durch. Nach 35 Minuten Dauerbetrieb nur noch 43 bis 63 %, bei unveränderter Einstellung und unverändert sauberem Empfang in Gegenrichtung (638 Beacons, null Prüfsummenfehler).

    Das passt zu einem Muster, das an einem einzigen Tag mehrfach auftrat: Nach einem Reset geht es, mit zunehmender Sendedauer wird es schlechter. Der Verdacht fällt damit auf die Warteschlange im Funkmodul und nicht auf das Protokoll — belegt ist das aber nicht. Solange es nicht eingegrenzt ist, ist jede einzelne Prozentzahl hier nur eine Momentaufnahme von etwas, das sich bewegt, auch die 100 %.
  • Die Reichweite ist nie gemessen worden. Die Sendeleistung wurde nach einem echten Absturz des Flugrechners von 22 auf 10 dBm gesenkt — das sind grob drei Viertel weniger Reichweite. Wie weit es damit noch trägt, weiß niemand. Das muss vor einem Flug geklärt werden, bei dem verlorene Telemetrie eine verlorene Rakete bedeutet.
  • Alles wurde auf dem Tisch gemessen, über wenige Meter, ohne Hindernisse und ohne Bewegung.
  • Es gibt keine Fehlerkorrektur, nur Fehlererkennung. Ein gestörtes Paket wird erkannt und verworfen, nicht repariert. Bei ~5 % Verlust und mehreren Paketen pro Sekunde ist das vertretbar — bei schlechterer Verbindung wäre eine Korrektur der nächste sinnvolle Schritt.
Anhang

Begriffe

Telemetrie
Messwerte, die von einem entfernten Gerät zu einer Bodenstation übertragen werden.
Halbduplex
Übertragung, bei der immer nur eine Richtung gleichzeitig möglich ist — wie ein Funkgerät, bei dem man eine Sprechtaste drückt.
Prüfsumme (CRC)
Eine kurze Zahl, aus dem Paketinhalt berechnet und mitgeschickt. Stimmt sie beim Empfänger nicht, wurde etwas verfälscht. Sie erkennt Fehler, sie behebt sie nicht.
Sync-Bytes
Ein festes Erkennungsmuster am Paketanfang. Es sagt „hier könnte etwas beginnen“ — nicht mehr, weshalb die Prüfsumme zusätzlich nötig ist.
Sendezeit (Airtime)
Wie lange das Modul für ein Paket den Kanal belegt. Die eigentlich knappe Ressource — nicht die Datenmenge.
Beacon
Eine regelmäßig gesendete Statusmeldung, die niemand bestätigen muss. Sie geht raus, ob jemand zuhört oder nicht.
Protokoll im Detail: docs/Telemetry_Protocol.md. Empfangslogik: groundstation/transport/live_source.py. Verwandte Erklärungen: docs/Filter_Erklaert.html und docs/Zustandsautomat_Erklaert.html.

Schreiben Sie einen Kommentar