- 3D-Druck Einstieg und Tipps         
Seite 2 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 11 bis 20 von 35

Thema: DCF77 Funksignal auslesen

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803

    DCF77

    Anzeige

    Praxistest und DIY Projekte
    Moin cesupa,

    also eine Pause ist die Phase mit max. Sendeleistung des DCF77-Senders und der Impuls wird mit 25% Leistung gesendet.
    Aber das ist egal. Deine Negierung bei der Abfrage wars schon.

    Deine Änderung ist so schon gut.

    Was du noch machen must:

    Du must 4 Zustände erkennen: Pausen 800/900/1800/1900ms.
    Du brauchst also 4 Abfragen z.B. der Art:
    Pause > 780 and Pause < 820 -> DiesisteinEINSBIT
    Pause > 880 and Pause < 920 -> DiesisteinNULLBIT

    ... und so auch für die beiden anderen Bits (EINSBITENDE/NULLBITENDE).

    Wenn du ein ENDE-Bit erreicht hast stellst du die RS232-Ausgabe auf Zeilenanfang um. Mit den Wertebereichen must du experimentieren: Lass sie dir später ausgeben, um die Mitte festzulegen und einen sicheren +-Bereich.

    Gruß Dirk

  2. #12
    Benutzer Stammmitglied
    Registriert seit
    01.07.2005
    Beiträge
    64
    Also so langsam krieg ich hier die Krise. Ich hab das ganze jetzt so umgesetzt wie du gesagt hast, aber jetzt bekomme ich gar keine Zeichen mehr ausgegeben. Hier der Code ausm Timer:


    Code:
    if(!(PINC & (1<<PC0)))			//Kein Impuls==Pause
    {
    
    	if(t>78000 && t<82000)					
    	{
    	if(dcf!='0')
    	dcf='1';
    	}
    
    	if(t>88000 && t<92000)					
    	{
    	dcf='0';
    	}	
    
    	if(t>170000 && t<180000)
    	{
    	dcf_buf[t2]='1';				//ENDEBIT 
    	dcf_buf[t2+1]='\0';
    	t2=0;
    	r='2';							//empfangene Zeichenkette über RS232 senden 
    	}
    
    	if(t>180000 && t<190000)
    	{
    	dcf_buf[t2]='0';				//ENDEBIT
    	dcf_buf[t2+1]='\0';
    	t2=0;
    	r='2';							//empfangene Zeichenkette über RS232 senden
    	}
    
    t++;								//Timer inkrementieren
    }
    else							//Impuls==timer zurücksetzen
    {
    	if(dcf=='0' || dcf=='1')		//Wenn Zeichen empfangen
    	{
    	dcf_buf[t2]=dcf;				//empfangenes Zeichen in zur Zeichenkette hinzufügen
    	dcf_buf[t2+1]='\0';							
    	t2++;							//eine Stelle weiterrücken
    	}
    t=0;							//Timer zurücksetzen
    }
    Ich nehme mal stark an, dass mein Counter t anscheinend nie die eigentlich gewünschten Zahlen erreicht. Sollte ich vielleicht den Voreingestellten Timer, der ja jetzt auf 0,01ms steht auf z.b. mal 10ms sekunden erhöhen? Oder liegt das Problem doch ganz woanders?

    Gruß
    cesupa

  3. #13
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803

    DCF77

    Hallo cesupa,

    Sollte ich vielleicht den Voreingestellten Timer, der ja jetzt auf 0,01ms steht auf z.b. mal 10ms sekunden erhöhen?
    Ich hatte dein Prog wohl nicht richtig angesehen. Poste doch mal das komplette Prog! Eine ISR für 10ms = 0,01s ist völlig ausreichend für die DCF-Decodierung.

    Das bedeutet dann, dass in einer Pause von 800ms die Interruptroutine 80x aufgerufen wird. Der Test auf ein 1-Bit wäre dann:
    Pause < 78 and Pause > 82 -> EINSBIT

    Gruß Dirk

  4. #14
    Benutzer Stammmitglied
    Registriert seit
    01.07.2005
    Beiträge
    64
    So, also hier nochmal mein kompletter code, jegliche Kritik und Verbesserung ist erwünscht, ich bin ja auch noch Anfänger in dieser Sache :



    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #define BAUD 9600UL
    
    #include "../classes/rs232/UART/UART.h"
    
    volatile uint32_t t,t2;
    volatile unsigned char dcf=0xff;
    volatile unsigned char dcf_buf[128];
    volatile unsigned char r;
    
    
    SIGNAL(SIG_OUTPUT_COMPARE2)
    {
    if(!(PINC & (1<<PC0)))			//Kein Impuls==Pause
    {
    
    	if(t>78000 && t<82000)					//Wenn kleiner 900ms
    	{
    	if(dcf!='0')
    	dcf='1';
    	}
    
    	if(t>88000 && t<92000)					//Wenn größer gleich 900ms
    	{
    	dcf='0';
    	}
    
    	if(t>170000 && t<180000)				//PAUSE für ENDEBIT
    	{
    	dcf_buf[t2]='1';
    	dcf_buf[t2+1]='\0';
    	t2=0;
    	r='2';
    	}
    
    	if(t>180000 && t<190000)				//Pause für ENDEBIT
    	{
    	dcf_buf[t2]='0';
    	dcf_buf[t2+1]='\0';
    	t2=0;
    	r='2';
    	}
    
    t++;
    }
    else							//Impuls==timer zurücksetzen
    {
    	if(dcf=='0' || dcf=='1')		//Wenn Zeichen empfangen
    	{
    	dcf_buf[t2]=dcf;
    	dcf_buf[t2+1]='\0';							
    	dcf=0xff;
    	t2++;
    	}
    t=0;							//Timer zurücksetzen
    }
    
    }
    
    void timer_init(void)
    {
    t2=0;
    t=0;
    r='0';
    TCCR2=(1<<CS22) | (1<<WGM21);
    OCR2=160;						//0,01ms (?)
    TIMSK|=(1<<OCIE2);
    sei();
    }
    
    
    int main(void)
    {
    DDRC&=~(1<<PC0);		//Eingangspin DCF-Signal
    PORTC|=(1<<PC0);		//Pullups aktivieren
    
    timer_init();			//Timer initialisieren
    
    uart_init();			//UART inititalisieren
    
    while(1)
    {
    	if(r=='2')			//Wenn Signal zum Senden gesetzt
    	{
    	dcf=0xff;			//Bit zurücksetzen
    	r='0';				//Signal zurücksetzen
    	send("DCF: ");
    	send(dcf_buf);		//Daten an PC senden
    	send("\r\n");
    	}
    }
    
    return 0;
    }
    Gruß
    cesupa

    P.S.: Mein Atmega8 läuft mit einem externen 16MHz Quarz.

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803

    DCF77

    Hallo cesupa,

    ich habe deine Timereinstellung noch nicht nachgerechnet, aber ein Interrupt von 0,01ms = 10us ist viel zu schnell. Da hast du ja nur 10 Taktzyklen in der ISR (bei 1 MHz) und 4 davon gehen schon mit RETI drauf.
    Auch bei deinen 16 MHz sind das 160 Zyklen, nach dem Sichern von Registern noch ca. 140-150.
    Das ist viel zu wenig für deine Menge an Code in der ISR. D.h. dass du einige Interrupts verpasst, weil dein uC beim folgenden Interrupt noch in der ISR beschäftigt ist.

    Nimm eine Abfragefrequenz des DCF-Eingangs von 10ms. Auch 25ms ist noch ausreichend.

    Dann kannst du dir die Zählerwerte ja erst mal ohne die 0/1-Bit Zuordnung per RS232 ausgeben. Die Anzeige sollte zwischen 2 Werten schwanken, 1x pro Minute kommt noch ein längerer Wert hinzu.

    Danach legst du dann deine Limits für die Bit-Tests fest.

    Gruß Dirk

  6. #16
    Benutzer Stammmitglied
    Registriert seit
    01.07.2005
    Beiträge
    64
    Hallo Dirk,

    ich glaube, so langsam kann ich meine ersten kleinen Erfolge verbuchen. Ich lasse die Interrupt-Rountine jetzt nur noch alle 10ms laufen und wenn ich mir die Empfangenen Bits anzeigen lasse kommt sowas dabei raus:

    Code:
    111100011111000111110001111100011111000111110001111100011111
    
    011111000111110001111100011111000111110001111100011111000111
    
    000111110001111100011111000111100001111000111110001111100011
    
    100011000000000000000000000000000000000000000000000000000000
    
    111000111110001111100011111000111110001111100011111000111110
    
    111100001111000111110001111100011111000111110001111100011111
    
    011111000111110001111100011111000111110001111100011111000111
    
    000111110001111100011111000111110001111100011111000111110001
    
    100011111000111110001111100011111000111110001111100011111000
    
    111000111110001111100011111000111110001111100011111000111110
    
    111110001111100011111000111110001111000111110001111100011111
    .
    .
    .
    .
    Ja, das sieht ja schonmal ziemlich regelmäßig aus, so solls doch auch bestimmt sein, richtig? (Das wäre dann nämlich der Erfolg den ich erwähnt habe )
    Aber jetzt stellt sich mir eine neue Frage:

    Wenn eine Pause ca. 700-900ms andauert, dann müsste ich ja in meinen Bitfolgen 70-90 gleiche Zeichen hintereinander finden. Dagegen findet man bei genauem hinschauen zwischen den regelmäßigen Bitfolgen auch eine Reihe in der nur Null-Bits stehen, ist das dann vielleicht das Signal für das Endebit?
    Wenn ich meinen Pin an den anderen Anschluss des Conrad-DCF-Empfängers anschließe bekomme ich ca. 8 Zeilen Nullen und dann eine regelmäßige Zeile wie oben. Sind diese 8 Zeilen dann vielleicht die Pausen?

    Meinen Timer hab ich übrigens wie folgt umgeschrieben:

    Code:
    void timer_init(void)
    {
    t=0;
    t2=0;
    TCCR2=(1<<CS22) | (1<<CS20) | (1<<WGM21);
    OCR2=156;						//10,0ms (?)
    TIMSK|=(1<<OCIE2);
    sei();
    }
    Gruß
    cesupa

    P.S.: Hab mir jetzt mal die Variable t ausgeben lassen. Komischerweise reicht die Zahl ziemlich oft bis ca 200, aber Zahlen zwischen 70 und 90 werden auch erreicht.

  7. #17
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Hallo cesupa,

    ja das sieht ja schon gut aus.

    Da sich die Bitfolge um jeweils 1 Bit verschiebt, hast du noch mit der Ende-Erkennung ein Problem.

    Du brauchst jetzt die Zählerwerte, um weiter zu kommen.
    Du solltest in der 0-Bit- und 1-Bit-Erkennung eine Variable einbauen, die den Wert von t speichert oder du gibt ihn sofort via RS232 aus.
    Für das Ende-Bit testest du z.B. nur auf > 1000ms, so dass erst mal beide Ende-Bits (0/1) erfasst werden. Den Wert von t gibst du für das Ende-Bit auch aus.

    Dann hast du schon die 3 wesentlichen Werte (normale 0/1-Bits und EIN Ende-Bit, von dem du nicht sicher weißt, ob es Null oder Eins ist. Das hängt vom Datum ab (genauer von der Parität des Datums!). Dieses Ende-Bit bleibt den ganzen Tag lang 1 oder 0 und wechselt meist erst am nächsten Tag (muss aber nicht sein!). Wenn dein t beim Ende-Bit um die 1800ms ergibt, wird es aber ein 1-Bit sein und bei 1900ms ein 0-Bit.

    Gruß Dirk

  8. #18
    Benutzer Stammmitglied
    Registriert seit
    01.07.2005
    Beiträge
    64
    Hallo,

    hab jetzt mal den Fehler in meinem Timer behoben. Jetzt läuft die ISR wirklich mit 10ms

    Ich lasse mir grad ein paar Werte ausgeben, unzwar mit folgendendem Code, der in der ISR steht:

    Code:
    if(!(PINC & (1<<PC0)))
    {
    	if(t>70 && t<85)
    	{
    	if(dcf!='1')
    	dcf='1';
    	}
    
    	if(t>85 && t<95)
    	{
    	if(dcf!='0')
    	dcf='0';
    	}
    
    		
    	if(t>172 && t<183)
    	{
    	if(dcf!='1')
    	dcf='1';
    	
    	if(start!=1)
    	start=1;
    	}
    
    	if(t>183 && t<192)
    	{
    	if(dcf!='0')
    	dcf=0;
    
    	if(start!=0)
    	start=0;
    	}
    
    t++;
    }
    else
    {
    t=0;                     //Timer zurücksetzen
    t2=1;                   //Empfangenes Zeichen an PC senden
    }
    Wenn ich das laufen lasse, erhalte ich ziemlich viele Einsen, jedoch nur recht wenig Nullen(Also hin und wieder mal eine Null zwischen zwei einsen). Ab und zu erscheint auch mal eine längere Folge an Einsen, aber größtenteils erhalte ich solche folgen wie: "01010101..." -Muss das so sein?
    Desweiteren empfange ich nie ein ENDEBIT, woran kann das liegen?

    Gruß
    cesupa

  9. #19
    Benutzer Stammmitglied
    Registriert seit
    01.07.2005
    Beiträge
    64
    So, hab mir jetzt mal ein paar Werte von t ausgeben lassen. Also von ca. 70 bis ca. 90 ist so ziemlich alles dabei. Mittendrin finden sich auch Werte die bis 147 gehen.

    Gruß
    cesupa

  10. #20
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803

    DCF-Decodierung

    Hallo cesupa,

    dein Proggi funktioniert noch nicht sauber:

    Die Logik sollte z.B. so sein:

    Alle 10ms wird der Eingang in der ISR abgefragt.
    Ist der Pegel am Eingang gleich wie bei der letzten Abfrage geblieben, wird die Zählvariable inkrementiert und dann passiert nix mehr (Ende der ISR).
    Hat sich der Pegel am Eingang geändert, dann ist eine Pause oder ein Impuls beendet und die Zählvariable wird dann mit den 4 Bezugswerten 800/900/1800/1900ms verglichen. Danach wird die Zählvariable auf Null gesetzt.

    Die Auswertung der Bits passiert also NUR bei einer Pegeländerung! Bleibt der Pegel gleich, wir nur der Zähler erhöht.
    Das heisst natürlich auch, dass du dir immer den letzten Pegel in einer Variable speichern must (wenn er anders als der vorherige war), um ihn beim nächsten Mal vergleichen zu können.

    Wenn du das so machst, ist es auch egal, welchen Ausgang (invertiert/ nicht invertiert) des DCF-Empfängers du nimmst, weil jede Impuls-/Pausenlänge gemessen wird, also AUCH die Impulse 100/200ms. Die beachtest du aber einfach nicht.

    Gruß Dirk

Seite 2 von 4 ErsteErste 1234 LetzteLetzte

Berechtigungen

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

12V Akku bauen