Forum: Mikrocontroller und Digitale Elektronik DCF77 Signale auswerten


von Yen L. (yenlo)


Lesenswert?

Moin, ich stehe gerade auf dem Schlauch beim Versuch DCF Signale 
auszuwerten.

DCF-Modul: Conrad und es wird der nicht(!)-invertierte Ausgang 
abgenommen und via INT0/PD2 eingelesen. Dafür habe ich die 
"lcd-routines" auf Port C umgebogen.
AVR: AtMega8 bei 1 Mhz internem Takt mit 1ms Ticker
Kontroll LEDs: PB2 - Sekundentakt; PB1 - DCF Signal

Der Sekundentakt PB2 passt und die DCF Kontrolleuchte PB1 toggelt 
passend zum DCF Signal vor sich hin. Die DCFZeitdauer wird in 
Millisekunden gelesen und im LCD als "eins" und "null" interpretiert. 
Soweit so gut -
allerdings erreicht mein DCF-Zähler keine Sync-Dauer und wird deutlich 
vor 1700ms genullt :-/

Jetzt @work und fern des Projekts sitzend fallen mir ein:
- nehme ich das richtige Signal ab oder muss ich die Pinabfrage am PIN 
umdrehen?
- gibt es beim AtMega8 und uint16_t etwas zu beachten?
oder mache ich ganz woanders Mist?


Code (noch nicht aufgeräumt):
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "LCD-Routines.h"  // geaendert auf PORT-C
4
#include <stdlib.h>
5
6
#define F_CPU 100000L     // interner Takt 1 MHz
7
volatile uint16_t internalTime = 0;      // fuer Sekunde
8
// dcf Zeit
9
volatile uint16_t dcfTime = 0;      // Signaldauer INT0 DCF
10
volatile uint16_t dcfAnz =0;
11
volatile uint8_t dcfFlag =0;
12
13
14
/**********************************************
15
* Interrupt Routinen
16
**********************************************/
17
ISR (TIMER2_COMP_vect) {
18
  internalTime++;              // 1ms
19
  if (internalTime == 1000) {  // 1000ms (0-999) = 1 Sek
20
    internalSek++;           // Sekunden hoch  
21
    internalTime = 0;
22
    PORTB ^= (1 << PB2);     // Kontrolle LED PB2
23
  }
24
  
25
  // INT0 abfragen
26
  if (PIND &(1 << DDD2)) {
27
    PORTB |= (1 << PB1);     // Kontrolle LED PB1 an
28
    dcfTime++;
29
    dcfFlag=1;
30
  } else   if (!(PIND &(1 << DDD2))) {
31
    PORTB &= ~(1 << PB1);     // Kontrolle LED PB1 aus
32
      if (dcfFlag == 1) {  
33
      dcfAnz=dcfTime;
34
      dcfTime = 0;
35
      dcfFlag = 0;
36
    }    
37
  }
38
39
}
40
41
42
// Ueberwachung INT0 - DCF77-Eingang
43
ISR (INT0_vect) {
44
  // foo
45
}
46
47
48
// ****************************** MAIN *********************
49
int main(void) {
50
   internalTime = 0;  // Start interner Zeitzaehler
51
   dcfAnz = 0;   
52
   dcfTime = 0;
53
   dcfFlag =0;     
54
   
55
   // PORT B als Ausgänge
56
   DDRB |= (1 << DDB1) | (1 << DDB2); // PB1 und PB2 als LED OUT
57
   PORTB &= ~(1 << PB1);      // PB1 aus
58
   PORTB &= ~(1 << PB2);      // PB2 aus
59
   
60
   // PORT D als Eingang fuer INT0
61
   DDRD &= ~(1 << DDD2);  // INT0 als Eingang
62
   MCUCR = (1 << ISC00) | (1 << ISC01);   // steigende Flanke INT0
63
   GICR = (1 << INT0);                    // IRQ an INT0 zulassen
64
   
65
   // Timer2 als Millisekundencounter
66
   TIMSK  |= (1 << TOIE2) | (1 << OCIE2);
67
   OCR2 = 125 - 1;          // Compare gegen 125 für 1 ms
68
   TCCR2  |= (1 << CS21);   // Prescaler Timer2 = 8
69
   TCCR2  |= (1 << WGM21);   // Compare Mode CTC zulassen
70
   sei();                   // Interrupts global zulassen
71
   
72
   // **** LCD ****
73
   lcd_init();
74
   
75
   
76
    while(1)
77
    {
78
      // DCF Signal = AUS
79
      if (dcfAnz >=60 && dcfAnz <= 140) {
80
       lcd_setcursor(0,1);
81
       lcd_string("DCF: NULL ");
82
      // DCF Signal = EIN
83
      } else if (dcfAnz >=150 && dcfAnz <=260) {
84
         lcd_setcursor(0,1);
85
         lcd_string("DCF: EINS ");
86
       // DCF Signal = SYNC
87
      } else if (dcfAnz >=1700 && dcfAnz <=2200) {
88
         lcd_setcursor(0,1);
89
         lcd_string("DCF: SYNC ");
90
      } 
91
    
92
    }
93
}

von Yen L. (yenlo)


Lesenswert?

Soweit habe ich das mit dem DCF Signal und der Uhrzeit hinbekommen.
Allerdings sehe ich alle 4 Minuten eine Bitverschiebung, als ob der Sync 
an der Stelle nur als 1 Sek und nicht als 2 Sek Intervall interpretiert 
ist..

schaue ich mir morgen mal in Ruhe an

von Yen L. (yenlo)


Lesenswert?

Fehler gefunden. Das Conrad Modul läuft jetzt seit knapp ner Stunde 
stabil mit der DCF Zeit/Datumsanzeige.

Einen Großteil der Lösungen habe ich hier im Forum in diversen 
Problembeschreibungen oder Tutorials finden können. Dafür Danke an alle, 
die sich hier im Forum engagiert haben ;)

von Martin K. (maart)


Lesenswert?

Und was war der Fehler?

von Yen L. (yenlo)


Lesenswert?

Martin Kreiner schrieb:
> Und was war der Fehler?

Bei der Signalauswertung: In meinen Setup werte ich Inverse aus(könnte 
man auch andersherum machen... ist ja wurscht ;)

Der Fehler lag am ungeschickt ausgelagertem Aufbau der 
Auswertungsroutine, die periodisch zuviel Zeit gefressen hat. Das 
Herzstück sieht nun so aus und lief von gestern abend bis heute früh 
ohne Ausreisser - Code noch unbereinigt und ressoucenverschwendend:

ISR (TIMER2_COMP_vect) {
  internalTime++;              // 1ms
  if (internalTime == 1000) {  // 1000ms (0-999) = 1 Sek
    internalSek++;           // Sekunden hoch
    internalTime = 0;
    PORTB ^= (1 << PB2);     // Kontrolle LED PB2
    showInternal=1;
    intUhrzeit();
  }

  // INT0 abfragen
  if (!(PIND &(1 << DDD2))) {
    PORTB |= (1 << PB1);     // Kontrolle LED PB1 an
    dcfTime++;
    dcfFlag=1;
  } else   {
  // if ((PIND &(1 << DDD2))) {
    PORTB &= ~(1 << PB1);     // Kontrolle LED PB1 aus
    if (dcfFlag == 1) {
      dcfBit=dcfTime;
      dcfTime = 0;
      dcfFlag = 0;

      // --- Signalauswertung --
      if (dcfBit >=760 && dcfBit <= 832) {  //um 325 hex
        signalDCF[arrayCounter]=0;

      // DCF Signal = EIN
      } else if (dcfBit >=850 && dcfBit <=1000) { //um 385 hex
        signalDCF[arrayCounter]=1;

      // DCF Signal = SYNC
      } else if (dcfBit >=1600 && dcfBit <=2200) { // 702 hex
        normalSync=1;
        arrayCounter=255;
        if (rtcSync == 0) {  // erstmaliger SYNC?
          rtcSync =1;
          internalSek=0;
          internalMin=0;
          internalHour=0;
        }
        dcfZeit();
      }
      arrayCounter++;
    }

  }

}

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.