PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : DCF-77 mit Bascom 1.11.8.6



for_ro
26.04.2007, 22:55
Hallo zusammen,
ich habe mir gerade mal testweise die neue DCF-Routine angesehen.
Programm wie in der Hilfe, config so
Config Dcf77 = Pind.1 , Debug = 1 , Inverted = 1 , Check = 0 , Update = 1 , Updatetime = 3 , Switchpower = 1 , Powerpin = Pind.4 , Powerlevel = 1 , Timer1sec = 1 , Timer = 1
Wenn ich mir die Impulslängen ansehe, dann kommt fast immer 4 (für eine 0) oder 8 (für eine 1).
Manchmal allerdings kommt auch 3 oder 7. Beide führen dann zu einer 0 im Ergebnis an einer Stelle, wo bei der 7 wohl eine 1 sein sollte. Die Zeit verwirft die Routine dann, wohl wegen Parity Fehler.
Die 7 kommt so oft, dass es manchmal 10 Minuten dauert, bis er die Zeit richtig gelesen hat. Die Checks musste ich dabei abschalten, sonst schafft es die Routine überhaupt nicht. Andere Werte von Secondticks machen keinen Unterschied.
Kann man da irgendetwas dran einstellen? Ich finde nichts und habe schon alles mögliche ausprobiert.

Wie kann ich sowas wie die alte Sectic isr benutzen um einmal pro Sekunde etwas zu tun? Timer1sec verstehe ich nicht.

Danke für eure Hilfe

Gruß

Rolf

oe9vfj
27.04.2007, 11:06
Hallo Rolf,

Beginne mal mit der Grundkonfiguration:


CONFIG DCF77 = PinX.y, Timer=1, Debug = 1

und einem Ort mit einem sauberen DCF-Empfang um die Funktion zu testen. Der Parameter DEBUG wird nur benötigt um die Impulslängen festzustellen.
Der Compiler nimmt wenn von der Quarzfrequenz her möglich, einen Timer-Interrupt von 40 pro Sekunde. Im Kompiler-Report kann man bei der Konstante _CDCF_SECONDTICS den Wert kontrollieren. Bei 'unüblichen' Quarzfrequenzen wird ein Wert zwischen 32 und 128 möglichst nahe bei 40 gewählt, welche die geringste Zeitabweichung gewährleistet.
Bei einem Timer-Interrupt von 40 wird dieser alle 25 mSec (1000mSec/40) ausgelöst. Mit diesem zeitlichen Abstand wird der Pegel des DCF77-Signals getestet.
Man kommt dann auf deine erwähnten Werte von 4 für Bit0 (4*25mSec=100mSec) und 8 für Bit1 (8*25mSec=200mSec). Da ja die Pegelabtastungen und das DCF-Signal nicht synchron sind, kann dieser Wert auch mal um 1 höher oder niedriger sein. Also 3, 4, oder 5 für Bit0 und 7, 8 oder 9 für Bit1. Der Grenzwert zwischen Bit 0 oder 1 definiert die Konstante CDCF_BIT1. In diesem Beispiel ist dieser 6. Das heißt, dass Impulslängen größer gleich 6 als Bit1 interpretiert werden.

Timer1Sec:
Es gibt die Möglichkeit (Parameter UPDATE) die Zeit kontinuierlich (0), stündlich (1) oder täglich (2) synchronisieren zu lassen. Bei stündlicher oder täglicher Synchronisation erfolgt in der Zwischenzeit keine DCF77-Signal Auswertung. Das gibt die Möglichkeit in dieser Zeit den Timer-Interrupt auf 1 mal pro Sekunde zu reduzieren, da dieser ja dann nur die SOFT-CLOCK bedienen muss. Dies reduziert die Zeit, welche die CPU mit dieser Interrupt-Routine verbringt.
Weiters kann in dieser Zeit speziell in Batterie/Akku betriebenen Geräten der DCF77-Empfänger abgeschaltet werden. Dazu dienen die Parameter SWITCHPOWER, POWERPIN und POWERLEVEL.


SecondTicks sollte nur dann verwendet werden, wenn man in den Timer-Interrupt noch eine eigene Routine mit einem anderen Takt hängen will. Dieser kann aber nur höher sein als der vorgegebene Wert.

SECTIC ist derzeit nicht berücksichtigt, sollte aber meines Erachtens kein Problem sein, diese in zukünftige Releases zu implementieren.

Siehe auch: https://www.roboternetz.de/phpBB2/viewtopic.php?t=29977

Falls Du weiterhin Probleme hast, kannst du die Ausgabe des Test-Programmes in deinem Post als Attachement anfügen. Vielleicht ist dann eine Beurteilung des Problems möglich.

for_ro
27.04.2007, 11:51
Hallo Josef,
erst mal danke für die Erklärungen.
Ich habe jetzt festgestellt, dass mal mit 40 mal mit 50 Interrupts pro Sekunde gescannt wird. Bei 40 ist auch alles ok, die Längen 6 und 7 werden als '1' erkannt. Aus mir nicht verständlichen Gründen - kein Wechsel der Quarzfrequenz - läuft die Routine nach neuflashen häufig mit 50 Interrupts, und dann kommt genau das Problem. Und da scheint die Grenze bei 8 zu liegen.




SECTIC ist derzeit nicht berücksichtigt, sollte aber meines Erachtens kein Problem sein, diese in zukünftige Releases zu implementieren.


Heisst das, das es im Moment keine Möglichkeit gibt, selber noch Code in den 1-Sekunden Interrupt zu hängen, so wie das bisher mit der Soft-Clock ging? Config Clock kann ich ja nicht mehr benutzen. Oder kann ich für den Timer1 eine Interrupt Routine angeben, die dann zusätzlich zu deiner aufgerufen wird?

Siehe auch: https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=29977 habe ich aufmerksam gelesen, beantwortet aber nicht die Fragen.

Gruß

Rolf

oe9vfj
27.04.2007, 12:28
Hallo Ralf,

Ich hänge Dir eine neue Version der DCF77.LBX an mit welcher SECTIC funktionieren sollte. Die Konfiguration erfolgt aber nicht in der CONFIG - Zeile, sondern bis zur endgültigen Implementation in den Compiler bitte die Zeile

Const _sectic = 1

einfügen.

Willst Du SECTIC nicht verwenden, musst Du vorerst mit dieser LBX-Version auf Const _Sectic = 0 ändern, da es ansonsten einen Error gibt.


Vielleicht kannst Du noch Deinen Code posten, der manchmal 40 oder 50 ticks erzeugt.

Benenne die Datei dcf77.txt in dcf77.lbx um und kopieren diese in den LIB Pfad. (Mache vorher eine Sicherungskopie deiner bisherigen dcf77.lbx)

Die Änderung habe ich noch nicht gründlich getestet, Test-Report sind daher willkommen.

for_ro
27.04.2007, 13:18
Hallo Josef,
werde ich mal ausprobieren, geht aber erst heute abend.
Ich versuche mal zwei Versionen zu finden, die sicher zu 40 und 50 ticks führen. Dann kannst du sehen, ob das reproduzierbar ist.

Gruß

Rolf

for_ro
27.04.2007, 18:25
Hallo Josef,
dieser code


$crystal = 16000000
$regfile = "m128def.dat"
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 128 'default use 10 for the SW stack
$framesize = 128 'default use 40 for the frame space

Config Graphlcd = 240 * 128 , Dataport = Portc , Controlport = Porta , Ce = 5 , Cd = 4 , Wr = 1 , Rd = 0 , Reset = 6 , Fs = 7 , Mode = 6
Config Dcf77 = Pind.1 , Debug = 1 , Inverted = 1 , Check = 0 , Update = 1 , Updatetime = 30 , Switchpower = 1 , Powerpin = Pind.4 , Powerlevel = 1 , Timer1sec = 0 , Timer = 1
Enable Interrupts
Config Date = Dmy , Separator = .
Cls
Cursor Off

Do

Locate 1 , 1 : Lcd Time$ ; " " ; Date$
Locate 2 , 1 : Lcd Time(dcf_sec) ; " " ; Date(dcf_day)
Locate 3 , 1 : Lcd Bin(dcf_status) ; " " ; Bin(dcf_bits)
Locate 4 , 1 : Lcd Bdcf_impuls ; " " ; Bdcf_pause
Loop
End


compiliert zu 40 ticks. Dann habe ich keine Probleme mit den '1'. Wenn ich timer1sec=1 schreibe, compiliert er zu 50 ticks.

Gruß

Rolf

for_ro
27.04.2007, 18:34
Hallo Josef,
sectic aufrufen geht ausgezeichnet.



$crystal = 16000000
$regfile = "m128def.dat"
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 128 'default use 10 for the SW stack
$framesize = 128 'default use 40 for the frame space
Const _sectic = 1
Config Graphlcd = 240 * 128 , Dataport = Portc , Controlport = Porta , Ce = 5 , Cd = 4 , Wr = 1 , Rd = 0 , Reset = 6 , Fs = 7 , Mode = 6
Config Dcf77 = Pind.1 , Debug = 1 , Inverted = 1 , Check = 0 , Update = 1 , Updatetime = 30 , Switchpower = 1 , Powerpin = Pind.4 , Powerlevel = 1 , Timer1sec = 0 , Timer = 1
Enable Interrupts
Config Date = Dmy , Separator = .
Cls
Cursor Off

Do
nop
Loop
End

Sectic:
Locate 5 , 1 : Lcd Time$ ; " " ; Date$
Locate 6 , 1 : Lcd Time(dcf_sec) ; " " ; Date(dcf_day)
Locate 7 , 1 : Lcd Bin(dcf_status) ; " " ; Bin(dcf_bits)
Locate 8 , 1 : Lcd Bdcf_impuls ; " " ; Bdcf_pause
Return

Der Wechsel von 40 nach 50 ist hierbei übrigens auch.
Ich werde die Routine jetzt mal in mein Programm einbauen und sehen, was passiert.

Schon mal vielen Dank.

Gruß

Rolf

oe9vfj
27.04.2007, 20:55
Hallo Rolf,

Beachte aber, dass die in SECTIC 'verbratene' Zeit deutlich unter der Zeit liegen sollte, die ein Timer-Tick braucht (Bei 40 Interrupts pro Sekunden sind das weniger als 25mSec) ansonsten gehen Timer-Interrupts verloren, was nicht nur die Impulsauswertung beinträchtigt, sondern auch die SOFT-CLOCK ausser Tritt bringt . Je nach Applikation wäre es vielleicht besser, in der Hauptschleife prüfen, ob sich _Sec geändert hat, und dann die sekündlichen Aktionen durchzuführen.


Der Wechsel von 40 nach 50 ist hierbei übrigens auch.

Ich hab nicht verstanden, was Du damit sagen willst.

for_ro
27.04.2007, 21:12
Hallo Josef,
in meinem Vorletzten Post habe ich doch erklärt, dass ich mit tiemr1sec=0 40 Ticks bekomme und bei timer1sec=1 50 Ticks.
Vielleicht kannst du das ja mal bei dir ausprobieren.

Gruß

Rolf

oe9vfj
28.04.2007, 09:01
Hallo Rolf,

Das mit den unterschiedlichen Frequenzen für die Timer-Interrupts Timer1Sec = 0 oder 1 lässt sich erklären.

Um möglichst einen ganzzahligen Timer-Interrupt pro Sekunde bei vielen Quarz-Frequenzen zu bekommen wird der Timer in CTC-Mode betrieben.
CTC = Clear Timer on Compare match
Der Timer zählt bis zu einem vorgegebenen Wert hoch, wenn dieser Compare-Wert erreicht ist, wird ein Interrupt ausgelöst und der Timer automatisch auf Null gestellt. Je nach Quarzfrequenz ergibt sich dabei ein Vorteiler-Faktor und ein Compare-Wert.
Soll der 16-Bit Timer auch 1-Sekunden Interrupts auslösen, muss meist ein anderer Vorteiler-Faktor gewählt werden, als wenn nur 25mSec-Interrupts notwendig sind.
Während der Laufzeit wird der Compare-Wert des Timers geändert, um zwischen dem 1-Sekunden-Interrupt und dem anderen zur DCF-Auswertung zu wechseln. Der Vorteilerfaktor wird für beide gleich belassen.
Bei 16Mhz Quarzfrequenz und einem 1-Sekunden Interrupt ergibt sich dann bei diesem anderen Vorteiler-Faktor für 25mSec (40 Interupts pro Sekunde) kein geeigneter Compare-Wert sondern nur für 20mSec (=50 Interrupts pro Sekunde).
Klingt etwas verwirrend #-o , ich hoffe aber, dass ich mich für jemanden, der sich schon etwas in die Timer-Einstellungen eingelesen hat, doch verständlich ausgedrückt habe.

Ich bin aber noch nicht dazu gekommen, bei dein gegenständliches Beispiel auf der Hardware zu prüfen.

oe9vfj
30.04.2007, 08:09
Hallo Rolf,

ich habe Dein Programm getestet und habe sowohl bei Timer1Sec = 0 als auch 1 eine funktionierende DCF77 Auswertung bekommen.

Übrigens: die Option SECTIC hat Mark schon in die am Samstag erschienen Release 1.11.8.7 aufgenommen.

for_ro
30.04.2007, 09:19
Hallo Josef,
ich könnte mir vorstellen, dass mein Problem bei den 50 Ticks auch gut an dem Signal vom DCF Empfänger liegt. Wenn das nicht ganz so steil geht, werden alle Impuls Längen etwas verkürzt, sodass ich dann zu den 7er Längen kommt. Ich benutze jetzt jedenfalls Timer1Sec=0 und gut ist.
Eure neue Version habe ich auch schon geladen und funktioniert ausgezeichnet. Finde ich übrigens super, wie ihr solche Wünsche sofort umsetzt.
Ich habe jetzt meine eigene Routine überall rausgeworfen und durch dein Kommando ersetzt. Einmal, weil es 4K weniger Code erzeugt und zum anderen, weil ich es so einfacher in andere Programme integrieren kann.
Vielen Dank nochmal.

Gruß

Rolf

oe9vfj
30.04.2007, 13:03
Hallo Rolf,

ich habe mir die Parameter für die Signal-Abtastung angeschaut. Bei 40 Interrupts pro Sekunde ergibt sich bei 25mSec Zeit-Takt und dem Grenzwert von 6 die Grenze von 150mSec (6 * 25mSec). Ist die Impulslänge >= 150mSec wird das Signalbit als 1 darunter als 0 interpretiert. Dieser Wert kann natürlich um einige mSec differieren, je nachdem wie die Abtastzeitpunkte auf das DCF-Signal treffen, da die beiden ja nicht synchron sind.
Bei 50 Interrupts pro Sekunde ergibt sich ein Zeittakt von 20 mSec und damit bieten sich entweder 140 oder 160mSec als Grenzwert. Beim derzeit implementierten Algorithmus ergeben sich 8 Zeittakte und damit 160mSec.
Sofern bei Deinem DCF-Modul wie Du vermutest die Impulse stark verkürzt abgegeben werden und der 200mSec-Impuls manchmal unter 160mSec liegt, gibt es natürlich Probleme in der Auswertung.

Du könntest mal folgendes probieren:

Ändere in der DCF77.LBX die Zeile

* CPI rDCF_TimerCount, cDCF_Bit1
in

* CPI rDCF_TimerCount, 7
(vorher eine Sicherungskopie erstellen )

Damit wird der Grenzwert bei einem Timer-Tick von 50 auf 140mSec herabgesetzt.
Diese Änderung musst Du dann natürlich wieder rückgängig machen, falls Du mit anderen Konfigurationen arbeitest.

Bei meinen Versuchen mit meinem DCF-Modul habe ich festgestellt, dass die Impulse doch recht genau bei 100 bzw. 200mSec mit etwa +/- 10mSec Abweichung liegen. Vielleicht können andere Anwender mit entsprechenden Messequipment mal ihre Erfahrungen über das Signalverhalten mitteilen.

Möglicherweise ist ein Pull-Up Widerstand hilfreich, da der im AVR aktivierte Pull-Up je nach DCF-Modul nicht ausreichend ist.