www.mikrocontroller.net

Forum: Codesammlung DCF77 AVR-Assemblerbaustein


Autor: Pit (Gast)
Datum:
Angehängte Dateien:

Ein für sich unabhängiger, in nur 112 Words formulierter
AVR-Assemblerbaustein zur Dekodierung des DCF77-Signals & zur
Verwendung in eigenen Programmen sei an dieser Stelle vorgestellt.
Das gute Stück ist allein in 10 mSek. Zyklus aufzurufen, übergibt die
Zeitinformation nach erfolgreichem Empfang BCD-codiert und stellt die
Sekunden-Zelle einer optionalen, zuvor aufzurufenden Software-RTC sowie
sinnvollerweise auch deren 1/100 Sekunden-Zelle (zur Vermeidung kurzer
Sek.Sprünge) bei Minutenwechseln zurück.
Impulslängen-, Paritäts- und Bitvollständigkeitsprüfung machen den
Baustein zuverlässig, die Tolerierung gewisser (definierbarer)
Impulslängen-Ungenauigkeiten sowie ggf. kurz nachfolgender Störspikes
sehr robust.
Habe diesen Decoder zusammen mit dem berühmten Conrad-Modul in Betrieb.
Das Sensibelchen ist noch dazu in relativ schlechter Empfangslage, über
mehrere Meter und mit nicht ganz sauberer Spannungsversorgung
angebunden...
Freue mich über weitere Anregungen/Verbesserungsvorschläge!
Gruss Pit
Autor: Pit (Gast)
Datum:
Angehängte Dateien:

Achtung! Initialisierungsroutine enthielt noch einen kleinen Fehler
(hatte ich selbst nicht vorab verwendet). Jetzt dürfte es aber passen.

Pit
Autor: Läubi (Gast)
Datum:

Schut gut aus! Werde das bei gelgeheit mal testen, nur eins würde ich
noch sagen, mach das doch so, das du den benötigten pin noch per DEF
.def DCFPORT = PORTB;
.def DCFPIN = 1;
noch einfügst :)
Autor: Läubi (Gast)
Datum:

Ach ja ein Tiny+das DCF Modul von Reichelt solte doch dafür geeigent
sein oder wird irgenwelche Spezillen eigenschaften beim AVR benötigt?
Autor: Joachim Börke (joachimb)
Datum:
Angehängte Dateien:

Hallo Pit,

ich habe noch ein Verständnisproblem zum Code.
In der anhängenden Datei habe ich einige Stellen rot markiert,
an denen nach unbedingten Sprüngen (rjmp) Programmcode nicht mehr
erreichbar ist?

Gruß
Joachim
Autor: Christoph Kessler (Gast)
Datum:

das sind doch "skip if bit set..." Befehle,(die PICs arbeiten NUR mit
sowas) d.h. der nächste Befehl wird übersprungen wenn die Bedingung
zutrifft, das braucht kein Label an der folgenden Zeile.
Autor: Joachim Börke (joachimb)
Datum:

danke für den Hinweis,
das war mir neu.
Autor: Pit (Gast)
Datum:

@joachim:
die eine sprungmarke (dcf77_13) ist tatsächlich überflüssig.
stammt noch aus der zeit von codeentwicklung & -optimierung.
ansonsten schau doch bitte mal in der doku nach, was sbis
bzw. sbrc tatsächlich bedeuten. vermutlich gehst du davon
aus, hier würden irgendwelche bits gesetzt...

@läubi:
das dcf-modul von reichelt kenne ich nicht. es dürfte aber keine
probleme geben, wenn nur hinten die dcf77-typische impulsfolge mit
ausreichendem pegel rauskommt. bitte aber die polarität beachten und
ggf. im programm anpassen. ansonsten ist der code auf jedem avr
lauffähig, der noch einen portpin und ein paar bytes sram frei hat.
der 10 millisekunden-aufruftakt sollte auch hinreichend stabil sein.

gruss pit
Autor: peter dannegger (Gast)
Datum:

Hier ist auch ein kurzer Assemblercode (96 Worte):

http://www.mikrocontroller.net/forum/read-4-23408.html#new


Zusätzlich ist noch ne Uhr drin, die bei Fehlern oder Ausfall des
Signals weiterläuft.


Peter
Autor: Läubi (Gast)
Datum:

< http://www.reichelt.de/artikeldruck.html?ARTIKEL=D... >
Hört sich doch vernünftig an.
Dann brauch ich nurnoch einpassendes Display und ein wenig Geld :-\
und schon kanns losgehen ;)
Autor: Pit (Gast)
Datum:

@peter:

hatte schon vermutet, dass du dich hier einschalten wirst :-))
aber bitte nicht schummeln: die dcf77-receive funktion in OVF0INT.inc
darfst du ruhig mitzählen... trotzdem ein elegantes programm für den,
der die komplettlösung sucht. ich selbst wollte mal ohne eine fette
datentabelle auskommen.

@läubi:

viel erfolg!

gruss pit
Autor: peter dannegger (Gast)
Datum:

@Pit,

stimmt, da sind noch 26 Worte im Interrupt.

Wenn man beides zusammenpackt, könnte man noch was einsparen. Die
Dekodierung braucht ja nicht soviel Rechenzeit.

Aber ich versuche bei den AVRs die Interrupts so kurz wie möglich zu
halten.

Auch habe ich es lieber, wenn die Zahlen binär vorliegen, das rechnet
sich leichter als 2 Dezimaldigits gepackt (packed BCD).


Peter
Autor: Pit (Gast)
Datum:

@peter

für meinen teil sollte ich vielleicht auch noch in rechnung stellen,
dass die unabhängigkeit des bausteins natürlich seinen tribut fordert.
sprich jene zusätzliche words, die lds/sts für ihre arbeit mit dem sram
nun mal benötigen. wenn sich das noch irgendwie mit einem pointer
behandeln ließe, könnte man den speicherbedarf der
programmfunktionaliät womöglich unter 100 words drücken.

binär ist die handhabung der variablen sicher leichter. wer's braucht,
kann die routine "erfolgreicher empfang" dahingehend ergänzen. die 112
words dürften aber dann leider nicht mehr zu halten sein.

gruss pit
Autor: Pit (Gast)
Datum:
Angehängte Dateien:

das gute liegt doch so nah: ersetzt man alle lds/sts durch ldd/std unter
zusätzlichem einsatz des y-pointers, lässt sich noch beachtliches
sparen. wer schliesslich anfangs auf die initialisierungsroutine
verzichten kann (weil z.b. das sram vorher aus anderer quelle
initialisiert wird) kann die ersten zwei zeilen der dcf77_init dann
noch durch ein gepflegtes movw ZL:ZH,YL:YH ersetzen.
da waren es tatsächlich nur noch 99...

pit
Autor: Winne (Gast)
Datum:

für alle DCF77 interressierten ein Tip

http://www.progforum.com/showthread.php?t=5896

das mdol ist separat und gibt ein sehr gutes Signal
Autor: Jens D. (Gast)
Datum:

lol
gibts die noch immer???
Naja hab schon 4 zu hause rumfliegen einer komplett im einsatz und
einer eingepackt und 2 auseinander
die laufen auch mit 5V..
Autor: Joachim Börke (joachimb)
Datum:

Hallo,

ich habe meinen DCF-Dekoder nun auch fertig.
http://www.mikrocontroller.net/forum/read-4-248219...
Das Programm ist in C und Assembler geschrieben. Die Abtastung des
Signals erfolgt recht störsicher. Die Anschaltung des Empfängers mache
ich über eine Stromschleife. Das hat den Vorteil, daß ich eine lange
zweiadrige Klingelleitung für Betriebsspannung und Zeitzeichensignal
verwenden kann und den Empfänger (ohne Batterie) am günstigsten
Empfangsort aufstellen kann.
Die erste Dekodierung erfolgt im Durchschnitt 20s schneller als bei
anderen Lösungen.
Speicheroptimiert ist das Programm allerdings nicht...

Gruß
Joachim
Autor: Joachim Börke (joachimb)
Datum:

Nachtrag:
Die Polung (normal bzw. invertiert) des DCF-Signals ist unerheblich.
Der Dekoder stellt das fest.
Autor: petersch (Gast)
Datum:

Hallo Joachim,

und welcher DCF Baustein benutzt Du ?

Ich habe bei meiner Propeller-Uhr den von Conrad, aber ehrlich gesagt,
ist das Teil sowas von sch..., außer man richtet es irgendwie Richtung
Mainflingen aus.

Ich habe zwar jetzt schon 4 von diesen Uhren mit dem Conrad Modul
gebaut, aber mich würde schon interessieren, ob es am Modul oder der
Software liegt, obwohl ich eher zum ersteren tendiere, da ich mittels
LED's die empfangenen Interrupts ausgebe und wenn die Uhr nicht
korrekt ausgerichtet ist, flackerts wie wild. Dreh ich sie richtig,
dann sehe ich den Sekundenimpuls mittels der LED's.

Viele Grüße, Peter
Autor: Uwe (Gast)
Datum:

Hi!
Es liegt an der sch... Antenne des Moduls.
1. meistens schlecht abgeglichen
2. schlechte Kondensatoren im Schwinkreis
Nimm einen Ferritstab mit Mittelwellenspule und gleiche sie mit guten
C's auf 77,5KHz ab. Dann sollten deine Probl. aus der Wellt sein.

MFG Uwe
Autor: Joachim Börke (joachimb)
Datum:

Hallo Peter,

ich habe einen Funkwecker von Aral zerlegt. War mit 3 Euro und einer
Sammelkarte recht preiswert zu erstehen.
Ich werde den Empfänger später auf dem Dachboden platzieren. Da habe
ich Ruhe vor den "Störern" im Haus.

Gruß
Joachim
Autor: petersch (Gast)
Datum:

Hallo Uwe,

danke für den Tipp :)

Als Kondensatore(n) fällt mir jetzt nur diese eine ein, der auf der
Antenne draufklebt. Ist das der einzige den man erst mal abgleichen
könnte, bevor man sich eine komplett neue Antenne baut ?

Merci
Autor: Wolfgang Horn (Gast)
Datum:

Hi, petersch,

die Spule auf der Ferritantenne bildet mit dem Kondensator dabei einen
Schwingkreis, und nur auf dessen Resonanzfrequenz empfängt das Ganze.

Dieser Schwingkreis muß auf 77,5 kHz abgestimmt sein.
Wie, wenn man die Meßmittel eines Funkamateurs nicht hat und auch nicht
die aus dem Labor der Uni? Einfach- such Dir einen beim nächsten Treffen
des Ortsvereins des DARC. Oder den nächsten Meister, der Radios noch
selbst repariert - falls es das überhaupt noch gibt.

Nähere Infos: http://www.darc.de/ardf.

Mit zu den größten Problemen beim DCF77-Empfang gehören die Störungen
durch Fernseher, die fünfte Oberwelle der Zeilenfrequenz liegt nur 625
Hz oberhalb der 77,5 kHz - und kann Vorstufe und Empfänger völlig
zustopfen. Das Optimum wäre ein Quarzfilter direkt an der
Ferritantenne, aber wer sucht schon das Optimum...

Ciao
Wolfgang Horn
Autor: Uwe (Gast)
Datum:

Hi!
@Wolfgang, Einen Frequenzgenerator haben eigentlich viele Bastler, auch
eine vernünftige Werkstatt sollte sowas haben.
>die fünfte Oberwelle der Zeilenfrequenz liegt nur 625 Hz oberhalb >der
77,5 kHz - und kann Vorstufe und Empfänger völlig zustopfen.
Das ist ja richtig, aber eine hohe Güte und damit ein "scharfer"
Schwinkreis helfen da schon recht ordentlich. Der Fernseher stört
meinen Empang eigentlich nicht. Er steht 2m "vor" meiner Antenne in
Richtung DCF-Sender gesehen.
> Das Optimum wäre ein Quarzfilter direkt an der Ferritantenne, aber >
wer sucht schon das Optimum...
Ich, wenn es nicht zu aufwändig ist.
@petersch, ja der ist das, gegen guten tauschen und abgleichen hilft
schon. Nur der Ferritstab ist bischen klein.

Viel Erfolg, Uwe
Autor: Raik (Gast)
Datum:
Angehängte Dateien:

Hi,
ich habe versucht den DCF-Programmbaustein mit in das Programm für
einen ph-Controller (Aquariumsteuerung) aufzunehmen. Leider werden aber
nur unsinnige Werte für Datum und Uhrzeit (keine ini-Werte) auf dem
Display angezeigt. Das DCF-Modul von Conrad scheint aber korrekt zu
arbeiten, denn ich kann mit dem Oszi am Pin entsprechende Pegel sehen.
Kann mir jemand helfen?

Gruß
Raik
Autor: Ralf D. (Gast)
Datum:

Hallo Raik,

die Initialisierung des Bausteins machst du schon mal doppelt.
Und verzichte doch mal zunächst auf dessen Aufruf. Werden nun
ordnungsgemäss die Ini-Werte angezeigt ?
Autor: Raik (Gast)
Datum:

Hallo Ralf,
leider konnte ich keinen doppelten Aufruf der Initialisierung des
dcf-Moduls finden.
Ohne Initialisierung habe ich noch nicht getestet.
Ansonsten funktionieren alle anderen Menüpunke des Programms ohne
Probleme.
MfG
Raik
Autor: Ralf D. (Gast)
Datum:

Hallo Raik,

schau doch mal genau: den Speicher, den der Baustein belegt,
initialisierst du doppelt. Einmal du selbst, einmal über dcf77_init.
Und wo werden eigentlich die Zellen HSEK-JHR von dir initialisiert? Der
Baustein macht das jedenfalls nicht von selbst. Klar, dass dann da
zufällige Werte stehen. Dieser Bereich soll übrigens von einer RTC
betrieben werden. Der Baustein schreibt da bei erfolgreichem Empfang
nur bei jedem Minutenwechsel die Zeitinformation hin...

Gruss Ralf
Autor: Raik (Gast)
Datum:
Angehängte Dateien:

Hi,
@ Ralf, ich habe jetzt eine Soft-RTC mit eingefügt. Außerdem verwende
ich nun eine dcf-Auswerteroutine, die von Peter schon vor einiger Zeit
veröffentlicht wurde.
Die Initialisierungswerte werden zwar jetzt korrekt im Sekundentakt
hochgezählt, aber die aktuelle Uhrzeit wird noch immer nicht erkannt.
Außerdem wird mir angezeigt, daß eine neue Sekunde erkannt wurde
(newsecond -> Anzeige *). Beim Abklemmen des DCF-Empfängers
verschwindet die Anzeige newsecond und die Datenpakete werden verworfen
(dcf77error -> Anzeige E).
MfG
Raik
Autor: Ulli (Gast)
Datum:
Angehängte Dateien:

Hallo
@Raik.. ich baue mir selbst grade einen Aquacomp mit Zeitschaltuhr,
Heizung, PH und Leitwertmessung und bei mir traten dieselben Probleme
auf.
Hab das in C (CAVR) geschrieben und bei mir läuft es recht zuverlässig.
 Vieleicht hilft es dir ...schreib mal wenn du noch fragen dazu hast.

mfg Ulli
Autor: Ulli (Gast)
Datum:

muss noch etwas hinzufügen, damits ein Reim wird..

also als µC nehme ich hier einen Mega8535
und im Hauptprogramm werden diese beiden Interrupts eingesetzt:
//---------------------------------------------------------
// Timer 2 output compare interrupt 64µS
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
 dcf_tim2();
}
//---------------------------------------------------------
// External Interrupt 0 service routine  Steigende Flanke
interrupt [EXT_INT0] void ext_int0_isr(void)
{
 dcf_int0();
}
//----------------------------------------------------------
*Timer 2 ist folgendermaßen eingestellt:
// Timer/Counter 2 initialization
 ASSR=0x00;
 TCCR2=T2_PRESCALE;
 TCNT2=0x00;
 OCR2=(T2_CTC * RATE_FAKTOR) - 1;  // ctc & interrupt bei 24 (0...24)
 // Timer(s)/Counter(s) Interrupt(s) initialization
 //TIMSK=0x02;  //timer 0 enabled
 TIMSK=0x82; //Timer Interrupt 0 + 2 an

also versuch mal das in deinen Programm einzubauen :-)
Autor: Robert Sommerfeld (Gast)
Datum:

Hi Pit,

funktioniert ja super. Allein einfache Binärvariablen für's Zeitformat
hätte ich mir noch gewünscht, vielleicht hast Du ja dafür noch
irgendwann einmal eine effiziente Lösung parat!

MfG Robert Sommerfeld
Autor: Michi (Gast)
Datum:

@Ulli bzw. @Raik

Ich bin eben über diesen Thread gestolpert und möchte mir auch so einen
kleinen Aquariencomputer bauen. Hat sich bei euch schon was getan -
sprich wie weit seid ihr jeweils mit eurem Projekt?

Grüße
Michi
Autor: Raik (Gast)
Datum:

@ Michi

leider habe ich momentan wenig Zeit am diesem Projekt weiter zu
arbeiten. Die Probleme mit der fehlerhaften DCF-Anzeige bestehen aber
immer noch. Vielleicht kannst Du mir ja noch einige entscheidende
Hinweise geben.

MfG
Raik
Autor: Wolfram Quehl (quehl)
Datum:

hallo

ich möchte diesen Baustein auch verwenden. Dazu einige Fragen:

kann man auch ein invertiertes Signal mit einbauen? Mit Xor zwar kein
Problem, aber die Erkennung, ob ein Empfänger angeschlossen ist, sehe
ich dann als Problem.

Wie kommen die angegebenen Timing-Zahlen zustande? Bei 180 und 10ms
müßten 1,8 sek. rauskommen. Wo die Zeit zwischen 100ms und 200 ms
abgefragt wird, kann ich nicht erkennen. Ich wollte statt 10ms 8ms als
Aufruffrequenz verwenden (8bit Timer) und da konnte ich nicht finden, an
welcher Stelle ich da was verändern muß.

mfg
Autor: Pit (Gast)
Datum:

Hallo,

für ein invertiertes DCF77-Signal ist in Zeile 5 sbis durch sbic PINX,Y
zu ersetzen. Mit 10 mSek. Aufruftaktzyklus lassen sich Impulszeiten von
100/200 mSek. naturgemäß am besten teilen bzw. abzählen. Nicht
vergessen, daß aber nicht die eigentlichen Impulse sondern die
Pausenzeiten dazwischen zur Bestimmung des jeweils vorherigen Bits
abgemessen werden. Klar geht das auch mit 8 mSek Takt zu erfassen, zumal
die Impulszeiten sowieso ziemlich verschmiert sein können. Dazu sind die
Konstanten für die lange letzte sowie alle anderen Pausenzeiten einfach
je nach Aufruftakt (wobei 10 MSek eher eine obere Grenze ist)
anzupassen. Ergibt sich eigentlich alles aus Quelltext+Beschreibung.

Gruß Pit
Autor: Wolfram Quehl (quehl)
Datum:

danke, da muß ich mich erst noch etwas einarbeiten. Hab das mit den
Pausen messen auch festgestellt und hab den vermutl. Grund gefunden. Am
Anfang wird festgestellt, ob ein Empfänger vorhanden ist mit Pause >2
sek. Bei 8ms Takt ist das schon etwas knapp, aber vielleicht noch
ausreichend. Würde das gehen?

Ich bin jetzt dabei, das Programm auf Interrupt und Mainloop
aufzuteilen, damit die ISR so wenig wie möglich Zeit verbraucht. Wegen
der Sprünge ist das allerdings nicht so einfach. Das Umspeichern und
INIT könnte z.B. in die Mainloop. Auch die ganze Auswertung könnte
dahin.

Ich habe am Anfang folgendes gesetzt.
ldi  pol,$FF      ; Pol=  FF=low-aktiv, 00=high-aktiv
    lds  r20,DCF77CT    ;alle 10 mSek. aufzurufen
    lds  r21,DCF77CHECK
    ldi  temp2,1<<pinb0    ; 0x0
    eor  temp2,pol      ;
    andi  temp2,1<<pinb0    ; 0x0
    in  temp,PINB      ; Port
    eor  temp,temp2      ;
    sbrs  temp,PinB0      ;Input-Pin

Der Grund ist, daß alle möglichen Änderungen am Anfang des Programms
stehen sollen. Ich finde meine Ergänzung allerdings etwas umständlich.


ich habe vor ca. 15 Jahren eine serielle PC Funkuhr gekauft. Kostete ca.
50,- DM.
Ich möchte diese an den Mega32 anschließen. Weiß jemand die
Kontaktbelegung von dieser Uhr. Mit dem mitgelieferten Programm wird die
Stromversorgung über die serielle Schnittstelle eingeschaltet. Das
Signal muß ja auch nicht unbedingt über Tx rauskommen. Das Wichtigste
ist aber die Stromversorgung. Das übrige könnte ich wahrscheinlich
messen.
Bei der Funkuhr von C habe ich nur den Batteriebetrieb mit 1,5V gesehen.
Da kann doch dann kein TTL Signal rauskommen. Deshalb hatte ich diese
Uhr nicht weiter beachtet, zumal die mir auch recht teuer erscheint.

mfg
Autor: Wolfram Quehl (quehl)
Datum:

ich habe jetzt mal dieses DCF Programm mit einem anderen verglichen.
Arbeitsweise: anderes Programm: bits werden nur gelesen und in Reg.
gespeichert. Am Ende der Min. erfolgt die Interpretation: Parityprüfung,
Fehlerbits setzen, Schieben und Speichern. Dies hat den Vorteil, daß der
größere Teil in die Mainloop gelegt werden kann. Trotzdem war das Ganze
wegen zusätzlicher Sachen unübersichtlich, was eigentlich nicht
notwendig ist und der Registerverbrauch war auch zu hoch.
Bei Pit: Das Ganze liegt in der ISR und kann durch Ergänzung von Push
und POP der 4 Register und Ersetzen von ret durch reti angewendet
werden. Da der Interrupt verhältnismäßig lange gesperrt bleibt, kann das
Programm hauptsächlich nur als Standalone verwendet werden und das ist
nicht sinnvoll. Darum versuche ich eine Aufteilung. Im Interrupt müßten
2 bits gesetzt werden. Ein Fehlerbit und ein "Minute noch nicht zu Ende"
bit. Im Main werden diese abgefragt: Bei Fehler, Init und überspringen,
bei dem anderen bit Umspeichern, Init. So wären Umspeichern und Init aus
der ISR raus. Leider kann ich das in dem Programm nicht so erkennen, wie
das abläuft.

Zur Diskussion wäre zu stellen, ob nach einem Fehler abgebrochen wird
und eine volle gültige Min. erkannt werden muß oder gültige Teile
beibehalten werden. Die Beibehaltung könnte eine schnellere gültige
Vollmin. erkennen, aber ich wäre trotzdem dafür, von vorne anzufangen.
(wohl hauptsächlich wegen der einfacheren Programmierung)

Scanzeiten:

Pit:      anderes Programm (auf Highzählung umgerechnet)  mein Vorschlag
     <60ms = Störung              <60ms = Störung
  60-780ms = Fehler        782ms = Fehler         60-775ms = Fehler
 780-860ms = 1      782-828ms = 1          775-825ms = 1
        828-875ms = Fehler        825-875ms = Fehler
 870-950ms = 0      875-922ms = 0          875-925ms = 0
 960-1,78s = Fehler    922-1,17s = Fehler        925-940ms = Fehler
                    940-1,06s = Störung
1780-1,86s = Lastbit1?     >1,17s    = volle Minute      1,06-1,5s =
volle Minute
1870-1,95s = Lastbit0?
>1960      = Fehler                 >1,950    = Fehler

Lastbit müßte doch Firstbit heißen, denn in dieser Zeit fällt doch die
1. sek, an. Oder sehe ich da was falsch?
Bei den Zeiten bei voller Min. bin ich mir nicht so sicher, was da hin
kommen müßte. Ich denke nur, wenn die Minute voll ist, brauch man nicht
noch zusätzlich das erste Bit abfragen. Dann fängt es von vorne an. Die
Sollzeiten sollten in die Dokumentation, damit diese abhängig von der
Aufruffrequenz in das Programm eingerechnet werden können. Sonst würden
mehrfache Rundungsfehler entstehen, wenn jeder seine gerundeten Werte
weitergibt.

Die Scantabelle könnte in dieser Reihenfolge und mit BRLO abgefragt
werden. Dann wäre das etwas übersichtlicher. Und bei Fehler immer an
dieselbe Stelle springen. Der letzte Fehler benötigt einen gesonderten
Einsprung, weil das Gültigkeitsbit der vollen Minute zurückgesetzt
werden muß.

Die ersten 16 bits sollten noch gespeichert werden, damit diese später
für eine Wetterauswertung verwendet werden können.

mfg

PS: Meine Invertierungsergänzung habe ich wieder rausgenommen.
Autor: Pit (Gast)
Datum:

Hallo Wolfram, besten Dank für die tiefgründige Analyse, die erste ihrer
Art. Wenn ich auch vorerst wenig Zeit finde, das Programm, das in dieser
Form zufriedenstellend seit Monaten arbeitet weiter zu verbessern möchte
ich zu Deinen Anregungen nur kurz folgendes sagen: Es war Ziel der
Entwicklung, einen von weiteren Abhängigkeiten frei verwendbaren
Baustein zu entwickeln. Diese Modularität bedeutet insbesondere, auf
eine möglicherweise effizientere Zweiteilung in Mainprog+Interrupt zu
verzichten. Die "verhältnismässig lange" Sperrzeit des Interrupts wird
dadurch relativiert, daß dieser ja nur "alle  Ewigkeit" von 0,8 Sek
tatsächlich so "lange" ausgeführt wird und sonst nur ein Counter für die
Pausenzeit inkrementiert wird. Weitere Verbesserungen stelle doch bitte
in fertigem Code vor, wobei die aktuellen 99 Worte Platzbedarf bitte
nicht überboten werden- denn minimalster Code war ein weiteres meiner
Ziele... Gruß Pit
Autor: Wolfram Quehl (quehl)
Datum:

leider muß die längste Sperrzeit berücksichtigt werden, auch wenn sie
nur 1x alle paar Jahre auftritt. In diesem Falle können dann Fehler
entstehen. Meine  Heizung hat ca. 10 Jahre einwandfrei funktioniert und
aufgrund eines zeitl. orientierten Programmfehlers (Interrupt), ist
meine Heizung im Wert von ca. 6000,- Euro kaputtgegangen. Darum lege ich
jetzt wert auf fehlerfreie Programme, die sich nicht gegenseitig stören.
Darum diese Aufteilung.
Wenig Speicher ist richtig, aber das zeigt doch, daß auch andere
Programme im AVR drin sein können.

Ich werd sehen, was ich machen kann. Aber da muß ich wohl das Programm
noch weiter analysieren.

mfg
Autor: Pit (Gast)
Datum:

Die Bedenken bezüglich der Sperrzeit sind sicher absolut berechtigt,
solange diese unkalkulierbar fürs System ist. Bisher habe ich aber keine
Veranlassung, an der Stabilität und Zeitbedarf des Codes zu zweifeln.
Was dagegen spricht, globale interrupts bereits zu Beginn der
Datenauswertung wieder freizugeben habe ich noch nicht untersucht. Denn
diese Auswertung ist nicht zeitkritisch.

Vielleicht noch etwas zum Background dieses Programms. Es findet
Verwendung als Teil einer Haussteuerung in 100% Assembler, die sehr
viele Aufgaben zu erledigen hat. Die Idee war, alle "Betriebssystem"-
Funktionen und insbesondere alle zeitkritischen Teile wie diese Funkuhr
in einen (5 mSek) Timerinterrupt auszulagern. Das Hauptprogramm kann
dann schalten und walten wie es will, solange es selbst keine Ansprüche
auf Unterbrechungsfreiheit stellt. Als Programmierer ist man stets
versucht, hunderttausend Abhängigkeiten zu kreieren- nur würde dann der
Überblick über ein solches System sehr schnell verloren gehen. Deshalb
die strikte Bausteinarchitektur.Und alles in allem funktioniert die
Sache auch hervorragend, wenn konsequent umgesetzt.

Die mit Wetterdaten gepickten Bits würd ich auch gerne verwenden, wenn
nur der Code endlich offengelegt wäre :-))

Pit
Autor: Läubi .. (laeubi) (Moderator) Benutzerseite
Datum:

Jep dazu bin ich auch übergegangen!
Interupts sollten generell imemr alles so belassen wie es vorher war,
und ihre Rückgaben nur über Flags oder eine Speicherzelle im SRAM
regeln.
Funktionen programmier ich inzischen auch so, das die Variablen über den
Stack übergeben werden, und ich keine spezifischen Registernamen
verwende. So wird selbst ASM Code in weiten Teilen "portabel" und die 10
Takte mehr tun meistens keinem weh :)
Autor: Wolfram Quehl (quehl)
Datum:

ich habe das Ganze jetzt in eine bessere Reihenfolge bzw. Ordnung
gebracht. Es ist schon schwer, da durchzusteigen. Manchmal dachte ich,
wie kann das nur funktionieren, aber dann habe ichs doch gefunden.
Nachdem ich das jetzt weitgehend fertig habe, ist mir z.B. aufgefallen,
daß das Datum Parity nicht geprüft wird. Gespeichert wird es, nur der
Vergleich fehlt. Es besagt daher wohl nichts, wenn ein Programm läuft,
daß das auch fehlerfrei wäre.

Ich muß noch die Wetterdaten speichern.

mfg
Autor: Pit (Gast)
Datum:

@Wolfram: Dann war wohl die lange Tüftelei doch noch nicht perfekt :-(
Danke für den Hinweis auf die fehlende Prüfung der Datum Parity. Ich
werd der Sache nun auch noch mal auf den Grund gehen müssen. Vielleicht
könntest Du an dieser Stelle noch mitteilen, was Dir darüber hinaus
"aufgefallen" ist. Und den verbesserten Code natürlich :-) Pit
Autor: Pit (Gast)
Datum:

@Wolfram: Beim Datum Parity liegst Du nun offensichtlich doch daneben.
Bitte betrachte nochmal den Abschnitt ab dcf77_10, der nach
Registrierung des letzten Bits der DCF77-Zeitscheibe, eben nämlich der
Datum Parity aufgerufen wird: R21 enthält neben dem allgemeinen
Fehlerflag auf Bit7 die Anzahl aller Einsen des Datum inklusive der
Parity. Ein andi mit $81 gibt nun einen Fehler, wenn deren Anzahl
ungerade wäre- das letzte Paritybit findet demnach durchaus Beachtung!

Als interessante Frage bleibt natürlich, ob die Prüfung die Parität, der
Impulslängen und Bitvollständigkeit allein zur 100%igen Fehlervermeidung
ausreicht. Nach einigen Bedenken auch hier im Forum bin ich inzwischen
dazu übergegangen, die empfangene Zeit erst nach dem zweiten
erfolgreichen Empfang hintereinander zu übernehmen.

Pit
Autor: Wolfram Quehl (quehl)
Datum:
Angehängte Dateien:

anbei der neue Code. Das war gerade das, was ich nicht so schön fand,
daß die  Parity Prüfung z.B. an verschiedenen Stellen stattfindet.
Deshalb hatte ich das übersehen.
Der neue Code ist nicht getestet, weil ich noch keinen passenden
Empfänger habe.
Wäre schön, wenn das mal getestet werden könnte, ob da noch Fehler drin
sind. Die Bausteinfunktion habe ich hier noch beibehalten. Aber anhand
der Flags ist dann auch eine leichtere Auslagerung möglich.

mfg
Autor: Pit (Gast)
Datum:

Ist R21 jetzt nicht doppelt belegt? Ansonsten schaut das zum Preis
einiger zusätzlicher Codeworte sicher nicht schlecht aus - im Hinblick
auf mehr Flexibilität und die Bereitstellung der "Wetterbits".  Pit
Autor: Wolfram Quehl (quehl)
Datum:

ja, das eine Register ist doppelt belegt, weil es zu dem Zeitpunkt von
der vorherigen Belegung nicht mehr gebraucht wird. Es wird dadurch ein
Register eingespart.

mfg
Autor: Wolfram Quehl (quehl)
Datum:

hat noch keiner das Programm testen können? Von den 35 Downloads sollte
doch einer dabei sein, der einen DCF77 Empfänger angeschlossen hat.

mfg
Autor: Wolfram Quehl (quehl)
Datum:

hallo Pit,

nach meiner Meinung ist in Deinem und meinem Programm ein kleiner
Fehler.
Es wird zuerst die INIT aufgerufen. Darin wird das Reg. 23 verwendet,
ohne das vorher die 0 in das Reg. geschrieben wird. Möglicherweise
funktioniert das Programm deshalb, weil im zunächst fehlerhaften Verlauf
die Reg. richtig gesetzt werden. Dadurch verzögert sich aber die erste
gültige Anzeige.
Alles nur theoretisch.

mfg
Autor: Pit (Gast)
Datum:

Hallo Wolfram,

wieso? Hast Du das "clr r23" übersehen? Der Aufruf der Init geschieht
vorab vom Hauptprogramm aus. In meiner Anwendung brauche ich das
allerdings gar nicht, weil das RAM bereits vorher komplett aus dem
EEPROM initialisiert wird.

Gruß Pit
Autor: Wolfram Quehl (quehl)
Datum:

hallo Pit,

ich hatte noch die ältere Version in Bearbeitung und da fehlte das clr
R23.
Ich werde jetzt noch mal die beiden Versionen vergleichen.
Mein Programm oben hat noch einige Fehler und wird wohl deshalb nicht
laufen.

Ich habe jetzt auch eine Aufteilung gemacht zwischen Interrupt und Main.
Da werden das schon etwas mehr Words. Aber eine kurze Interruptlaufzeit
erscheint mir wichtiger. Bin noch am Überlegen, ob man die lange Latte
der Abfragen besser machen kann.

mfg
Autor: Pit (Gast)
Datum:

Also wenn die (komplexere) Aufteilung zwischen Interrupt und Main noch
umfangreicher ausfällt wär's vielleicht doch besser, man stellt die
"Schönheit" hintenan. Ist es nicht letztlich egal, wo die eigentliche
Programmfunktionalität nun verpackt wird? Natürlich immer vorausgesetzt,
im Interrupt wird nicht sinnlos Zeit etwa in Pollschleifen vertrödelt
und ein SEI macht schnellstmöglich Platz für ggf. wichtigere Dinge, die
in der Interrupttabelle prioritätsmäßig dann weiter oben zu stehen
haben.

Die Abfragenliste finde ich auch nicht unbedingt "schön", sie war aber
immer die einfachste aller Varianten. Bin gespannt wie das noch kürzer
gehen könnte!
Denn den Code weiter einzudampfen wäre durchaus noch eine Anstrengung
wert. Im Auge hätte ich da insbesondere den Verzicht auf den Test der
Paritätsbits. Die Prüfung a) der Bitvollständigkeit, b) der korrekten
Bittimings und c) der Plausibilität durch Zeitvergleich mit der
vorhergehenden Minute reicht meiner Meinung nach "in der Praxis" 100%ig
zur Vermeidung von Fehlern und käme mit noch weniger Code aus.
Zugegeben: mehr als sportlicher Ehrgeiz ist das aber nicht :-))

Pit
Autor: Wolfram Quehl (quehl)
Datum:

diese Aufteilung halte ich schon für notwendig. Habe da auch eine gute
Schnittstelle gefunden. Jede Verzögerung im Interrupt kann andere
Aufgaben behindern. Ein SEI im Interrupt geht auch nicht, weil dann
nicht nur die vorhergesehene Aufgabe abgearbeitet wird, sondern auch
andere weniger wichtige, weil das eben ein Pauschalinterrupt ist.

Meine Abfragenliste habe ich um 6 Bytes kürzer bekommen, hatte gedacht,
daß die Auswikungen besser sind. Und eine etwas längere Ausführungszeit.
Diese spielt hier aber nicht so die Rolle, weil diese in der Main liegt
und ich dafür für alles zusammen 1 sek. Zeit habe.

Daß weniger Prüfungen und Kontrollen auch weniger Code haben, ist klar.
Aber das sollte nicht das Ziel sein. Im Gegenteil, vom Prinzip her
sollte man es sich angewöhnen, möglichst viele Kontrollen zu machen. Ich
spare mir aber oft den Code, der eine möglichst genaue Fehleranalyse
ausgibt. Darum wird bei mir nach einem Fehler nur Init und zum Ende
gesprungen.

dcf77__0a:  ldi   zl,low (state*2)
    ldi   zh,high(state*2)
nextstate:  lpm   temp,z+
      cp    r22,temp
      brlo   dcf77_8    ; Zyklus
      brne   nextstate
     adiw  z,8
      lpm   temp,z
     ldd  ZL ,Y+13  ;DCF77TAL
    ldd  ZH ,Y+14  ;DCF77TAH ;Z-> NEWTIME ARRAY
     cpi   temp,7
    breq   dcf77_7    ; LastBit
    rjmp   dcf77_9    ; Prüfbit

State: .db 8,16,$15,$1c,$23,$29,$2c,$31,$3a,7,7,7,9,9,7,7,7,9

ich weiß jetzt nicht, ob ein fehlender Minutenimpuls ausreichend
abgesichert ist.

mfg
Autor: Steffen (Gast)
Datum:

Hallo Pit

Ist zwar schon ne ganze Weile her, als du den Assemblerbaustein hier ins
mikrokontrolle.net reingestellt hast, aber ich komm mit meinem Projekt
nicht wikklich voran.

Ich versuche gerade deine DCF77-dekodier-Routine in meinem Studio-Uhr
Projekt zu integrieren. Hast du eventuell noch mehr Unterlagen
(Registeraufbau im RAM, Aufbau von DCF77CHECK..) Ich muss meine interne
Uhr mit der dcf Zeit syncronisieren.

Leider komm ich nicht mal zu einer Statusauswertung, ob ein Fehler
vorliegt und vor allem wann bekommt die Routine mit, dass eine neue
Übertragung beginnt? Also wann sind 58 Impulse gesendet worden (denn der
59 müsste ja eigentlich fehlen). Denn genau da könnt ich meine
Syncronisation starten.


@ Peter Danneger

Ich hatte erst die Routine von Peter Dannegger ausprobiert und auf den
mega8 angepasst, doch da hab ich nur 32:00 (hh:mm) nach der
Syncronisation angezeigt bekommen. Wenn dann mal das DCF-Paket verworfen
wurde, zählte die interne Uhr einfach wie gewollt weiter. Allerdings kam
es nun zu einer erneuten gültigen Synchronisation, zeigte die Anzeige
wieder 32:00 an. Ich verstehe hier auch nicht so recht, woher die
NewSecond, NewMinute, NewHour... u.s.w. her kommen.
Vieleicht kann mir das ja der Peter noch sagen, denn darauf wird ja die
Zeit syncroniesiert.


In der Hoffnung hier diesen Treed mal wieder etwas Leben einzuhauchen..

Grüße der Steffen
Autor: Steffen (Gast)
Datum:
Angehängte Dateien:

@ Peter Dannegger

Ich hab es gefunden... Beim ATtiny12 existiert ja gar kein RAM. Im
ATmega8 sind die Register-Adressen im RAM gemapped. Das heißt: Es wurde
immer irgend eine wilde Speicherstelle geladen anstatt die des Registers
r10, r11,..,r15 !

Das lag hauptsächlich am Pointerregister Xh. Das hatte immer eine 0x04
drin stehen. (woher auch immer) Das darf es aber beim ATmega8 nicht,
denn die 32 Arbeitsregister sind ab $0000->r0, $0001->r1,..,
$001A->r10,..., u.s.w organisiert.

Hab das in deinem Code mal geändert. Ist wahrscheinlich auch nur wegen
dem portieren in einen ATmega8 wichtig. Kenn den ATtiny12 nicht so gut.

Nun läuft die DCF77 syncronisation super! ..wenn dann mal das Signal
stark genug ist und ich nicht so oft einen Error detektiere.

Änderung ist im Anhang!



Steffen
Autor: Z8 (Gast)
Datum:

Hi Pit, DANKE!!!!!!

Man muss sich schon des Gehirn verrenken um das zu verstehen.
(DCF77CHECK Doppelnutzug) :)
Habs mit einer Soft-RTC versehen und läuft ... und läuft ...

ganz großes DANKE! Z8
Autor: Hallo (Gast)
Datum:

Hallo,
ich habe den Code von Pit gerade in mein Projekt eingefügt, funktioniert
soweit auch tadellos. Jedoch werden in den Speicheradressen wie STU, MIN
usw keine Zeiten abgelegt. Das ablegen sollte doch in diesem Programunkt
ablaufen oder???

dcf77_12:  std  Z+11,r21    ;nach MIN...JHR sichern
    ld  r21,-Z
    dec  r20
    brne  dcf77_12
    std  Z+11,r20    ;Sek. = 0 setzen
    std  Z+10,r20    ;1/100 Sek. = 0 setzen


Kann mir hier vlt jemand weiterhelfen da ich mich erst in den SRAM
einarbeite.

Gruß
HAllo


P.S: Controller ist ein ATmega8
Autor: Jan K. (pit1)
Datum:

Hallo schrieb:
> Das ablegen sollte doch in diesem Programunkt
> ablaufen oder???

Ja, aber nur bei erfolgreichem Empfang!
Am besten mit ner kleinen LED den Puls kontrollieren- da darf kein
Flackern dabei sein.

Gruß Jan K.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net