Impulslängen DCF 77

OP #456112
Lesenswert?

ICh habs nun mal so versucht.... aber irgendwie funzt das nciht :(
1
#pragma vector=TIMERA0_VECTOR
2
__interrupt void Timer_A0 (void)
3
{
4

5
  if(P2IN & 0x01)
6
  {
7
   timecount += 1;
8
  }
9
 
10
  //position(2,1);
11
  //int2string(timecount,buffer);
12
  //printtext(buffer);
13
  
14
  if(timecount >= 8 && timecount <= 12)
15
  {
16
   position(2,1);
17
   printtext("0");
18
   timecount = 0;
19
  }
20
  
21
  if(timecount >= 18 && timecount <= 22)
22
  {
23
   position(2,1);
24
   printtext("1");
25
   timecount = 0;
26
  }
27
 
28
 CCR0 = 327;
29
}
#456236
Lesenswert?

In deiner Funktion wird timecount niemals den Wert
18 erreichen. Wenn timecount bis auf 8 hochgezählt
hat, detektierst du eine 0 und das wars dann auch schon.

Du sollst 1 Sekunde lang den Eingang alle 10 ms beobachten.
Wenn er in dieser 1 Sekunde 8 bis 12 mal 1 war, dann gilt
das als 0.

Du musst also die Interrupts mitzählen. Dein Interrupt tritt
alle 10 ms auf. Nach 100 Interrupts ist also 1 Sekunde vergangen.
Beim Start einer Sekunde setzt du den timecount auf 0.
Danach prüfst du bei jedem Interrupt den Zustand des
Port-Pins und zählst gegebenenfalls den timecount hoch.
Wenn der 100-ste Interrupt auftritt (also nach 1 Sekunde)
schaust du nach wie oft du eine 1 vorgefunden hast (du
wertest also den timecount aus).

Anstatt 100 würde ich vielleicht auf 90 gehen. An der
Anzahl in timecount ändert das nichts, aber du wirst
wahrscheinlich noch etwas Zeit brauchen um dich auf
die nächste 0-1 Flanke synchronisieren zu können.
Gast #456252
Lesenswert?

Diese Art Impulse auszumessen frisst unnötigerweise Rechenleistung, da 
alle 10ms ein INT ausgeführt wird. Dann lieber fallende und steigende 
Flanke auswerten Zeit messen und mit Toleranz bewerten. Damit kann ich 1 
und 0 festlegen. Alles was nicht 1 oder 0 ist muss ein Fehler sein, das 
heißt ich muss wieder von vorne anfangen die Bits zu zählen.
Gast #456253
Lesenswert?

@Sonic: Das ist nicht so ganz richtig. Der Interrupt kommt zwar alle 
10ms, kann aber extrem kurz gehalten werden. Die Auswertung der 
gemessenen Zeiten geschieht in der Main. So wie Du es mit dem ICP 
machst, hatte ich früher auch gearbeitet, bis ich feststellte, daß bei 
Störungen des DCF-Signals durch Maschinen oder Lampen der ICP bis zu 100 
mal pro Sekunde wild getoggelt wurde. An "Messen" war da nicht mehr zu 
denken. Zudem verfälschten kleine Störimpulse immer wieder die Messung. 
Da reichte schon das Einschalten einer Leuchstoffröhre und schon war das 
ganze Zeitprotokoll im Eimer. Durch die 10ms-Timer Variante kann man all 
diese Probleme umgehen.
#456271
Lesenswert?

In Programmen dieser Art benötigt man sowieso eine
Zeitbasis. Sei es für die Ausgabe auf gemultiplexten
7-Segmentanzeigen (ok, dann sind 10 ms nicht gerade viel)
oder sei es um die Uhr auch dann am laufen zu halten, wenn
das DCF Signal ausfällt. Ob diese Zeitbasis den DCF
Eingang noch zusätzlich beobachtet, fällt dann nicht
mehr wirklich ins Gewicht.
Gast #456324
Lesenswert?

@TravelRec.:
Um Fehler sauber erkennen zu können (Einschaltimpulse von 
Leuchtstofflampen sind welche) muss man den GANZEN Impuls messen, nicht 
in 10ms-Abständen. Wenn ich in Kauf nehmen will, dass ich einen Fehler 
nicht erkenne kann es halt passieren dass ein falsches Protokoll 
'rauskommt. Der Noise-Canceller vom ICP leistet bei mir sehr gute 
Dienste, habe so gut wie kein nicht vollständiges Protokoll.

>In Programmen dieser Art benötigt man sowieso eine Zeitbasis.

Stimmt. Die ist bei mir 1s (Timer1, RTC).
Ich will ja noch was Anderes machen als nur die Uhr laufen zu lassen, da 
kann's mit der Rechenleistung schon mal knapp werden, bzw. für 
Berechnungen etwas länger dauern.
(Firma: TravelRec.) Persönliche Seite #456336
Lesenswert?

>habe so gut wie kein nicht vollständiges Protokoll.

Ich auch nicht! Der NoiseCanceller des ICP überbrückt gerade mal 4 
CPU-Zyklen, für Störimpulse im oberen µs bis ms-Bereich absolut 
nonsense.

>Um Fehler sauber erkennen zu können (Einschaltimpulse von
>Leuchtstofflampen sind welche) muss man den GANZEN Impuls messen, nicht
>in 10ms-Abständen.

Ich messe den ganzen Impuls, im 10ms "Raster", nicht in 10ms 
"Abständen". Da die DCF-Signale 100 bzw. 200 ms lang sind, bekomme ich 
Zahlen von 8-12 für 100ms +-Toleranz und 18-22 für 200ms +-Toleranz. Ich 
will nicht Fehler erkennen, sondern DCF-Impulse. Die Fehlererkennung 
findet über die Prüfbits im DCF-Protokoll statt. Störimpulse an sich 
haben durch diesen programmtechnischen "Tiefpass" so gut wie keine 
Chance, es sei denn, der Empfang ist völlig hin und das Modul gibt nur 
noch wirres Zeug aus.
Gast #456370
Lesenswert?

>Ich messe den ganzen Impuls, im 10ms "Raster", nicht in 10ms "Abständen".

Ist genau das Gleiche! Du prüfst immer nur zu einem bestimmten 
Zeitpunkt, einen evt. Defekt des Moduls erkennst du so sehr schlecht. 
Kommt wohl immer drauf an wie man an die Sache 'rangeht. Ich prüfe nur 
auf Fehler (auch die Prüfbits), das vereinfacht die Programmierung.
Ist wie bei vielen Sachen: jeder hat seine bevorzugten Methoden.
#456380
Lesenswert?

Sonic wrote:

> Ich will ja noch was Anderes machen als nur die Uhr laufen zu lassen, da
> kann's mit der Rechenleistung schon mal knapp werden, bzw. für
> Berechnungen etwas länger dauern.

Also bei 4MHz Quarz und reichlich geschätzten 40 Zyklen für den 10ms 
Interrupt komme ich auf ne Wahnsinns-CPU-Belastung von 0,1% !

Kann mir keiner erzählen, daß er 0,1% merkt.


Peter
Gast #456400
Lesenswert?

@Peter:
Ich weiß ja nicht ob du nur einzelne Programmfunktionen programmierst, 
bei mir laufen ab und zu auch mal mehrere Funktionen auf einem µC. Eine 
Uhr, se es DCF oder RTC odr beides zusammen sind reine 
Hintergrundfunktionen, die möglichst gar nicht ins Gewicht fallen 
sollten. Sobald ich meinen Programmablauf alle 10ms durch einen INT, sei 
er noch so kurz gehlten, unterbreche, sind andere zeitkritische 
Funktionen sehr schwer zu realisieren.
Aber wie gesagt: jeder wie er will, mir isses halt nach meiner Methode 
lieber.
#456407
Lesenswert?

Sonic wrote:

> sollten. Sobald ich meinen Programmablauf alle 10ms durch einen INT, sei
> er noch so kurz gehlten, unterbreche, sind andere zeitkritische
> Funktionen sehr schwer zu realisieren.

Wenn ein Interrupt stört, dann isses vollkommen egal, wie oft er kommt.
Ein 1s Interrupt stört genau so, er stört nur seltener.


Wenn Interrupts stören, mußt Du entweder Dein Programm umstellen oder 
Interrupts zeitweise verbieten.
Und nur, wenn dieses zeitweise Verbieten länger als 10ms dauert, geht 
der 10ms Interrupt in die Hose.


Ich versuche allerdings das Hauptprogramm immer so zu schreiben, daß 
Interrupts nicht stören, egal welche.


Peter

P.S.:
10ms ist doch auch eine gute Zeit für die Tastenentprellung.
Gast #456416
Lesenswert?

>>Ich messe den ganzen Impuls, im 10ms "Raster", nicht in 10ms "Abständen".

>Ist genau das Gleiche! Du prüfst immer nur zu einem bestimmten
>Zeitpunkt, einen evt. Defekt des Moduls erkennst du so sehr schlecht.

Naja - ist es nicht. Der Timer guckt zwar nur alle 10ms, aber wenn die 
Impulse außerhalb der vorgegebenen Fenster - von 20ms nach oben und 
unten - liegen, wird dies auch als Fehler gesehen. Kommen ständig 
Fehlimpulse, ist der Empfang gestört oder das Modul defekt. Eindeutiger 
geht´s nicht.
Gast #456719
Lesenswert?

Wieso, alles unter 8 ist Murks, 8,9,10,11,12 ist Null / größer 12 und 
kleiner 18 ist Murks, 18,19,20,21,22 ist Eins, alles über 22 ist Murks, 
rund um 100 ist die Austastsekunde 59 - willst Du´s noch genauer? Mein 
Controller verwechselt da nix und weiß eigentlich sofort, was Null und 
Eins ist. Wie gesagt: unter normalen Bedingungen empfange ich keine 
Fehlprotokolle, eine Kontroll-LED zeigt mir den aktuellen Status an. Die 
einzig nennenswerten Probleme treten bei Gewittern in unmittelbarer Nähe 
auf. Dann tritt die interne Quarzuhr in Betrieb.
Gast #456723
Lesenswert?

Ich denke wir sollten es dabei bewenden lassen, dass beide Möglichkeiten 
gut funktionieren. Hier weiterzudiskutieren macht wenig Sinn. wie ich 
oben schon erwähnte, jeder ist halt von seiner Variante überzeugt. 
Möglicherweise ist von Fall zu Fall die Eine oder Andere Version 
angebrachter.
OP #456740
Lesenswert?

theoretisch klar ist bis jetzt alles....

hier mal eine neue Version:
1
// Timer A0 interrupt service routine
2
#pragma vector=TIMERA0_VECTOR
3
__interrupt void Timer_A0 (void)
4
{
5
  _DINT();
6
  
7
  intcount += 1;
8
  
9
  if(P2IN & 0x01)
10
  {
11
   timecount += 1;
12
  }
13
 
14
  if(intcount > 98)
15
  {
16
    if(timecount >= 8 && timecount <= 12)
17
    {
18
     position(2,1);
19
     printtext("0");
20
     timecount = 0;
21
    }
22
  
23
    if(timecount >= 18 && timecount <= 22)
24
    {
25
     position(2,1);
26
     printtext("1");
27
     timecount = 0;
28
    }
29
    intcount = 0;
30
  }
31
 
32
 CCR0 = 327;
33
 _EINT();
34
}


Müsste soweit klappen.... teste grade

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren