Forum: Mikrocontroller und Digitale Elektronik DCF Signal an INT1 von Atmega32 Problem


von derheld2k1 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe schon sämtliche relevante Beiträge gelesen, aber es war nichts 
dabei was mir weiterhelfen hätte können...

Nun zu meinem Problem:
Ich habe das reichelt DCF Modul an den INT1 Eingang gehängt und den 
Interrupt so eingestellt, dass er bei steigender Flanke auslöst.
Ich habe in die ISR einen einfachen Pintoggle reingeschrieben um zu 
überprüfen ob die Interrupts so kommen wie ich mir das vorstelle..
Wenn ich das Programm nun laufen lasse, sehe ich auf dem Oszi, dass der 
Interupt manchmal nicht , manchmal doppelt und meistens normal ausgelöst 
wird.

Die blaue Kurve ist das DCF Signal, gelb ist der Pintoggle. (Bild im 
Anhang)
Das DCF Modul hängt ohne Pullup und ohne serienwiderstand am INT1. (mit 
Pullup getesten, auch keine Besserung)

Hat jemand eine Idee, an was das liegt oder noch besser einen Vorschlag 
wie das Problem beseitigt werden kann.

mfg, Alex

von Der Dude (Gast)


Lesenswert?

Dehne doch das Signal in der Zeitachse etwas und schau nach, ob Du 
irgendwelche Spikes entdeckst.

von Alex K. (derheld2k1)


Lesenswert?

Das habe ich schon getan... der Screenshot ist nur zum Überblick so 
gewählt worden.. das Signal prellt nicht und auch keine Spikes..

mfg

von Der Dude (Gast)


Lesenswert?

Zeig doch mal Deinen Code.

von Alex K. (derheld2k1)


Lesenswert?

Hier der Code von der ISR:
ISR(INT1_vect)
{

  if(ms_counter == 0)
  {
    PORTA |= (1 << PA3);    //switch off backlight


    ms_counter++;
  }
  else if(ms_counter==1)
  {
    PORTA &= ~(1 << PA3);    //switch on backlight

    ms_counter = 0;
        }
}

und hier der Teil aus der main der den Interrupt initialisiert:
/*setup external interrupt 1 for dcf sync*/
  MCUCR |= (1<<ISC10) | (1<<ISC11);  //rising edge
  GICR |= (1<<INT1);

von Der Dude (Gast)


Lesenswert?

probier doch mal

ISR(INT1_vect)
{
    PORTA ^= (1 << PA3);    //toggle backlight
}

von Der Dude (Gast)


Lesenswert?

wie ist  ms_counter deklariert?

von Alex K. (derheld2k1)


Lesenswert?

leider selbes Verhalten

von Alex K. (derheld2k1)


Lesenswert?

int ms_counter;

von Der Dude (Gast)


Lesenswert?

volatile int ms_counter;

(volatile char täte auch reichen)

von Alex K. (derheld2k1)


Angehängte Dateien:

Lesenswert?

immer noch selbes verhalten.. auch mit char
hier nochmal n screenshot, da dieser Effekt bei dem anderen nicht 
dargestellt ist

von Der Dude (Gast)


Lesenswert?

Ich habe ähnlichen Ärger schon mit dem Pollin-DCF gehabt. Da kam während 
der negativen Flanke nochmal ganz kurz ein Ausreisser nach oben, der mir 
einen erneuten Interrupt ausgelöst hat.

War schwer zu finden, da wirklich sehr kurz.

Du solltest das Signal etwas genauer untersuchen - ordentlich in die 
Länge dehnen und die fallende Flanke ansehen.

von Besserwisser (Gast)


Lesenswert?

Also, ich finde die 1. Version von Dude besser. Keine Variable und das 
Ganze geht viel schneller.
1
ISR(INT1_vect)
2
{
3
    PORTA ^= (1 << PA3);    //toggle backlight
4
}

Falls PORTA noch irgendwo anders benutzt wird könnte Dir das natürlich 
noch reinfunken. Also Code am besten auf den INT und eine Endlosschleife 
reduzieren.

von Alex K. (derheld2k1)


Angehängte Dateien:

Lesenswert?

die fallenden Flanken sind sauber..
hier ein Shot, bei dem der Fehler auftritt

von Alex K. (derheld2k1)


Angehängte Dateien:

Lesenswert?

... und hier wärs in ordnung

von Der Dude (Gast)


Lesenswert?

Evtl. sind dann die Portpins nicht richtig konfiguriert?

wie schaut die main aus?

von Alex K. (derheld2k1)


Lesenswert?

@besserwisser: ok.. erstell eben n neues projekt.. dauert kurz

von Alex K. (derheld2k1)


Lesenswert?

1
/*includes*/
2
#include "startup.h"
3
#include "globals.h"
4
#include <avr/io.h>      //standart IO functions
5
#include <avr/interrupt.h>  //interrupt functions
6
7
8
/*beginn of main*/
9
int main(void)
10
{
11
  //initialize pins on PORTA and LCD_PORT
12
  PORTA = 0b00010000;    //Pin 0-7 to low, except pin 4
13
  DDRA = 0b11111111;    //Pin 0-2 as output (SCK, RCK, SER)
14
              //Pin 4-7 as output (display_on_off, RS, R/W, E)
15
  PORTB = 0b00000000;    //Pin 0-7 to low
16
  DDRB = 0b11111111;     //Pin 0-7 as output (DB0 - DB7)
17
18
  DDRD = 0x00;      //input to switch on/off backlight of lcd and dcf signal
19
  //PORTD |= (1<<PD3);     internen Pull-Up an PC7 aktivieren 
20
21
  
22
  /*setup the timer0 & 1*/
23
  cli();          //interrupts disabled
24
  setup_timer0();
25
  setup_timer1();
26
  sei();          //global interrupts enabled
27
28
  /*setup external interrupt 0 for display switch*/
29
  MCUCR |= (1<<ISC00) | (1<<ISC01);  //rising edge
30
  GICR |= (1<<INT0);
31
  
32
  /*setup external interrupt 1 for dcf sync*/
33
  MCUCR |= (1<<ISC10) | (1<<ISC11);  //rising edge
34
  GICR |= (1<<INT1);          //enable external int request 0
35
36
  /*initialize lcd*/
37
  int i;
38
  for(i=0; i<3000; i++)   //wait 150ms for display to be ready
39
      asmdelay50();
40
  lcd_init();
41
42
  /*initialize global variables*/
43
  time = 0;
44
  
45
  while(1)
46
  {
47
    /*calculate bitpattern for shiftregisters*/
48
    generate_outarray();
49
50
    /*output the bitpattern to the shiftregisters*/
51
    led_out();
52
53
    /*output the time to the lcd if enabled via switch*/
54
    if(lcd_switch==0)
55
      lcd_out();
56
  }
57
 
58
  return(0);  //never reached
59
}
60
/*end of main*/
61
62
63
64
/*additional functions for use with main function*/
65
/*-----------------------------------------------------------------------
66
/ functionname: setup timer1()
67
/ behaviour:  setups the timer1 module with following attributes:
68
/        -timebase 1 second (prescaler 1024, compare value 15625)
69
/        -generate interrupts if compare match A
70
        -no PWM, normal operation
71
/----------------------------------------------------------------------*/
72
void setup_timer1()
73
{
74
  TCCR1B |= (1<<CS10) | (1<<CS12);    //clock prescaler set to 1024
75
  OCR1A = 0x3D09;            //compare value set to 15625
76
  TIMSK |= (1<<OCIE1A);        //enable compare match interrupt with compare value A
77
}
78
79
80
/*-----------------------------------------------------------------------
81
/ functionname: setup timer1()
82
/ behaviour:  setups the timer1 module with following attributes:
83
/        -timebase 1 second (prescaler 1024, compare value 15625)
84
/        -generate interrupts if compare match A
85
        -no PWM, normal operation
86
/----------------------------------------------------------------------*/
87
void setup_timer0()
88
{
89
  TCCR0 |= (1<<CS00) | (1<<CS02);    //clock prescaler set to 1024
90
  OCR0 = 0x9C;            //compare value set to 156
91
//  TIMSK |= (1<<OCIE0);        //enable compare match interrupt timer0
92
}

von Alex K. (derheld2k1)


Lesenswert?

@besserwisser:

hi hab des jez so gemacht, aber immer noch identisches verhalten,
hier der Code der übrigblieb:
1
#include <avr/io.h>      //standart IO functions
2
#include <avr/interrupt.h>  //interrupt functions
3
4
5
/*beginn of main*/
6
int main(void)
7
{
8
  PORTA = 0b00010000;    //Pin 0-7 to low, except pin 4
9
  DDRA = 0b11111111;    //Pin 0-2 as output (SCK, RCK, SER)
10
11
  DDRD = 0x00;      //input to switch on/off backlight of lcd and dcf signal
12
  
13
  sei();          //global interrupts enabled
14
  
15
  /*setup external interrupt 1 for dcf sync*/
16
  MCUCR |= (1<<ISC10) | (1<<ISC11);  //rising edge
17
  GICR |= (1<<INT1);          //enable external int request 0
18
  
19
  while(1){}
20
  
21
 
22
  return(0);  //never reached
23
}
24
25
26
ISR(INT1_vect)
27
{
28
29
  PORTA ^= (1 << PA3);
30
          
31
}

von Der Dude (Gast)


Lesenswert?

schaut eigentlich gut aus...seltsam...

Was verwendest Du als Speisespannung?

von Alex K. (derheld2k1)


Lesenswert?

5V aus nem 7805 ohne S,L oder sonstwas ;)
natürlich mit diversen C's davor und dahinter gegen masse

von Der Dude (Gast)


Lesenswert?

Hast Du noch einen anderen mega32 zum Testen? Glaub ja nicht, dass der 
hin ist, aber wer weiss...

von Alex K. (derheld2k1)


Lesenswert?

leider nicht griffbereit.. aber das kann ich bis morgen ändern...
ich test mal noch kurz wies beim INT0 ausschaut...

von Der Dude (Gast)


Lesenswert?

Was mir auch suspekt erscheint...auf dem Oszillogramm von  18:48 
wechseln beide Signale exakt gleichzeitig den Pegel. Woher kommt das?

von Der Dude (Gast)


Lesenswert?

Hängt eine fette Last an PA3? Mach den mal unbelastet.

von Alex K. (derheld2k1)


Lesenswert?

das mit dem gleichzeitigen Signalwechsel kann ich mir auch nicht 
erklären...
manchmal springt er auch bei fallender flanke in die isr, manchmal 
"übersieht" er ne steigende...

der Test mit INT0 und dem abgespecktem Code zeigt auch wieder das selbe 
Verhalten.

von Alex K. (derheld2k1)


Lesenswert?

an PA3 hängt aussschließlich das Oszi dran

von Analog (Gast)


Lesenswert?

Probier es mal mit einem Pulldown 10k-100k an der INT-Leitung. 
Alertantiv einen Tiefpass-Kondensator. Ich vermute auch Spikes. Wie hoch 
ist die Abtastrate Deines Oszis ?? Vielleicht kann es diese Spikes nicht 
mitschneiden. Außerdem kannst Du auch noch den Takt vom Atmega mal ganz 
runter setzen auf 1MHz, dann ist der Interrupt vielleicht zu träge für 
die Spikes  und es passiert nicht mehr.

von Der Dude (Gast)


Lesenswert?

Hast Du einen Rechteckgenerator? Da kannst schon mal den DCF als 
Fehlerquelle ausschliessen.

von Der Dude (Gast)


Lesenswert?

Pulldown und Tiefpass geht nicht, da der DCF nur einige uA treiben kann.

von Analog (Gast)


Lesenswert?

Das mit dem Takt ist nur als Nachweis gemeint. Ich wollte das nicht als 
Lösung für das Problem vorschlagen. Wenn es Störungen gibt, dann 
brauchst Du ein Filter.

von Besserwisser (Gast)


Lesenswert?

Tja, der abgespeckte Code sieht eigentlich gut aus. Sehe jedenfalls 
keine Fehlermöglichkeiten.

Das das Signal teilweise zu identischen Zeiten wechselt ist merkwürdig.
Ist das selbstgelötet? Vielleicht hast Du da aus Versehen einen Schluss 
gemacht, der ein wenig halblebig ist und deswegen, wenn Du am Tisch oder 
sonstwo wackelst auch mal einen INT auslöst wenn keiner sein sollte.

von Der Dude (Gast)


Lesenswert?

Ich habe meine Störungen beim Pollin-Modul softwaremässig erschlagen.

Aber dazu muss man erst mal genau wissen, was los ist.

von Alex K. (derheld2k1)


Lesenswert?

@dude: rechteckgenerator ist auch erst morgen verfügbar
@analog: 10k pulldown drück das signal soweit, dass INT0 gar nicht mehr 
reagiert; samplingrate ist nicht berauschend.. is n 500 euro DSO.. 2,5 
KS / s ;AVR runtertakten is keine gute idee, weil der doch noch einiges 
zu verarbeiten bekommt..

von Besserwisser (Gast)


Lesenswert?

@ Alexander
Hast Du mal nach nem Schluss geguckt?
Tut mir, aber ich bin echt gespannt, ob es das ist.

von Der Dude (Gast)


Lesenswert?

Stell den Interrupt doch mal auf fallende Flanken und schau, was er da 
macht.

von Alex K. (derheld2k1)


Lesenswert?

@besserwisser: ist auf nem steckbrett gesteckt, rüttelt aber nix und 
sonst geht auch alles immer reibungslos damit (ints kommen auch wenn ich 
vom anderen zimmer aus rüberschau ;) )

@analog: werd morgen zum test mal den generator dranhängen

von Der Dude (Gast)


Lesenswert?

Du kannst auch ein Rechteck mit dem uC selbst erzeugen OCR1A z. B. und 
ihm selbst ant INT1 einspeisen

von Besserwisser (Gast)


Lesenswert?

> (ints kommen auch wenn ich vom anderen zimmer aus rüberschau ;) )
Mmh. Merkwürdig.
Dann ist wohl der Vorschlag von Dude im Moment am besten.

von Alex K. (derheld2k1)


Lesenswert?

@besserwisser: 100% kein schluss
@dude: mit fallenden Flanken wieder dasselbe Verhalten; muss ich beim 
rechteckerzeugen auf irgendwas spezielles achten (habe das noch nie 
gemacht)

von Der Dude (Gast)


Lesenswert?

Das kann nur am DCF-Signal liegen. Alles andere ist Voodoo.

von Der Dude (Gast)


Lesenswert?

> muss ich beim rechteckerzeugen auf irgendwas spezielles achten

Nein, eigentlich nicht. Einen Timer in CTC betreiben und den zugehörigen 
OCR-Pin toggeln und mit INT1 verbinden.

Kannst ja auch 1 Hz ca wählen, ist unkritisch.

von AVRFan (Gast)


Lesenswert?

>AVR runtertakten is keine gute idee,

Gibt aber ein Äquivalent dazu: Den DCF77-Portpin einfach fortlaufend 
alle z. B. 10 ms (generiert von Software-Timer) sampeln.  Erschlägt Dein 
Problem aus prinzipiellem Grund, weil das Sampling wie ein Tiefpass 
wirkt.  Funktioniert bestens.  CPU-Last ist vernachlässigbar (0.01%). 
Musst Dich nur von dem Interrupt verabschieden.

von Alex K. (derheld2k1)


Lesenswert?

ich werd das DCF Modul morgen mit in die Arbeit nehmen... da stehn 
schicke Tektronix mit 2GS/s rum

von Alex K. (derheld2k1)


Lesenswert?

@AVRFAn: hmm wenn alles andere versagt werd ichs so machen, danke für 
den Vorschlag, allerdings will ich es schon mit dem INT0 machen

von Der Dude (Gast)


Lesenswert?

Da hast Du aber nicht die gleiche HF-Umgebung wie zuhause. Wenn Du mit 
dem schicken Teil nichts findest, heisst das gar nichts.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

derheld2k1 wrote:
> Hallo zusammen,
>
> Nun zu meinem Problem:
> Ich habe das reichelt DCF Modul an den INT1 Eingang gehängt und den
> Interrupt so eingestellt, dass er bei steigender Flanke auslöst.

Es ist üblich, dass DCF-Empfang gestört wird, etwa durch

-- Monitor, PC, ...
-- Wetterlage
-- Schaltnetzteil
-- µC in unmittelbarer Nähe
-- Atombomben
-- weiss der Teufel

DCF an einen INT-Port zu hängen ist keine so tolle Idee, weil

1) verbraucht das nen wertvollen INT-Port
2) das Signal wie gesagt nicht sauber ist

Stattdessen empfiehlt sich ein Vorgehen wie bei Tasterentprellung. ZB 
indem man einfach alle 10ms auf den Port schaut -- das dann aber gerne 
in einer ISR.

Danach kann man Spratzer ausbügeln, also Bitfolgen (hier gesamplet alle 
10ms) wie 0001000 ersetzen durch 000000.

Bei extrem mieser Empfangslage muss man zusätzlich über mehrere Minuten 
sammeln und Bits reparieren. Ein Voting wie "2 aus 3" ist aber nicht so 
einfach zu implementieren, weil sich die Nutzdaten ja ändern. Da 
brauch's also etwas mehr Gehirnschmalz.

von Alex K. (derheld2k1)


Lesenswert?

@dude: bekomme das mit dem timer grad nicht auch die schnelle so 
gebacken, werds morgen mit generator machen

@johann: der empfang war anfangs extrem gestört, habe dass aber dank 
laptop statt desktop rechner und verlagern des empfängers mittels 2m 
kabel ans fenster in griff bekommen, das Signal sieht ja sehr sauber 
aufm Oszi aus.
Aber langsam bin ich auch am zweifeln ob das mit dem INT so ne gute idee 
ist.
Werd mich mal kurz hinsetzen und des Signal samplen, muss ich ja eh 
machen wenn ich die dauer von den "highs" messe um die bits zu 
bestimmen, aber das wollte ich eben dann angestossen durch den interrupt 
machen "lassen". Und gestörte Daten werf ich einfach weg, indem ich sie 
mit der aktuellen zeit vergleiche und er solls nochmal versuchen..

von Der Dude (Gast)


Lesenswert?

Das Sampeln findest Du einfacher als einem Timer ein Rechteck zu 
entlocken?

Die Wege des Herrn sind oftmals unergründlich.

von Alex K. (derheld2k1)


Lesenswert?

lol momentan ja ;)

von Alex K. (derheld2k1)


Lesenswert?

so, im moment komm ich nicht mehr weiter.. mein hirn is einfach voll 
(häng da schon den ganzen tag dran)
hier noch die letzten zeilen code die ich zum samplen geschrieben hab, 
funktioniert aber noch nicht. der timmerinterrupt kommt jede ms, daher 
läuft das array schnell voll und nicht erst nach ner minute. Wer lust 
und laune hat des schnell auszubessern ist herzlich eingeladen. 
Ansonsten vielen Dank für die schnelle und ausführliche Hilfe, ich werde 
morgen weiter berichten.
mfg
1
ISR(TIMER0_COMP_vect)
2
{
3
  if(PIND & (1<<PIND3))
4
    dcfsignaltime++;
5
6
  else if(!(PIND & (1<<PIND3)))
7
  {  
8
    if((dcfsignaltime > 80) && (dcfsignaltime < 140))
9
      dcf_bit[dcf_bitcounter] = 0;
10
11
    else if((dcfsignaltime > 170) && (dcfsignaltime < 260))
12
      dcf_bit[dcf_bitcounter] = 1;
13
14
    dcfsignaltime = 0;
15
    dcf_bitcounter++;
16
    if(dcf_bitcounter == 57)
17
      dcf_bitcounter = 0;
18
  }
19
  TCNT0 = 0x0;  //reset timer count value
20
}

von Alex K. (derheld2k1)


Lesenswert?

Nachtrag:
angenommen es sind doch spikes im DCF signal und ich wills doch mitn 
INT1 machen, würde es dann helfen mit RC ladekurve n schmittrigger 
anzusteuern?
eigentlich schon oder überseh ich da in meiner momentanen Verwirrtheit 
etwas?

von Besserwisser (Gast)


Lesenswert?

>es dann helfen mit RC ladekurve n schmittrigger anzusteuern

Ich würde sagen, es lohnt den Versuch. Das mit dem RC-Tiefpass hat ja 
auch am Anfang jemand vorgeschlagen. Grenzfrequenz kann ja sehr niedrig 
sein. Hauptsache die 100ms kommen noch durch.

von AVRFan (Gast)


Lesenswert?

>würde es dann helfen mit RC ladekurve n schmittrigger anzusteuern?

Möglich, aber wozu extra Hardware-Aufwand treiben, wenn sich das Problem 
rein softwaremäßig in nullkommanix erschlagen lässt?  Nochmal: Dem 
Samplen haftet genau die gewünschte Tiefpass-Charakteristik an.  Was 
willst Du noch?

von AVRFan (Gast)


Lesenswert?

>der timmerinterrupt kommt jede ms, daher läuft das array schnell voll

Tipp: 10 ms.  Ein Array ist überflüssig.  Du brauchst doch nur den 
aktuell gesampelten Wert und den Vorgängerwert, um jede Flanke 
detektieren zu können.  Eine Speicherqueue der Länge 1, d. h. eine 
simple Variable zum Zwischenspeichern des aktuellen Werts bis zum 
nächsten "Tick", reicht also. Die DCF77-Decodier-Zustandsmaschine rufst 
Du natürlich auch alle 10 ms auf. Nicht erst 200 Samples in einem Array 
sammeln und die Maschine danach 200-fache Arbeit erledigen lassen - das 
ist Nonsens.  Immer gleich jedes Sample sofort verarbeiten - das ist bei 
schnarchlahmen 10 ms kein Problem und  bzgl. des Rechenaufwands 
dasselbe, aber Du brauchst kein Array.

von Alex K. (derheld2k1)


Lesenswert?

Hallo nochmal,

habe das Problem jetzt gelöst indem ich wie AVRFan geraten hat, das 
Signal zu samplen ohne Interrupt eingang. Funktioniert bestens, auch den 
Signalbeginn erkennt die software.

Vielen Dank nochmal für die schnelle Hilfestellungen.
mfg

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.