Forum: Mikrocontroller und Digitale Elektronik Atmega8: DCF77 an ICP1-Pin hängen


von Tobi F. (knuutt)


Lesenswert?

Hi,

ich versuche gerade das DCF77-Modul von Conrad mit meinen ATmega8 zum 
Laufen zu bekommen. Um das empfangene Signal vom DCF77-Modul zu 
dekodieren, wollte ich mit Hilfe vom ICP1-Pin und einen Timer die 
Biterekennung(100ms low = '0'; 200ms low = '1') realisieren.

Um jetzt erstmal "einzusteigen" habe ich mir unten stehende Funktion 
geschrieben. Wenn ich die Decodierung vom DCF77 richtig verstanden habe, 
sollte jetzt die Ausgabe 'TIMER1_CAPT_vect' 59Mal pro Minute ausgegeben 
werden, oder?. Aber die Ausgabe kommt wesentlich öfters(Zeitmessung alle 
8Sekunden: Da kommt die Ausgabe zwischen 0x - 40x; Eigentlich erwartet: 
8x). Habe ich einen Fehler im Programm, in der Denkweiße oder bekomme 
ich so viele Störsignale, dass ich das Programm so nicht realisieren 
kann?

Bin für jede Hilfe dankbar.

clock.c
1
ISR(TIMER1_CAPT_vect)
2
{
3
  usart_write("TIMER1_CAPT_vect\n");
4
5
}
6
7
void startClock(void) {
8
  TCNT1 |= (1 << ICES1); //0 = 'falling edge', '1'=rising edge
9
10
  //timer
11
  TIMSK |= (1 << TOIE1); //enable interrupt timer
12
  TIMSK |= (1 << TICIE1); //enable interupt capter Register(ICP)
13
  TCCR1B |= (1 << CS10 | 0 << CS11 | 1 << CS12); //prescaler 1024
14
  TCCR1B |= (1 << ICNC1); //noise filter enable
15
16
  TCNT1 = 65535 - (SYSCLK / 1024); //sysclk = 8000000, define in uart.h
17
}

main.c
1
int main(void) {
2
3
  //using usart for debugging
4
  usart_init(9600);
5
6
  DDRC = _BV(LED);   //LED as Output
7
  PORTC = _BV(LED);
8
9
  PORTB = (1 << PD0); //pullup widerstand ICP
10
11
12
  //Enable global interrupt
13
  sei();
14
15
  //start clock
16
  startClock();
17
18
  usart_write("\nDCF 77 Debugger123\n\n");
19
20
  while (1)
21
  {
22
    LED_ON
23
    _delay_ms(1000);
24
    LED_OFF
25
    _delay_ms(1000);
26
  }
27
}

von HildeK (Gast)


Lesenswert?

Tobi F. schrieb:
> TCNT1 |= (1 << ICES1); //0 = 'falling edge', '1'=rising edge

TCNT1 ist doch der 16-Bit-Zähler des Counters. ICES1 sollte m.E. im 
TCCR1B-Register gesetzt werden.
Abgesehen davon ist die Methode, das DCF-Signal mittels Interrupt 
aufzunehmen, nicht so ganz optimal. Häufig hat man Störungen, die sich 
wie Prellen geben, und dann werden einzelne Flanken mehrfach erfasst.

von Peter D. (peda)


Lesenswert?

Tobi F. schrieb:
> bekomme
> ich so viele Störsignale, dass ich das Programm so nicht realisieren
> kann?

So wirds sein.
Gibt doch mal den Pin auf ne LED aus.

Die bevorzugte Methode ist z.B. alle 10ms per Timerinterrupt das Signal 
einzulesen. Die 100/200ms Pulsdauer und die 2s Pause kann man dann 
bequem mit je einem Byte abzählen.
Die 10ms kann man gleichzeitig auch für die interne Zeitzählung bei 
Empfangsstörungen benutzen.

: Bearbeitet durch User
von Frank (Gast)


Lesenswert?

Hallo,
Es kann schon sein, dass du Störsignale empfängst. Ich hatte auch ein 
ähnliches Problem. Versuch alle Netzteile fernzuhalten, Kabel möglichst 
kurz oder mal andere Orte ausprobieren. Und richte die Antenne grob 
Richtung Frankfut aus (sodass Antenne und die gedachte Linie Richtung 
Frankfurt einen rechten Winkel bilden). Du kannst die Signalqualität 
natürlich auch mit einem Oszilloskop überprüfen. Oder, falls nicht 
vorhanden, eine LED anschließen, oder per µC eine LED ansteuern (erstmal 
ohne Timer oä.) Da das Signal doch recht langsam ist, kann man schon was 
erkennen.

von Tobi F. (knuutt)


Lesenswert?

Vielen Dank für eure Antworten!

HildeK schrieb:
> TCNT1 ist doch der 16-Bit-Zähler des Counters. ICES1 sollte m.E. im
> TCCR1B-Register gesetzt werden.

Da hast du natürlich recht. Habe es im Code geändert. Danke.

Peter D. schrieb:
> Gibt doch mal den Pin auf ne LED aus.

Ich habe jetzt den Pin vom DCF77 direkt mit einer LED verbunden. Die LED 
sollte jetzt doch eigentlich (ungefähr) im Sekundentakt blinken, oder? 
Aber die 'flakert' ab und zu. D.h. ich habe erhalte zu viel Störsignale.

Peter D. schrieb:
> Die bevorzugte Methode ist z.B. alle 10ms per Timerinterrupt das Signal
> einzulesen. Die 100/200ms Pulsdauer und die 2s Pause kann man dann
> bequem mit je einem Byte abzählen.
> Die 10ms kann man gleichzeitig auch für die interne Zeitzählung bei
> Empfangsstörungen benutzen.

Danke. Ich denke ich werde es dann mal so probieren, wenn ich einen 
Position hier gefunden habe, wo nicht so viel Störungen sind.

von Tobi F. (knuutt)


Lesenswert?

Soo, der erste Schritt, die Binärzahlen aus dem DCF77-Modul zu 
decodieren und über die UART-Schnittstelle auszugeben, funktioniert 
schonmal. Ich bekomme zwar immer noch oft falsche Werte, aber es kommen 
auch ab und zu die richtige Bitfolge.

Für alle die es interessiert, hier mein Code:
1
ISR(TIMER1_COMPA_vect) {
2
  pulse_sync++;
3
4
  //If DCF77-Pin is "high" count pulse_wide
5
  if (PINB & (1 << PB0)) {
6
    pulse_wide++;
7
    dcf77_pin_low = 1;
8
    pulse_sync = 0;
9
  } else {
10
11
    if (dcf77_pin_low) {
12
      // pulse_wide >= 150ms => '1'
13
       if (pulse_wide >= 15) {
14
        usart_write("1");
15
        pulse_wide = 0;
16
        pulse_sync = 0;
17
      }
18
       // pulse_wide < 150ms => '0'
19
       else {
20
        usart_write("0");
21
        pulse_wide = 0;
22
        pulse_sync = 0;
23
      }
24
      dcf77_pin_low = 0;
25
      pulse_sync = 0;
26
    }
27
  }
28
29
  //linebreak at 59.bit/syncbit, pulse_sync => 180ms
30
  if(pulse_sync >= 180)
31
  {
32
    usart_write("\n %i\n", pulse_sync);
33
  }
34
}
35
36
void startClock(void) {
37
38
  // stop interrupts
39
  cli();
40
  
41
  TCCR1A = 0; // set entire TCCR1A register to 0
42
  TCCR1B = 0; // same for TCCR1B
43
  TCNT1 = 0; // initialize counter value to 0
44
45
  // set compare match register for 100 Hz increments
46
  OCR1A = 1249; // = (8000000 / (64* 100))-1
47
48
  // turn on CTC mode
49
  TCCR1B |= (1 << WGM12);
50
51
  // Set CS12, CS11 and CS10 bits for 64 prescaler
52
  TCCR1B |= (1 << CS11);
53
  TCCR1B |= (1 << CS10);
54
55
  // enable timer compare interrupt
56
  TIMSK |= (1 << OCIE1A);
57
  
58
  // allow interrupts
59
  sei();
60
}
61
62
63
int main(void) {
64
65
  //using usart for debugging
66
  usart_init(9600);
67
68
  DDRC = _BV(LED);   //LED as Output
69
  PORTC = _BV(LED); //Pull-up resistor LED
70
71
  PORTB = (1 << PD0); //Pull-up resistor DCF77
72
73
  //start clock
74
  startClock();
75
76
  usart_write("\nDCF 77 Debugger123\n\n");
77
78
  while (1)
79
  {
80
    LED_ON;
81
    _delay_ms(1000);
82
    LED_OFF;
83
    _delay_ms(1000);
84
  }
85
}

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.