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
Schreib doch bitte ein wenig mehr zu deinem Projekt ! Etwas fertiges möchtest nicht nutzen ?
Hallo, Einfache Experimente mit ATMega8, um ein POCSAG zu empfangen. Eine konkrete Anwendung wollte ich später in einer selbstgebauten Wetterstation suchen. Gruß cmb
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 .
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.