Forum: HF, Funk und Felder POCSAG Protokoll


von cmb (Gast)


Lesenswert?

Hallo,

Ich versuche gerade, ein POCSAG Signal mit einem ATMEGA8 zu 
dekodieren/empfangen. Zum Ausweichen habe ich mir noch einen Mega128 
bereitgelegt, falls die Rechenleistung/Speicher nicht reicht.

Nun zu meiner Frage: Ich habe ein Analoges Eingangssignal, wie kann ich 
die Signalflanken für den Controller etwas glätten, bzw. wie sieht die 
Signalverarbeitung allgemein aus - auch im Bezug auf Grundrauschen etc.?
Sollte ich in einem Timeslot besser dreimal messen, um Fehler zu 
erkennen?

Gruß cmb

von Tino N. (tino)


Lesenswert?

Schreib doch bitte ein wenig mehr zu deinem Projekt !
Etwas fertiges möchtest nicht nutzen ?

von cmb (Gast)


Lesenswert?

Hallo,

Einfache Experimente mit ATMega8, um ein POCSAG zu empfangen. Eine 
konkrete Anwendung wollte ich später in einer selbstgebauten 
Wetterstation suchen.

Gruß cmb

von Tino N. (tino)


Lesenswert?

Schau mal hier :
http://www.mikrocontroller.net/attachment/1432/rx-pager.zip

Da ist auch Code dabei,vielleicht holft es dir ja .

Auch die Sendeseite hier :
http://users.rcn.com/carlott/poc_code.zip

Das Ganze ist zwar nicht für den Atmega sondern für PIC`s aber 
vielleicht kannste da ja etwas ableiten .

von cmb (Gast)


Lesenswert?

Hallo,

zwei Punkte gibt es noch, an denen ich Hänge:
Zum einen ist das, den Start zu erkennen (lange 1-0-Folge zum 
initialisieren), diese jedoch unter Rauschen und Fremden Sprachsignalen 
zu erkennen (also er soll nur bei erkannter Startsequenz die Decodierung 
starten, aber nicht bei Sprache oder sowas.

das zweite ist das PLL - wie löse ich das mit dem ATMega am besten? 
Quartz mit abgestimmter Frequenz zur Erzeugung der BAUD verwenden?

gruß

von Christian S. (kruemel)


Lesenswert?

Hallo,

ich hab gerade euren Beitrag hier gefunden.
Wird an der Sache noch gearbeitet oder ist die Sache im Sande verlaufen.
Möchte auch gerne einen Pocsag Decoder auf Atmega8 Basis aufbauen und 
suche zur Zeit die Empfangsgrundlagen, wie ich die Signale in den µC 
reinbekomme und wie die Daten dann weiterverarbeitet werden.

Gruß
Christian

von T. (Gast)


Lesenswert?

Hallo.

Es gibt wohl zwei Ansätze, die sich jeweils von deiner Signalquelle
unterscheiden.

Vermutlich wird es am einfachsten sein, dein analoges Signal per OPV
derart zu übersteuern, das es vom sinus zum rechteck wird, und das dann
recht einfach weiterzuverarbeiten.

von PIC_POCSAG (Gast)


Lesenswert?

Zuerst solltest du das Signal vom Diskriminator aus auf einen
Schmidt Trigger geben um die Signalform zu wahren.

Danach prüfst du auf das vorhandensein der Preambel (0101010101)
und sobald du diese Signalform erkannt hast prüft du BIT-weise die
Änderung bis du das "Startbit" erkennst. Achtung: NRZ Format !

Dazu mußt du nur wissen mit wieviel Baud gesendet wird (Typischerweise
1200 BPS) sonst funktioniert das natürlich nicht.

Das PIC Programm von Dejan ist ein sehr schönes Beispiel wie man genau
so verfährt, leider nicht so dolle Dokumentiert.

von Christian S. (kruemel)


Lesenswert?

Hallo,

vielen Dank für eure Antworten.
Ja wäre das gut dokumentiert, dann könnte man damit auch was anfangen.

Okay ich guck mal ob ich mich da rein denken kann.
Ich möchte gerne 512 Baud dekodieren.

Bei der Schaltung ist immer ein Quarz eingebaut, wieso muss der AVR 
einen externen Quarz bekommen?

Okay Prinzip hab ich verstanden, die 0101 folge is die präamble dann 
folgt das text format jeweils 8 bit pro Zahl oder Buchstabe, ist das 
richtig?

Gruß
Christian

von Roland (r_fischer)


Angehängte Dateien:

Lesenswert?

Hallo Christian,

nein, leider ist das nicht so einfach.

Ich häng dir mal die Beschreibung mit an (englisch) aber sehr gut.

Bei Pocsag wird als erstes BIT nach der Präambel das Frame Synchronword
Übertragen, es beginnt mit einer 1 und Kennzeichnet damit ein 
Adressword.
Es gibt 2 lass es mich mal Controlwords nennen, das Frame synch und das 
Idle Word. Alle anderen mit 1 gekennzeichneten Adresswords sind 
tatsächlich RIC Adressen bzw. System Meldungen an alle RIC. Diese werden 
auch in jedem der 8 Frame's Übertragen da ja die RIC Adresse nicht 
vollständig Übertragen wird (18 BIT von 21) die letzen 3 Bit mußt du aus 
dem Frame ziehen in der das Adressword Übertragen wurde.

Schau dir die DOC an, das ersparrt dir viel Herumprobieren.

Um zu Empfangen gehe ich den Weg der auch Dejan im PIC verfolgt hat.

Bei 512 BPS Dauert ein Bit ==> 1/512 = 0,001953125 Sekunden oder 1,953 
mS
Wenn du Pollen willst solltest du mind. die Doppelte Geschwindigkeit der
Bit's als Abtastrate des Port verwenden. Dejan macht das mit 8 Facher 
Geschwindigkeit (Das bot sich an da er auch noch Softwaremäßig im 
Interrupt
eine 9600 BPS Ausgabe macht da dieser Pic keinen Uart hat).
Also 1,953 mS / 8 => 244,140 uS. Dejan hat den Timer0 nun mit dem 
Zyklustakt bei 4MHz Clock = 1MHz Zyklus direkt verbunden (Prescaler mit 
dem WDT Timer Verbinden = 1:1 für den TMR0). Das war clever.
Nun hat er den TMR0 Vorgeladen (8 Bit Timer hat einen Überlauf bei 255 
oder
anders gesagt alle 255 uS) mit genau der Zeit für einen Abtastpunkt.
Also 255 - 162 = 93 uS //eigentlich müßten das 104 uS für 1200 BPS sein 
aber beim Pic gehen für 2 Zyklen die Taktsignale des Timers beim 
Anspringen des Interrupt verloren und die PUSH Routine benötigt auch 
einige Zyklen deshalb hat er weniger Vorgeladen.
Das heißt es wird immer zum Richtigen Zeitpunkt ein Interrupt erzeugt 
und
in der Interrupt Routine dann der Zustand des Eingangsportes Ausgewertet 
und gespeichert. Desweiteren hat er eine Art PLL Synchronistation 
gemacht in dem er zusätzlich einen Timer (COUNT_IN) bis 8 Hochzählt und 
den Wechsel von 0 nach 1 mit genau dem Wert dieses Timers vergleicht.
Theorie ist das wenn ich in der Mitte des Abzufragenden BIT's bin dieser 
Timer dann den Wert 4 hat. ist er niedriger so stimmt die Phase in 
negativer Richtung nicht und er gleicht das aus indem er den COUNT_IN 
auf 0 setzt. Ist der Wert höher so ist die Phase in Positiver Richtung 
Nach zu
Stellen, er übernimmt das Bit aber trotzdem. In einer PLL wäre das dann
die LOCK und die PLL ist gerastet. Nun zählt er die BIT die er Empfängt 
und speichert diese in DATA_0 bis DATA_3 (leider macht er das mit DATA_ 
+1
was der Übersicht jedoch schadet). Wenn er so ein 32 BIT Code Word (1/2 
Frame) zusammen hat wertet er diesen aus. Das Programm ist Tricky 
geschrieben und außerdem Absolut Programmiert (Table Read für CRC usw.)

Ich glaube das Prinzip ist nun klar und du kannst es auf einen AVR oder
anderen Controller Übertragen.

viel Spaß
Roland

von Frank H. (gowi)


Lesenswert?

Sehr guter Beitrag, danke!

von Christian S. (kruemel)


Lesenswert?

Vielen Dank für die Anwort.

"Desweiteren hat er eine Art PLL Synchronistation
gemacht in dem er zusätzlich einen Timer (COUNT_IN) bis 8 Hochzählt und
den Wechsel von 0 nach 1 mit genau dem Wert dieses Timers vergleicht.
Theorie ist das wenn ich in der Mitte des Abzufragenden BIT's bin dieser
Timer dann den Wert 4 hat. ist er niedriger so stimmt die Phase in
negativer Richtung nicht und er gleicht das aus indem er den COUNT_IN
auf 0 setzt. Ist der Wert höher so ist die Phase in Positiver Richtung
Nach zustellen..."

Wird damit das Sync Wort erkannt?
Also es wird hochgezählt von 0..1..2..3..4.. auf 7 und was wird dann 
verglichen? Wenn ich also bei 3 beim Timer bin und nicht in der Mitte 
des Bits, dann stimmt die Phase in negativer Richtung nicht?

"Dejan hat den Timer0 nun mit dem
Zyklustakt bei 4MHz Clock = 1MHz Zyklus direkt verbunden (Prescaler mit
dem WDT Timer Verbinden = 1:1 für den TMR0). Das war clever.
Nun hat er den TMR0 Vorgeladen (8 Bit Timer hat einen Überlauf bei 255
oder
anders gesagt alle 255 uS) mit genau der Zeit für einen Abtastpunkt."

Das verstehe ich nicht ganz, was wird hier gemacht?



Okay, viel auf einmal, ich versuche mich mal in die Sache einzuarbeiten 
und die Schritte nachzuvollziehen.

Danke
Gruß
Christian

von Roland (r_fischer)


Lesenswert?

Hallo Christian,

ich habe gerade das hier gesehen, hatte ich vorher gar nicht bemerkt:

"Bei der Schaltung ist immer ein Quarz eingebaut, wieso muss der AVR
einen externen Quarz bekommen?"

Die Antwort ist nein, der Pic 16F84 benötigte einen Quarz da er keine
interne Frequenzerzeugung hat. Wenn der 16F628A bzw. 16F648A oder auch 
der
16F88 verwendet worden wäre hätte man auch keinen Quarz benötigt.

Die wahl der Taktgeschwindigkeit hängt stark von dem Umfang der im 
Programm
ablaufenden Funktionen ab, die Kosten ja Zeit und Speicher. Der Pic 
hatte
von allem zu wenig und wäre es nicht so gut programmiert worden hätte 
man
das nicht hinbekommen auf dem kleinen Ding.


"Wird damit das Sync Wort erkannt?
Also es wird hochgezählt von 0..1..2..3..4.. auf 7 und was wird dann
verglichen? Wenn ich also bei 3 beim Timer bin und nicht in der Mitte
des Bits, dann stimmt die Phase in negativer Richtung nicht?"

Nein, das sind 2 paar Schuhe.

1. Nutzsignal in Phase mit der Taktgeschwindigkeit des Mikrocontrolers
bringen. Dadurch ist es dir möglich den Zustand der Bit's ohne weitere 
Kontrolle der Phasenlage immer zum richtigen Zeitpunkt (in der Mitte)
Abzufragen.

2. zu der Frage wie erkenne ich das erste NUTZ Bit.

Hier mal ein Programmablauf:

1- Eingangsport Abfragen, wenn 1 dann Prüfen ob es sich um ein Bit 
handelt
oder um "Rauschen" (Funkempfang). Das macht man über die Zeit die 1 Bit
benötigt bei XXX BPS. Bei dir also 512 BPS = 1,954 mS. Da du mit einer
Vielfachen Pollst z.B.: 8 mal ( alle 244,25 uS) mußt du also 8 mal High 
haben und du weißt jetzt kommt ein Nutzbit.
Das könnte man als Rauschsperre betrachten.

Dies könnte so Aussehen:
ACHTUNG PIC ASSEMBLER, kein AVR.

#define DISKRI PORTB,x <= Eingang Pin

START:
BTFSS   DISKR          ; Eingang Abfragen
GOTO    EIN_NULL       ; der Eingangszustand war 0
GOTO    EIN_EINS       ; der Eingangszustand war 1

; Prüfe ob der Zustand 0 für 8 Abtastpunkte gleich ist
EIN_NULL:
MOVLW   d'8'            ; 8 mal 244,25 uS = 1,954 mS Bitlänge bei 512 
BPS
MOFWF   BIT_LANGE       ; im FR speichern POLL Intervall

POLL_NULL:
BTFSS   DISKRI          ; Prüfe Eingang auf 0, wenn 1 dann wieder von 
vorne Anfangen da es kein Nutzsignal war
GOTO    WEITER_P0       ; nun das POLLDELAY abwarten und erneut Prüfen
GOTO    START           ; Innerhalb der Bitlänge hat sich der Zustand 
verändert, es handelt sich um Rauschen, erneut von vorne beginnen.

WEITER_P0:
CALL    POLL_DELAY      ; je nach Baudrate eine Warteschleife von x uS
DECFSZ  BIT_LANGE       ; POLL Intervall -1
GOTO    POLL_NULL       ; nächster Test

; Ein Bit wurde nun Vollständig Empfangen, nun das BIT in ein Byte 
Übernehmen
BCF     EMPFANG_BYTE,0  ; WERT 0 im Empfangsbyte speichern
RLF     EMPFANG_BYTE,F  ; nach Links schieben und im FR speichern
GOTO    START           ; nächstes BIT Empfangen

.....

; Prüfe ob der Zustand 1 für 8 Abtastpunkte gleich ist
EIN_EINS:
MOVLW   d'8'            ; 8 mal 244,25 uS = 1,954 mS Bitlänge bei 512 
BPS
MOFWF   BIT_LANGE       ; im FR speichern POLL Intervall

POLL_EINS:
BTFSC   DISKRI          ; Prüfe Eingang auf 1, wenn 0 dann wieder von 
vorne Anfangen da es kein Nutzsignal war
GOTO    WEITER_P1       ; nun das POLLDELAY abwarten und erneut Prüfen
GOTO    START           ; Innerhalb der Bitlänge hat sich der Zustand 
verändert, es handelt sich um Rauschen, erneut von vorne beginnen.

WEITER_P1:
CALL    POLL_DELAY      ; je nach Baudrate eine Warteschleife von x uS
DECFSZ  BIT_LANGE       ; POLL Intervall -1
GOTO    POLL_EINS       ; nächster Test

; Ein Bit wurde nun Vollständig Empfangen, nun das BIT in ein Byte 
Übernehmen
BSF     EMPFANG_BYTE,0  ; WERT 0 im Empfangsbyte speichern
RLF     EMPFANG_BYTE,F  ; nach Links schieben und im FR speichern
GOTO    START           ; nächstes BIT Empfangen

.........

Natürlich mußt du vorher einen Zähler Einbauen das du bei Ereichen von
8 BIT das  nächste Empfangsbyte füllst.

2- Es kommen also BIT's rein, nun Prüfen ob sich der Zustand der Bit's
von 0 nach 1 nach 0 nach 1 usw. ändert. Präambel Erkennung:
Dies macht man am besten so:

ACHTUNG PIC ASSEMBLER, kein AVR.

#define DISKRI PORTB,x <= Eingang Pin

MOVLW  d'8'           ; 8 Bit = 1 Byte
MOVWF  BITZAHLER      ; Zähler

BIT_EINLESEN:
CLRF  STATUS,C        ; zur Sicherheit Carry Flag Löschen
BTFSC DISKRI          ; Eingang Abfragen, wenn 0 dan Überspringe nächste 
Zeile
BSF   EINGANG_BYTE,0  ; Bit = 1 in den Empfangsbuffer schreiben
RLF   EINGANG_BYTE,F  ; 1 Stelle nach Links schieben
DECFSZ BITZAHLER      ; Bitzähler -1, wenn 0 dann Überspringe nächste 
Zeile
GOTO  BIT_EINLESEN    ; Noch kein Byte voll, erneut Einlesen.

Wenn dies Schleife Durchlaufen ist hast du das erste Byte von 4.
Nun mußt du es mit der Erwartung Präambel vergleichen.

MOVLW  b'01010101'   ; Vergleichswert
XORWF  EINGANG_BYTE,W ; Exclusiv Oder Vergleichswert mit Eingangs Byte
BTFSC  STATUS,Z       ; Zero Flag des Statusregisters Prüfen, dies ist 1
wenn der Inhalt von W und F Identisch waren.
GOTO   WEITER         ; es war die Präambel nun weiter mit....
GOTO   BIT_EINLESEN   ; war nicht die Präambel, erneut Anfangen


Ich weiß, ist ein wenig viel auf Einmal aber da mußt du durch ;-)
Und das war nur der leichte Teil.


viele Grüße
Roland

von Christian S. (kruemel)


Lesenswert?

Hi,

also so verstehe ich das schon besser. Ich werd das mal in Ruhe 
durchgehen und dann mal versuchen das in AVR Assembler oder in C Code zu 
schreiben.

Deine Kommentierung, wie du was machst nach dem Assembler ist viel 
besser nachzuvollziehen als undokumentierter Code.

Vielen Dank für deine Mühe.
Ich bleib dran und melde mich weiter :-).

von Christian S. (kruemel)


Lesenswert?

Hallo,

ich kram den Beitrag mal wieder raus.
Habe mich etwas mehr mit dem Programmier Denken angefreundet und bin im 
Moment in der Uni dabei eine DCF Uhr in VHDL zu programmieren. Im 
Prinzip handelt es sich dabei ja auch um eine Dekodierung.

Den Pocsag Dekoder würde ich gerne in C programmieren.

Nach oben ist es, so wie ich es verstanden habe also erforderlich zu 
gucken ob auf dem Kanal Rauschen ist oder ob es ein Nutzsignal ist.
So wie ich das oben verstanden habe soll dafür ein Timer eingesetzt 
werden, der das Signal abtastet. Das heisst der Timer muss abgefragt 
werden und wenn 8 mal logisch 1 auftaucht, handelt es sich um ein 
Nutzsignal bzw Nutzbit.

Dann würde ich einen Interrupt auslösen, der die Präamble erkennt und 
danach die vorhandenen Bits in ein Schieberegister schiebt, wo sie 
nachher ausgewertet werden können.

Mein erster Schritt wäre demnach nun erstmal die Rausch-Nutzsignal 
Erkennung bevor es weitergeht. Ist der Ansatz so richtig? Bei der DCF 
Uhr wurde solch eine Rausch-Nutzsignal Erkennung nämlich nicht 
vorgenommen.

Viele Grüße
Christian

von Roland (r_fischer)


Lesenswert?

Hallo Christian,

ja, so wird es in den Programmen oben gemacht.

Roland

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.