Ergebnis 1 bis 13 von 13

Thema: Raspberry Pi POCSAG Encoder/Sender (Python Script)

  1. #1
    Registriert seit
    01.08.2016
    Beiträge
    13

    Raspberry Pi POCSAG Encoder/Sender (Python Script)

    HeyHo liebe Funkmeldegemeinde! :)

    Ich war ja bisher noch nicht so oft auf dem Forum hier aktiv und habe dafür jetzt etwas (hoffentlich) umso interessanteres für Euch.

    Ich arbeite momentan daran, meinen Raspberry Pi (3 B+) zu einem POCSAG Sender umzubauen, das ganze natürlich nur bis 10mW und im 433MHz Bereich. Damit könnte man sich dann einige Sachen zu Hause zuspielen. Wenn das Telefon geht oder jemand an der Tür klingelt beispielsweise... oder Wetterwarnungen vom DWD für das Gebiet in dem man wohnt.

    Das klingt an sich erstmal ziemlich simpel, aber nach einiger Recherche und einigen Versuchen habe ich festgestellt, dass es zum einen sehr schwierig ist, nützliche Encoder für den Pi zu finden und zum anderen, Melder für diesen Frequenzbereich. Also habe ich mich mal an etwas ran gesetzt.

    Die letzten Tage habe ich mich mit einem Python-Script beschäftigt, das einen String einliest, diesen mittels POCSAG-Protokoll codiert und die Signale über einen Pin ausgibt. Das hat nach vielen Stunden Arbeit ganz gut funktioniert.
    Das Script an sich ist fertig. Es beinhaltet die folgenden Arbeitsschritte (vereinfacht):
    - String per 7-bit Code Zeichen für Zeichen Umwandeln
    - Frames erstellen inkl. Info-Bit, Checksumme und Parität
    - leere Frames mit Idlewörtern füllen
    - Adresswörter erstellen
    - Batches erzeugen aus 8 Frames mit Synchronwörtern
    - Präambel voranstellen
    - der entstandene String aus 0en und 1en wird schon mit der vorgegebenen Baudrate auf einen beliebigen GPIO-PIN ausgegeben.


    >>>>Das Script hänge ich Euch bei Gelegenheit mal noch hier in den Beitrag rein!<<<<


    Um dieses Signal nun zu senden bin ich aktuell auf der Suche nach einem 433MHz Sendemodul, welches FSK für die Übertragung nutzt und einen Frequenzhub von 4,5kHz besitzt. Die meisten Module nutzen leider ASK, und wenn es sich doch um ein FSK Modell handelt, wird der Frequenzhub leider nie vom Verkäufer angegeben. Bei Nachfrage stellt man dann auch oft fest, dass die Verkäufer selten Ahnung davon haben und können mit Frequenzhub nichts anfangen... das erschwert die Suche natürlich...

    Letztlich bin ich bei meiner Suche nach einem Melder auf folgende Seite gestoßen:
    https://www.rufsysteme-webshop.de/we...a-pager-1.html
    Das sieht erst einmal vielversprechend aus. Das ist das einzige Modell das ich bisher gefunden habe, welches auf die Frequenz 433,92MHz abgestimmt werden kann. Außerdem ist er laut Verkäuferangaben fähig, Textnachrichten zu empfangen. Also nicht wie diese ganzen billig-Pager für Personenrufsysteme, die nur piepen können.
    Zusätzlich habe ich bei der Firma Alphapoc mal angefragt, ob man deren Pager (z.B. die Reihe 601) auf die besagte Frequenz programmieren kann (die müssten dann ein spezielles Quarz einsetzen). Bin mir aber fast schon sicher, dass ich da eine Absage erhalten werde.

  2. #2
    Registriert seit
    10.12.2001
    Beiträge
    6.342
    Servus,

    Nützliches für Dich: https://hampager.de/dokuwiki/doku.php?id=raspager

    Gruß
    Alex
    Zitat Zitat von Sir Quickly (Irgendwie und sowieso)
    Dahoam is do wos Gfui is.

  3. #3
    Registriert seit
    01.08.2016
    Beiträge
    13
    Zitat Zitat von Quietschphone Beitrag anzeigen
    Servus,

    Nützliches für Dich: https://hampager.de/dokuwiki/doku.php?id=raspager

    Gruß
    Alex
    Interessant, das habe ich wohl übersehen bei meiner Suche. Ist Prinzipiell genau das was ich wollte.
    Ich werd mich mal damit auseinander setzen.

    Das Script habe ich Euch mal beigefügt. Es handelt sich um eine Python-Datei (gezipped).
    Bitte beachtet, dass ich kein Profi in der Programmierung bin, und dass man das Script noch wesentlich effizienter und kürzer halten könnte. Das war aber auch nicht das Ziel. Ich wollte ein Script erstellen mit möglichst vielen Erklärungen und Kommentaren, um den prinzipiellen Aufbau zu verstehen.

    Ihr könnt das Script gerne testen, falls einer die Möglichkeit hat auch mal per Funk. Denn ich bin noch nicht dazu gekommen, die Richtigkeit des entstandenen Signales zu überprüfen. Ich hab's mal mit einem Lautsprecher angehört und es klang sehr nach POCSAG. :D


    -EDIT-
    Was ich noch vergessen habe zum Script:
    Den String, den Ihr senden wollt, könnt Ihr ganz unten in der vorletzten Zeile definieren bei "strAlarmierung = "…" ". Die Funktion Funkruf() setzt dann die Codierung und die Ansteuerung des GPIO-Pins um.
    Das Script könnt Ihr über die Konsole mit "sudo python Funkruf.py" starten.

    Falls Ihr Fehler mit dem Script entdeckt, diese bitte melden. Dann kann ich das Script anpassen/verbessern/erweitern.

    LG
    Maskey
    Angehängte Dateien Angehängte Dateien
    Geändert von Maskey (05.03.2019 um 10:09 Uhr)

  4. #4
    Registriert seit
    01.08.2016
    Beiträge
    13
    Nochmal kurz zur Info bezüglich RasPager:
    (ich mach mal ausnahmsweise einen Doppelpost, damit die Datei weiter oben bleibt)

    Da die Produkte aktuell nicht lieferbar sind, habe ich mal den Support gefragt. folgende Nachricht kam zurück:

    Zitat Zitat von CJ-Elektronik GmbH
    Hallo Herr [...]

    vielen Dank für Ihre Nachricht. Wir hoffen, dass wir zur Ham Radio Ende Juni fertige RasPager V3 haben werden.

    Wenn Sie noch Fragen haben, wenden Sie sich bitte gerne wieder an mich.

    Mit freundlichen Grüßen
    [...]
    Das wird also noch ein Stück dauern :P

    Aus diesem Grund werde ich trotzdem versuchen, vorerst ein System auf 433,92MHz aufzubauen.

    Bisher kam noch keine Info von Alphapoc...

  5. #5
    Registriert seit
    26.08.2015
    Beiträge
    68
    Code:
    for i in range (intTextlaenge):     #Nachricht in Dualzahlen umwandeln, anhand der laenge jedes Bit einzeln codieren mit hilfe der If-Abfragen
            if strAlarmtext[i] == ' ':
                strInformationsbits = str(strInformationsbits+'0100000')
            elif strAlarmtext[i] == '!':
                strInformationsbits = str(strInformationsbits+'0100001')
            elif strAlarmtext[i] == '"':
            usw.…
    Wenn ich das richtig sehe wandelst du die Zeichen des Textes (Ascii) in Binär um. Ich denke das könnte man vereinfachen:

    Code:
    for i in range (intTextlaenge):
            charOrd = ord(strAlarmtext[i])
            if charOrd > 0:
                     strInformationsbits = str(strInformationsbits + bin(charOrd)
            else:
                    print('Das Zeichen ' + str(strAlarmtext[i]) + 'konnte nicht codiert werden. Es wird zu einem Leerzeichen')
                    strInformationsbits = str(strInformationsbits + '0100000')

    Ist nur eine Grundlegende Idee, nicht getestet und sicher noch ausbaufähig…

  6. #6
    Registriert seit
    01.08.2016
    Beiträge
    13
    Zitat Zitat von scripter Beitrag anzeigen
    Code:
    for i in range (intTextlaenge):     #Nachricht in Dualzahlen umwandeln, anhand der laenge jedes Bit einzeln codieren mit hilfe der If-Abfragen
            if strAlarmtext[i] == ' ':
                strInformationsbits = str(strInformationsbits+'0100000')
            elif strAlarmtext[i] == '!':
                strInformationsbits = str(strInformationsbits+'0100001')
            elif strAlarmtext[i] == '"':
            usw.…
    Wenn ich das richtig sehe wandelst du die Zeichen des Textes (Ascii) in Binär um. Ich denke das könnte man vereinfachen:

    Code:
    for i in range (intTextlaenge):
            charOrd = ord(strAlarmtext[i])
            if charOrd > 0:
                     strInformationsbits = str(strInformationsbits + bin(charOrd)
            else:
                    print('Das Zeichen ' + str(strAlarmtext[i]) + 'konnte nicht codiert werden. Es wird zu einem Leerzeichen')
                    strInformationsbits = str(strInformationsbits + '0100000')

    Ist nur eine Grundlegende Idee, nicht getestet und sicher noch ausbaufähig…
    Das ist zufällig genau das, was mir ein Kumpel heute früh auch schon geraten hat, dem ich das Script gezeigt habe. :D

    Ja, damit könnte man diese ewig langen if-Abfragen einkürzen. Gerade an der Stelle, wo der Binärcode erzeugt wird. Das waren glaube ich insgesamt 96 (!) einzelne else if-Abfragen. Das ist natürlich mit deinem Vorschlag wesentlich besser gelöst. Ich werde es bei Gelegenheit mal einbauen. Danke für den Tipp!

    PS. Für die, die sich das Script anschauen,
    Bitte über die eventuellen Schreibfehler in den Kommentaren hinweg sehen. Da gibt's bestimmt einige zu finden. ;D
    Die wurden nur schnell nebenbei reingeklimpert um die Aktionen zu erläutern.

  7. #7
    Registriert seit
    18.12.2001
    Beiträge
    4.981
    Guude!

    Zwei Punkte:

    1.) Der Sourcecode ist wie ein Fingerabdruck oftmals eine recht individuelle Marke eines jeden Entwicklers. Jeder geht eine Aufgabenstellung etwas anders an, strukturiert seinen Code anders und hat besondere Vorlieben für Sprachkonstrukte. Allen guten Programmierern gemein ist, dass der Code eine gewisse "Schönheit" aufweißt. Und zwar sowohl in messbarer Form (Anzahl Zeile/Methoden, Benennung Variablen, ...), als auch rein subjektiv. Ein guter Programmierer möchte, dass man beim Blick auf seinen Code "Wow" sagt, und das Programm und die Lösungsansätze schnell versteht. Besonders wenn auch noch andere Leute am Code mitarbeiten, ist das nicht nur wünschenswert, sondern absolut notwendig. Niemand möchte "schlechten" oder "hässlichen" Code lesen müssen und dann auch noch versuchen müssen herauszufinden, was der Code eigentlich tut.

    Dein Code sagt über dich aus, dass du absoluter Anfänger bist, und Python als Programmiersprache, bzw. allgemeine Sprachkonstrukte von Programmiersprachen noch nicht richtig verstanden hast. Das ist nicht schlimm, jeder hat mal so angefangen, von daher nimm das bloß nicht als Angriff auf. Meine Bitte an dich wäre nur, ein Gefühl dafür zu entwickeln wann dein Programm "fertig" ist und wann es einen Stand hat, in dem man es veröffentlichen kann. Dein Programm sollte nicht fertig sein wenn es tut was es soll, sondern erst dann, wenn es dabei auch noch "schön" aussieht und möglichst nicht weiter verbessert werden kann. Dann macht es viel mehr Spaß sich mit dir über die eigentliche Funktionalität zu unterhalten und du umgehst dumme Kommentare über deinen Programmierstil. Nicht jeder im Internet ist in der Lage, Kritik nur sachlich zu äußern. Das kann echt demotivieren.

    In deinem Fall schau dir konkret mal deine Variablen "strCodewort01" bis "strCodewort16" an. Da kann man z.B. ein Array daraus machen und vieles der Logik in Schleifen packen. Auch viele If/Else sprechen dafür, dass du an diesen Stellen noch zu "statisch" denkst. Viele Berechnungen oder Entscheidungen lassen sich durch Funktionen oder Lookup-Tabellen vereinfachen. Überleg einfach mal, was jeweils einzelne Gruppen von If/Else gemeinsam haben und versuch das zu verallgemeiner/ zu abstrahieren.


    2.) Wie du im Artikel von Quietschphone lesen konntest, ist die Ansteuerung über die GPIO des Raspberry nicht sinnvoll. Problem ist, dass dein time.sleep(xyz) nicht immer exakt xyz Zeiteinheiten schläft, sondern das mal mehr oder weniger sein kann. Ursache dafür ist das Betriebssystem, welches neben deinem Programm ja auch noch dutzende weitere "gleichzeitig" ausführen muss und dafür ein so genannter "Scheduler" den Prozessor der Raspberry immer unter all den Programmen "verteilen" muss. Das ist ein ganz allgemeines Problem bei "Echtzeit"-Anwendungen, wie das Generieren von genauen Bitraten, in Zusammenhang mit "normalen" Betriebssystemen. Es gibt diverse (und meist ziemlich komplexe) Möglichkeiten das zu lösen. Eine der einfacheren wird in dem Artikel genutzt.

    Gruß Joachim

  8. #8
    Registriert seit
    18.12.2001
    Beiträge
    4.981
    Ein Beispiel:

    Code:
    if strFunktion[0] == '0':           #Funktion in dualzahlen umwandeln
        strFunktionsbits = '00'
    elif strFunktion[0] == '1':
        strFunktionsbits = '01'
    elif strFunktion[0] == '2':
        strFunktionsbits = '10'
    elif strFunktion[0] == '3':
       strFunktionsbits = '11'
    else:
       print('Da ist ein Fehler bei der Umwandlung der Funktion (Schleife) aufgetreten. Bitte nur Ziffern 0,1,2,3 eingeben!')
    Was tut der Code?
    Wandelt die möglichen Subadressen 0-3 in die entsprechende Bitfolge um.

    Was haben alle If-Zweige gemeinsam?
    Wandeln die jeweilige Subadresse in eine Binärzahl um: 0 -> 00, 1 -> 01, 2 -> 10, 3 -> 11

    Vereinfachung
    Umwandlung der Subadresse in Binärzahl generalisieren.

    Code:
    if int(strFunktion) not in range(0, 4):
        raise Exception('Funktion muss zwischen 0 und 3 liegen!')    
    
    strFunktionsbits = format(int(strFunktion), '02b')
    Von 10 auf 3 Zeilen und deutlich übersichtlicher. :-)

    Aber genug Programmiertips, ist ja schließlich kein Python-Forum hier.

    Gruß Joachim

  9. #9
    Registriert seit
    01.08.2016
    Beiträge
    13
    Vielen Dank für Deine sehr konstruktive Kritik, MiThoTyN. Da hast Du natürlich in allen Punkten vollkommen Recht. Deinen Vorschlag werde ich auch bei Gelegenheit im Script abändern.

    Zitat Zitat von MiThoTyN
    Meine Bitte an dich wäre nur, ein Gefühl dafür zu entwickeln wann dein Programm "fertig" ist und wann es einen Stand hat, in dem man es veröffentlichen kann. Dein Programm sollte nicht fertig sein wenn es tut was es soll, sondern erst dann, wenn es dabei auch noch "schön" aussieht und möglichst nicht weiter verbessert werden kann.
    Das Veröffentlichen sollte eigentlich dazu dienen, dass verschiedene Interessenten das Script schon mal in diesem sehr frühen Stadium testen können - im besten Falle auch mal einen Funkruf über einen Transmitter laufen lassen - damit man die Funktionalität überprüfen kann (so eine Art Bugreport, bzw. Bugtracker). Ich bin eben momentan nicht im Besitz eines Senders, sonst hätte ich das schon längst mal in Angriff genommen, ohne ein unfertiges Script zu veröffentlichen.

    Zitat Zitat von MiThoTyN
    2.) Wie du im Artikel von Quietschphone lesen konntest, ist die Ansteuerung über die GPIO des Raspberry nicht sinnvoll. Problem ist, dass dein time.sleep(xyz) nicht immer exakt xyz Zeiteinheiten schläft, sondern das mal mehr oder weniger sein kann. Ursache dafür ist das Betriebssystem, welches neben deinem Programm ja auch noch dutzende weitere "gleichzeitig" ausführen muss und dafür ein so genannter "Scheduler" den Prozessor der Raspberry immer unter all den Programmen "verteilen" muss. Das ist ein ganz allgemeines Problem bei "Echtzeit"-Anwendungen, wie das Generieren von genauen Bitraten, in Zusammenhang mit "normalen" Betriebssystemen. Es gibt diverse (und meist ziemlich komplexe) Möglichkeiten das zu lösen. Eine der einfacheren wird in dem Artikel genutzt.
    Ich habe das ehrlich gesagt schon befürchtet. Dann wäre es ja beispielsweise möglich, den String aus Nullen und Einsen einem Arduino zu übergeben, der sich dann um das Senden kümmert. Der Arduino müsste doch als Mikrocontroller eine gleichbleibende delay-Zeit aufweisen. Liege ich da richtig in der Annahme?

  10. #10
    Registriert seit
    18.12.2001
    Beiträge
    4.981
    Zitat Zitat von Maskey Beitrag anzeigen
    Das Veröffentlichen sollte eigentlich dazu dienen, dass verschiedene Interessenten das Script schon mal in diesem sehr frühen Stadium testen können - im besten Falle auch mal einen Funkruf über einen Transmitter laufen lassen - damit man die Funktionalität überprüfen kann (so eine Art Bugreport, bzw. Bugtracker). Ich bin eben momentan nicht im Besitz eines Senders, sonst hätte ich das schon längst mal in Angriff genommen, ohne ein unfertiges Script zu veröffentlichen.
    Jein. Nette Idee, aber warum sollte jemand anderes mit einem so "unfertigen" Programm testen wollen? Wenn ich dir vier Reifen, ein Lenkrad und ein Satz Schrauben gebe und sage "Hier haste ein Audi A8, kannste schon mal Probe fahren", würdest du auch doof aus der Wäsche gucken.

    Dein Programm an sich "funktioniert" ja auch ohne Transmitter. Wichtig ist, dass die richtige Bitfolge am Ende zur Verfügung steht. Um das Sicherzustellen, baut sich ein guter Programmierer "Mocks" und "Tests". Du könntest z.B. mal per Hand eine Bitfolge für eine Beispiel-POCSAG-Meldung berechnen und dann mit der von deinem Programm vergleichen. Sind beide gleich, tut dein Programm das richtige. Wenn nicht, musst du noch Anpassungen machen. So kannst du ohne Transmitter dein Code so lange verbessern und verschönern, bis er auch wirklich von Jedermann nutzbar ist. Nur dann wird sich auch jemand mit deinem Code auseinander setzen.

    Zitat Zitat von Maskey Beitrag anzeigen
    Ich habe das ehrlich gesagt schon befürchtet. Dann wäre es ja beispielsweise möglich, den String aus Nullen und Einsen einem Arduino zu übergeben, der sich dann um das Senden kümmert. Der Arduino müsste doch als Mikrocontroller eine gleichbleibende delay-Zeit aufweisen. Liege ich da richtig in der Annahme?
    Grundsätzlich ja, aber auch da kommt es auf die Programmierung an. Stichworte sind Interrupts und Timer. Wenn du das einfach nur so mit Sleep und einer großen Schleife baust, wird es auch auf einem Arduino nicht (zuverlässig) funktionieren.
    Wobei sich dann die Frage stellt, warum du den POCSAG Dekoder dann nicht gleich im Arduino programmierst. Dann brauchst du den Umweg über Python und den Raspberry nicht.

    Gruß Joachim

  11. #11
    Registriert seit
    01.08.2016
    Beiträge
    13
    Ich habe soeben eine Rückinfo von Alphapoc erhalten.

    Es ist tatsächlich möglich beispielsweise einen AP601 auf die Sonderfrequenz 433,920 MHz abzustimmen.
    Allerdings ist in diesem Falle die Lieferzeit wesentlich länger.

    Ich hab mal ein schriftliches Angebot angefragt. Mal schauen auf was sich da die Kosten belaufen, bzw. inwiefern sich die Lieferzeiten verzögern.

    LG
    Maskey

  12. #12
    Registriert seit
    01.08.2016
    Beiträge
    13
    Mal ein kurzer Zwischenstand:

    Das Script funktioniert schon mal zuverlässig.
    Um das Synchrone aussenden der Bits zu verbessern, habe ich einen Arduino als Clock Generator "missbraucht", der einfach einen GPIO des Raspberry Pi's mit 1200 Hz ansteuert (Square Signal). Der Pi gibt dann bei jeder fallenden Flanke des Signals das nächste Bit an den Sender weiter und schiebt nach und nach den String durch, bis das letzte Bit erreicht ist.

    Zum Senden habe ich mir von Pollin ein RFM69 bestellt. Dieser wird über Register mit der SPI Schnittstelle programmiert und das Modul kann somit komplett frei nach Belieben angepasst werden, also z.B.
    Frequenz 433,92MHz, Frequenzhub 4,5kHz, 1200b/s, FSK Modulation, Sendemodus aktivieren usw....

    Soweit die Theorie, leider funktioniert das bisher nicht so ganz.
    Ich bekomme das Modul einfach nicht zum Senden... :/

    Kennt sich von Euch jemand mit solchen Sende Modulen aus?
    Hier ist mal ein Link zum Datenblatt:
    https://www.pollin.de/productdownloads/D810800D.PDF

    LG Maskey

  13. #13
    Registriert seit
    01.08.2016
    Beiträge
    13

    Video

    Hier mal der aktuelle Stand in einem Video. Übertragung funktioniert eiwandfrei!

    https://m.youtube.com/watch?v=MfIWmMxX8Ok

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •