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
Hallo,
Einfache Experimente mit ATMega8, um ein POCSAG zu empfangen. Eine
konkrete Anwendung wollte ich später in einer selbstgebauten
Wetterstation suchen.
Gruß cmb
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ß
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
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.
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.
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
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
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
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
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 :-).
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