Ein Frontpanel für den USB-Empfänger
Der USB-Sprachempfänger funktioniert, sieht aber aus wie ein generischer GRC-Flowgraph — Regler und Spektrumanzeigen, kein Empfangsgerät. Dieser Artikel sammelt, womit sich das ändern lässt.
Der USB-Sprachempfänger für 144,300 MHz demoduliert korrekt, sieht aber wie jeder andere GRC-Flowgraph aus: Schieberegler übereinander, zwei Spektrumplots, fertig. Ein echtes Empfangsgerät hat ein S-Meter, eine Signalanzeige, ein Bedienfeld mit fester Anordnung. Dieser Artikel bestandsaufnimmt, was GNU Radio Companion dafür von Haus aus mitbringt, und was jenseits davon möglich ist — als Grundlage für die spätere Umsetzung.
1. Was GNU Radio Companion nativ mitbringt
Neben den bereits im Empfänger genutzten Elementen (QT GUI Range-Schieberegler, QT GUI Freq Sink-Spektrumplots) bringt GRC 3.10 eine ganze Reihe weiterer QT-Widgets mit, die deutlich mehr nach Empfangsgerät aussehen:
| Block | Aussehen | Typischer Einsatz im Empfänger |
|---|---|---|
QT GUI Dial Gauge |
kreisförmige Anzeige mit gefülltem Bogen | S-Meter (Signalstärke) |
QT GUI Level Gauge |
Balkenanzeige (Fortschrittsbalken-Stil), vertikal oder horizontal | Aussteuerungsanzeige, alternative S-Meter-Form |
QT GUI LED Indicator |
farbiger Kreis, an/aus | „Signal vorhanden" bzw. Squelch-Status |
QT GUI Dial (Dial Control) |
Drehknopf als Eingabeelement | Lautstärke oder Feinabstimmung, statt Schieberegler |
QT GUI Toggle Switch / Toggle Button |
Kippschalter-Optik | Ein/Aus-artige Funktionen (z. B. Squelch aktivieren) |
QT GUI Number Sink |
digitale Zahlenanzeige | Frequenz-Digitalanzeige |
QT GUI Tab Widget |
Reiter/Tabs | mehrere „Seiten" wie bei einem echten Gerätemenü (Hauptbedienung / Spektrum / Einstellungen) |
QT GUI App Background |
Hintergrundbild/-farbe für das gesamte Fenster | Gehäusegrafik hinter den Bedienelementen |
Alle Anzeige-Widgets (Dial Gauge, Level Gauge, LED) haben eine feste Farbpalette (14 benannte Farben wie green, amber fehlt allerdings — am nächsten kommt orange/yellow), keine freien Hex-Werte — für ein grobes Retro-Empfänger-Design reicht das meist, für ein exaktes Markenlayout nicht.
2. Live-Werte in die Anzeige bekommen
Dial Gauge und Level Gauge erwarten ihren Wert nicht als Signal-Stream, sondern als GRC-Variable oder Message — das Signal muss also erst in eine periodisch aktualisierte Zahl umgewandelt werden. Das Standardmuster dafür kombiniert zwei Blöcke:
Probe Avg Mag^2(analog.probe_avg_mag_sqrd_f) hängt am Signalpfad und stellt eine.level()-Methode bereit, die die aktuelle (geglättete) Signalleistung zurückgibt.Function Probe(variable_function_probe) ruft diese Methode in einem eigenen Thread mit fester Rate (z. B. 10 Hz) ab und schreibt das Ergebnis in eine GRC-Variable — genau diese Variable trägt man dann alsvaluein den Dial Gauge ein.
sdr-hintergrund.png als Fenster-Hintergrund — kompiliert fehlerfrei und läuft ohne Laufzeitfehler. Auszug aus dem von grcc generierten Code:
self.qtgui_ledindicator_0 = qtgui.GrLEDIndicator('Signal', "green", "red", level_var > 0.05, 40, 1, 1, 1, self)
...
bkgnd = "background-image: url(" + '/pfad/zu/sdr-hintergrund.png' + "); background-repeat: repeat_n; background-position: center;"
self.setStyleSheet(styleSht)
...
_qtgui_dialgauge_0_lg_win = qtgui.GrDialGauge('S-Meter', "green", "black", "white", 0, 1, 150, 1, isFloat, True, True, self)
self.qtgui_ledindicator_0 = qtgui.GrLEDIndicator('Signal', "green", "red", level_var > 0.05, 40, 1, 1, 1, self)
...
bkgnd = "background-image: url(" + '/pfad/zu/sdr-hintergrund.png' + "); background-repeat: repeat_n; background-position: center;"
self.setStyleSheet(styleSht)
...
_qtgui_dialgauge_0_lg_win = qtgui.GrDialGauge('S-Meter', "green", "black", "white", 0, 1, 150, 1, isFloat, True, True, self)
Der LED-Zustand (level_var > 0.05) wird dabei direkt als Python-Ausdruck in den Parameter eingetragen — GRC übernimmt beliebige Ausdrücke, nicht nur einfache Variablennamen.
3. Globales Reskinning: Stylesheet und Hintergrundbild
Zwei unabhängige Hebel für den Gesamteindruck:
qt_qss_theme(Parameter desOptions-Blocks, bislang in unseren Projekten leer): Pfad zu einer externen.qss-Datei (Qt Style Sheets, syntaktisch an CSS angelehnt) — damit lassen sich Farben, Schriftarten und Rahmen aller Widgets der Anwendung auf einen Schlag umstellen, z. B. auf ein dunkles Thema mit heller Digitalanzeige-Schrift.QT GUI App Background: setzt gezielt ein Hintergrundbild (und/oder eine Hintergrundfarbe) für das gesamte Fenster — genau der Mechanismus, mit dem sich eine Gehäusegrafik hinter die Bedienelemente legen ließe. Für den USB-Empfänger böte sich unser bereits vorhandenessdr-hintergrund.pngals Ausgangsmaterial an.
4. Layout: GUI Hint und Tab Widget
Jedes QT-Widget hat einen GUI Hint-Parameter der Form [tab_id@tab_index]: [row, col, row_span, col_span] — exakt damit ist im Empfänger bereits die feste Anordnung der beiden Spektrumplots (0,0,1,2 bzw. 1,0,1,2) gesetzt. Mit QT GUI Tab Widget lässt sich zusätzlich in mehrere Reiter gliedern — z. B. ein Reiter „Empfang" mit S-Meter/LED/Reglern und ein separater Reiter „Spektrum" mit den Frequenzanzeigen, näher am Bedienkonzept eines echten Empfängers als eine einzige, immer volle Fläche.
5. Grenzen der nativen QT-Widgets
- Feste Formen: Der Dial Gauge zeichnet einen gefüllten Bogen, keine frei gestaltbare Zeigernadel-Grafik — für einen klassischen Zeiger-S-Meter-Look reicht das nicht.
- Begrenzte Farbpalette: 14 benannte Farben, keine beliebigen Hex-/RGB-Werte in den Standardparametern.
- Ein Hintergrundbild fürs ganze Fenster, nicht pro Widget — einzelne Regler lassen sich nicht individuell mit eigener Grafik hinterlegen.
- Kein Vektor-/SVG-Rendering der Bedienelemente selbst — es bleiben Qt-Standardwidgets mit angepassten Farben, kein eigenes Icon-/Skin-System.
6. Alternativen jenseits von GRC
| Ansatz | Gestaltungsfreiheit | Aufwand | Anmerkung |
|---|---|---|---|
| Eigene PyQt5/PySide-App über ZMQ | hoch (beliebige Widgets, SVG, eigene Zeigergrafiken) | mittel | Präzedenzfall bereits im eigenen Repo: der DCF77-ZMQ-Client empfängt Werte von einem GRC-Flowgraph und stellt sie in einer komplett eigenen PyQt5-Oberfläche dar — dasselbe Muster ließe sich auf den USB-Empfänger übertragen |
| Web-Frontend (Browser, HTML/CSS/SVG/Canvas) über WebSocket-Bridge | sehr hoch (CSS-Animationen, responsives Design) | hoch | erfordert einen dauerhaft laufenden Backend-Prozess, der die Werte per WebSocket an den Browser weiterreicht |
| Kivy statt Qt | hoch, moderneres/animierbares Widget-System | mittel bis hoch | eigenständige App, GRC nur noch als reine Signalverarbeitungs-Bibliothek genutzt, keine GRC-generierte Oberfläche mehr — Schritt 1 bereits umgesetzt: Kivy-Frontpanel |
| Fertige SDR-Konsolen (SDR++, GQRX, CubicSDR) | keine eigene — vorgegebene Oberfläche | keiner | kein eigener Flowgraph mehr dahinter, nur als Vorbild/Inspiration relevant |
7. Empfehlung für die Umsetzung
Zwei sinnvoll trennbare Ausbaustufen:
- Schneller Weg, native QT-Widgets: App-Background mit Gehäusegrafik, Dial Gauge als S-Meter (gespeist über Probe + Function Probe wie in Abschnitt 2), LED-Indikator für den Squelch-Status, Tab Widget zur Gliederung — alles direkt im bestehenden
ssb_usb_144300.grcergänzbar, keine neue Laufzeitumgebung nötig. - Aufwendiger, aber freier: eigene ZMQ-App — der Empfänger sendet Messwerte (Signalpegel, Squelch-Status, Frequenz) per ZMQ, eine separate PyQt5-Anwendung nach dem Vorbild des DCF77-Displays zeichnet ein vollständig frei gestaltetes Empfänger-Frontpanel, inklusive echter Zeigernadel-Grafik.
- Dritter Weg, schrittweiser Umbau in Kivy — GRC bleibt nur noch für die reine Signalverarbeitung im Einsatz, die komplette Oberfläche wird Widget für Widget in Kivy nachgebaut. Schritt 1 (Frequenzanzeige + Spektrum) ist bereits umgesetzt und dokumentiert im eigenen Artikel Kivy-Frontpanel: Frequenzanzeige + Spektrum — dort insbesondere Abschnitt 2 für die Kommunikation zwischen GRC und Kivy im Detail.
USB-Sprachempfänger für 144,300 MHz
Der Flowgraph, der dieses Frontpanel bekommen soll.
Kivy-Frontpanel: Frequenzanzeige + Spektrum
Schritt 1 des Kivy-Umbaus, bereits umgesetzt — inklusive Detailerklärung der GRC-Kivy-Kommunikation.
ZeroMQ-Schnittstelle
Das Muster (GRC → ZMQ → eigene PyQt5-App), das bereits beim DCF77-Projekt für eine freie Anzeige genutzt wurde.