Ich kaue mir schon seit einigen Tagen die Fingernägel kaputt weil ich folgendes Problem nicht gelöst bekomme: Ich möchte die Länge eines Pulses testen. Wenn er unter 0,2ms bleibt dann ist er null und ansonsten 1 (DCF Kodierung). Anzeigen wollte ich das über LED. Nun habe ich bei meinem angehängten Code das über den Timer0 versucht zu lösen indem ich bei einem 3.2768E6 Quarz den Timer mit einem Prescaler von 1024 beschaltet habe um für eine Sekunde 3200 Zyklen zu bekommen. Nun das Ganze nochmal durch 8 um 125ms zu bekommen die dann 400 Zyklen benötigen. Gestartet wird der Timer per Interrupt über die steigende Flanke. Wenn der Puls nach 125ms noch da ist, dann ist er mit 1 codiert. Alles andere ist Null. Aber irgendwie funzt das nicht so richtig. Mein Prog zeigt jeden Puls an. Obwohl simuliert im AVRStudio das Ganze funktioniert. Ist das etwa ein Laufzeitproblem oder habe ich da einen Denkfehler ??? Bitte keine anderen Codes zur Erklärung. Funktionierende Sourcecodes gibt es haufenweise und nur durch Fehler kann man lernen. Danke schon mal für Eure Hilfe. Gruß Axel
<avr/timer.h> ist bogus, die Datei sollte besser verschwinden. Für einen Teil der AVRs ist das kompletter Müll, was da drin ist. Was für einen benutzt Du denn?
buäh ! hartes Urteil (wegen dem letzten Thread?) Nein Scherz beiseite ich nutze einen 8515
Das harte Urteil bezieht sich auf die Datei in der avr-libc. Die kann bestenfalls als Beispiel dienen, aber so wie es da drin geschrieben steht, isses Quatsch mit Soße. Aber gut, für einen AT90S8515 (den wirst Du wohl meinen und keinen ATmega8515 :) gelten die Werte zumindest. Was ich nicht verstehe, wo teilst Du den Timer0 nochmal durch 8? Die Lösung mit der Abfrage der Timerwerte in der Hauptschleife finde ich nicht glücklich. Was ich tun würde: mit dem Einschalten des Timer0 noch den Überlauf-Int für Timer0 einschalten. Dort in einer Variable noch den Vorteiler durch 8 implementieren. Nach 8 Überläufen dann den Wert von PIND2 abfragen, irgendwo festhalten, ein globales Flag setzen und Timer0 wieder abschalten. main() wartet auf dieses globale Flag (muß es natürlich selbst rücksetzen) und wertet das vom Timer-Int eingelesene PIND2 aus. OK, main() könnte sicher PIND2 auch auswerten, so langsam wie das hier alles ist. ;-) Achso, jetzt sehe ich, was Du meinst. Du teilst nicht durch 8, sondern durch 400 (einmal Überlauf abwarten und dann bis 0x91 zählen lassen). Hmm, wer setzt denn das TOV0 eigentlich jemals wieder zurück? Ich denke, Du mußt das mit jedem Neustart des Timers manuell zurücksetzen, da Du ja keine Interrupts benutzt. Jau: ``TOV0 is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, TOV0 is cleared by writing a logical 1 to the flag.'' Beim Restart des Timers wird es nicht automatisch gelöscht. Damit ist es immer Gesetzt, Dein Vorteiler geht also nur bis 0x90 und Du fragst den Status nach 45 ms erneut ab. Logisch, daß dann jedes Bit als gesetzt erkannt werden sollte (außer der Sekunde 59) ;-)
Gelobet seist Du J.W.! Wusste ich doch dass ich irgendetwas wesentliches vergessen hatte. Nun tut es ! Danke Dir. Aber welchen hardwaremäßigen Grund hat es eigentlich, dass man das TIFR Register nicht mit 0x00 initialisieren kann? Bei einem Reset wird es laut Sheet ja auch mit $00 initialisiert. Liegt es etwa daran, dass die reservierten Bits 0,2,4 nur lesbar sind?
Naja, es ist eben kein Register im eigentlichen Sinne. Du bekommst irgendwelche 8 Hardware-Leitungen zusammengefaßt und mit einem Latch auf den Bus gelegt, wenn Du von dieser Adresse liest. Wenn Du auf die Adresse schreibst, werden die 8 Bit auf was anderes aufgeteilt. Warum die IRQs beim AVR in aller Regel mit Schreiben eines 1-Bits gelöscht werden, keine Ahnung. Vielleicht war das einfacher zu realisieren, vielleicht hatten sie ein Vorbild, oder es paßt besser mit der restlichen Interruptlogik zusammen (bei Benutzung echter Interrupts werden die meisten IRQ-Bits ja automatisch wieder gelöscht).
Ja, gut dass es nun funktioniert. Das war ja auch erstmal nur ein check wie ich die Nullen und einsen aus der Pulsdauer bekomme. Dass es eleganter ist dies über Interrupts zu machen ist mir auch klar und hatte ich auch vor. Ich war mir nur nicht sicher ob ich mit den Delay Schleifen für die LED Laufzeitprobleme bekomme, wenn ich die mit in die Interrupt Routine setze. Daher erstmal das ganze fast ohne Interrupt. Habe nun mal das Zeittelegramm von Hand entschlüsselt und wundere mich über die irren Zeiten die ich da bekomme (BCD Code ist klar). Da scheint einiges noch nicht richtig zu funktionieren. Weisst Du ob die 20% Toleranz bei der Pulsdauer im DCF Signal seitens der PTB auch eingehalten werden? Oder variiert die mit dem Empfangssignalstärke / Störungen?
Ich hab das mal mit einem PIC gemacht, AVR ist in arbeit. Die Pulsdauern werden von der PTB sehr genau eingehalten, der Empfänger ist hier im Allgemeinen das Problem. Das Teil von Conrad, das ich verwende, nutzt die Toleranzen voll aus. Über das Telegramm kann man auf meiner Homepage was nachlesen, falls noch bedarf besteht. Uwe http://www.uwe-nagel.de.vu
@Joerg: Da Du hier immer kunstruktive Beiträge leistest, speziell für Dich, die Aufklärung zu den '1'-Bits, um Interrupts zu löschen. Dies stammt von den I/O-Bausteinen der 8080-Serie. Nach Auslesen des Interrupt-Statusregisters, waren dem Prozessor alle Anforderungen (gesetzte Bits) bekannt. Die entsprechenden Routinen wurden ausgeführt und anschließend die gleichen gesetzten Bits zurückgeschrieben (oder auch umgekehrt). Wurden zwischendurch andere Bits im Statusregister gesetzt, so wurden diese durch das Rückschreiben nicht versehentlich gelöscht. Bei den Bausteinen der 6800 oder 6502 Reihe wurden die betreffenden Bits durch Zugriff (lesend oder schreibend) auf das zugehörige I/O-Register gelöscht. Diese Bits (und noch mehr) teilten damals die Welt in zwei Lager: 6800/6502 und 8080/Z80. Das setzte sich mit 68000 und 80286 fort. Heute nimmt man - glaube ich - 8051 und AVR, um sich zu streiten. Gibt ja sonst keine Probleme :-)
Danke für die Erklärung. Ja, die prinzipielle Logic des Intel-PIC ist mir auch noch dunkel in Erinnerung. Erklärt natürlich nicht ganz, warum Atmel sich dieses Prinzip abgeguckt hat, zumal sie ja im richtigen Interruptbetrieb zum ,,anderen Lager'' gehören (IRQ-Bits werden automatisch beim Zugriff auf die entsprechende Hardware-Resource gelöscht).
Der DCF77 sendet schon hochgenau, allerdings auf Langwelle und die kann nun mal sehr leicht gestört werden. Man muß dann beim Empfang schon etwas aufpassen. Wichtig ist es die Anzahl der Impusle je Minute zu überprüfen. Da Störungen ja asynchron sind, hat man dann mehr oder weniger Impulse. Also alles was ungleich 59 ist, wegschmeißen. Wenn man dann noch die Paritätsbits testet, ist man auf der sicheren Seite. Hier mein einwandfrei funktionierender Kode: http://www.mikrocontroller.net/forum/read-4-23408.html Das Bit setzen um zu löschen dürfte die größte Fallgrube des AVR sein. Ich schätze etwa 50% aller AVR-Anfänger fallen mindestens einmal darauf herein. Das Thema wird deshalb hier und auch im AVRfreaks-Forum immer und immer wieder auftauchen. Einen praktischen Nutzen hat es nicht, man muß sich eben damit abfinden. Peter
Naja, allein auf Paritätsauswertung würde ich mich nicht verlassen. Man hat schon hufbeschlagene Tiere vor der Arzneimittelausgabe sich erbrechen sehen... ;-) Einen Plausibilitätstest würde ich da schon noch mit machen, d. h. einer Zeitinformation, die sich grundlegend von der vorherigen unterscheidet, würde ich erst nach dreifach bestätigtem Empfang übern Weg trauen. Das Problem dieser Impulszeiten sind übrigens die relativ preiswerten und dennoch einigermaßen schmalbandigen Filter, die man für 77,5 kHz benötigt. Die 5. Oberwelle der Horizontablenkung unserer Fernseher (78,125 kHz) möchte beispielsweise schon 80 dB oder besser unterdrückt werden. Die Filter ,,klingeln'' dann, d. h. die Impulsflanken werden stark verschliffen. Zusammen mit Amplitudenschwankungen entstehen dann die recht unterschiedlich langen Impulse.
@Joerg, "Naja, allein auf Paritätsauswertung würde ich mich nicht verlassen." habe ich ja auch nirgends behauptet oder gemacht. "Wenn man dann noch die Paritätsbits..." Soll heißen, die sind nur noch das Tüpfelchen auf dem I. Peter
Nö, aber Peter hatte gemeint, daß man mit der Paritätsauswertung ja dann auf der sicheren Seite sei. Ein simples Paritätsbit ist einfach zu schlecht als Fehlererkennung.
@Joerg, "...Peter hatte gemeint..." Was ich gemeint habe, weiß ich doch wohl besser. Und das habe ich ja schon mehr als genügend verdeutlicht. Wenn Du mich unbedingt mißverstehen willst, dann steh bitte auch dazu und sag, daß Du es so und so interpretierst. Das ist dann wenigstens Deine Sache. Aber dichte bitte nicht anderen Leuten irgendwelche Meinungen an. Peter
Ich will Dich nicht mißverstehen, aber das, was Du da geschrieben hast, hatte ich so verstanden, sorry. (Das Programm hatte ich mir nicht angesehen. Das ZIP erst runterzuladen und zu entpacken, war ich zu faul -- schließlich will ich mir gerade keine DCF77-Uhr bauen.)
@Joerg && @Peter scheint mir ein wenig angespannt zu sein Euer Verhältnis. Also ich sehe das so: viele Wege führen nach Rom und der richtige ist meist der, der auch auf die gesetzten Anforderungen passt. Und selbst dann gibt es immer noch verschiedene "richtige" Wege. Ausserdem sind zwei gute Codes besser als einer. Seht es doch einmal so, dass Ihr u.a. mit die Erfahrensten auf diesem Gebiet hier im Forum seid und Euer Potential sicher besser bei der Hilfestellung anderer aufgehoben ist, als wenn Ihr Euch gegenseitig anfeindet. @All Aber mal um zum Thema zurückzukommen. Ich las, das das Modul von Conrad die angegebenen 20% Pulsdauertoleranz ausschöpft. Hat da jemand mal die Möglichkeit dieses genauer zu definieren? Heisst ausschöpfen bis zur Grenze oder darüber? Und wenn darüber, ist es für die Timer interessant wie viel darüber, damit man dies auch vernünftig auswerten kann. Also hat jemand schon einmal mit dem Oszilloskop hier Werte ermittelt? Mein Zeittelegramm ist jedenfalls per Hand decodiert alles andere als richtig. Ich wundere mich über BCD Codes bei denen ich Pseudotetraden ermittle. Also Minutenzahlen über 9. Invertieren und schieben nach links und rechts hat auch nichts gebracht. Hier muss irgendetwas faul sein. Habe auch schon die Zeit der Pulserkennung(High/Low) auf 150ms erhöht. Gleiches Ergebnis. Probiere das Ganze nun noch einmal mit Interrupts bei steigender und fallender Flanke sowie beim Überlaufen der Timer. @Uwe Danke für deinen Link, aber das Telegramm war mir bereits bekannt. Gruß Axel
@Axel, das mit der 150ms-Schwelle sollte im allgemeinen gut funktionieren. Ich detektiere mit 80..120ms und 180..220ms-Fenstern. Stimmen denn wenigstens die 59 Impulse pro Minute ? Allerdings gibt es viele Feinde des DCF77 Signals. Z.B. PC-Monitore und Fernseher sollten mindestens 2..5m weit weg sein. Bei Stahlbetonwänden hilft manchmal nur, den Empfänger aus dem Fenster zu halten. Am besten, erstmal eine LED an den Empfänger anschließen. Dann sieht man sehr gut, ob das Signal gestört ist oder nicht. Mit etwas Geschick kann man auch die 1-en und 0-en mitschreiben. Oftmals wird auch der Fehler gemacht, einen externen Interrupt für die Signalerkennung zu verwenden. Der reagiert aber auf jede noch so kurze Störnadel, d.h. dadurch nimmt die Fehlertoleranz drastisch ab. Abtasten z.B. im 10ms-Raster ist da weitaus sicherer. Mit dem "angespannt" hast Du recht. Ich würde ja niemals sagen, daß der Code eines anderen nicht funktioniert, wenns bei ihm läuft. Aber wenn daß ein anderer über meinen Code behauptet, ohne ihn jemals ausprobiert zu haben, finde ich das gelinde gesagt sehr unschön. Peter
Also, die Pulse kommen (Logiktester) sauber rüber, daher gehe ich davon aus das der Empfänger einen guten Empfang hat. 59 Pulse sind es auch immer. Habe bis jetzt keine andere Zahl gehabt. Ich muss schon mitschreiben um behaupten zu können dass ich irgendetwas falsches ermittle. Das mit dem 10ms Raster ist eine gute Idee, werde ich mal nachverfolgen. Aber Joerg hatte nicht behauptet dass Dein Code nicht läuft, er hatte lediglich gesagt dass Ihm eine simple Prüfung des Paritätsbits nicht reichen würde. Das war lediglich seine Meinung aber nicht eine Behauptung dass Dein Code nicht läuft. Aber jetzt habe ich mal ne Frage zur Beschreibung Deines Codes. Du sagst, dass zur Fehlererkennung die Überprüfung des Paritätsbits, sowie die Anzahl der Pulse(Sekunden) Dir als Fehlererkennung reichen. Was ist aber wenn zwei Bits im Zeittelegramm kippen? Dann stimmt doch das Paritätsbit wieder und die Anzahl der gezählten Sekunden ist auch richtig und trotzdem ist die ermittelte Zeit falsch. Oder? Hast Du da noch eine andere Kontrolle implementiert? Z.B. Erkennung von unmöglichen Werten(Pseudotetraden)? wie z.B. ich Sie festgestellt habe. Ich frage daher weil Dein Code in Assembler ist und ich aus dem C Bereich komme und mich mit Assembler auf dem AVR erst anfreunde. Daher kann ich Deinen Code noch nicht so richtig deuten. Gruß Axel
Ja, jetzt weiß ich auch, warum sich Peter auf den Schlips getreten gefühlt hat. ;-) Axel hat Recht, ich habe nirgends behauptet, der Code würde nicht funktionieren. Meine Bemerkung bezog sich darauf, daß ich sehr wohl schon industrielle DCF77-Uhren gesehen habe, die sich mitten am Tag plötzlich um einige Stunden verstellt haben... Daher würde ich das in sich schlüssige und korrekt ausgewertete Zeittelegramm persönlich in einer Uhr eben nur dann wirklich benutzen, wenn es auch in den Kontext paßt. Wenn meine letzte Zeit 0259 Uhr war und mir jetzt plötzlich der Empfänger behauptet, es sei 0600 Uhr, dann würde ich das erst glauben, wenn ich danach auch noch 0601 und 0602 gesehen habe.
@Axel, "Was ist aber wenn zwei Bits im Zeittelegramm kippen?" Nagut, ich wills nochmal erläutern: Der DCF77 wird immer korrekt ausgesendet, davon gehe ich aus. Um trotzdem die Zeitbedingungen einzuhalten, die ich abteste, müßten dann die 2 Störungen wirklich exakt synchron zum DCF77 sein und auch den gleichen Pegel haben. Störungen sind aber immer zufällig, d.h. eine solche Synchronität tritt praktisch nicht und erst recht nicht 2-mal kurz hintereinander auf. Wenn man so will ist das auch schon eine Art von Plausibilitätsprüfung aber eben auf der Bitebene. Exakt kann man natürlich nicht sagen, welche Methode nun besser oder schlechter ist. Und ich habe Joerg so verstanden, daß er sich sicher ist, daß mein Algorithmus schlechter ist, d.h. öfter mal "nicht funktioniert". Ich habe jedoch diesen Algorithmus schon mehrere Jahre auf verschiedenen Uhren laufen und noch nie wurde eine falsche Zeit beobachtet. Ich habe ihn aber dort in C auf einem AT89C2051 programmiert. Da Du ja mit C besser zurechkommst, ist hier mein C-Code: http://www.specs.de/users/danni/appl/soft/c51/dcf77/index.htm Die Bezeichnungen "idata" und "code" dienen beim 8051 nur zur Unterscheidung zwischen RAM und Flash. Mit: #define idata #define code kannst Du sie beim AVR einfach ausblenden. Wenn ich es richtig verstehe müßte aber der Algorithmus von Joerg insgesamt 6 Minuten pro Jahr die falsche Zeit anzeigen, dadurch, daß die Sommer-/Winterzeitumstellung jeweils 3 Minuten zu spät erfolgt. Bei "industriellen DCF77-Uhren" stellt auch das Wort "industrielle" keinerlei Gütesiegel in Bezug auf die Softwarequalität dar, auch wenn deren Preis noch so hoch ist. Peter
Nö Peter, warum soll man bei der Sommer-/Winterzeitumschaltung die falsche Zeit bekommen? Das DST-Bit selbst bekommt man doch auch mit, insofern kann man das doch in die Plausibilitätsprüfung mit aufnehmen, oder? Wenn im Umschaltmoment das Zeittelegramm nicht richtig empfangen wird, verpaßt Du die Umschaltung, aber das passiert ja dann sowieso. (Inwiefern es überhaupt sinnvoll ist, daß der DCF77 lokale Zeit überträgt und nicht UTC, bleibt dahingestellt. Für eine ernsthafte Weiterverwendung würde ich sie für mich auf UTC umrechnen, dann verpaßt man die Umschaltung auch dann nicht, wenn man in dem Moment gerade keinen Empfang hat, da man selbige ja lokal unabhängig vom Sender vornimmt. So funktioniert letztlich ein NTP-Dämon, wenn er von einem DCF77-Empfänger gesteuert wird.) Mit industriellen Uhren meinte ich übrigens mitnichten irgendwas teures, sondern irgendeinen billigen Funkwecker, bei dem ich sowas gesehen habe. Übrigens habe ich nirgends entweder/oder vorgeschlagen. Ich denke, man sollte einfach alle möglichen Überprüfungen miteinander kombinieren. Just MHO.
@Joerg, so isses: Du verläßt Dich doch nicht ALLEIN auf Deinen Algorithmus und ich verlasse mich auch nicht ALLEIN auf das Paritätsbit. Hauptsache es funktioniert und das tut es ja. Das mit der Sommerzeit gefällt mir auch nicht. Bei meiner DS1994-Routine hab ich doch ganz schön gegrübelt, wie ich das am besten hinkrieg. Für die UTC-Ausgabe must Du dann ja auch einen vollständigen Kalender mit Sommerzeitregel mitlaufen lassen, wie ich in meinem DS1994-Code: http://www.mikrocontroller.net/forum/read-4-32158.html bloß eben mit der Umstellung rückwärts. Peter
Naja, da man ja weiß, daß der DCF77 nur zwischen 2 und 3 Uhr vor und zurück stellt und ansonsten ME(S)Z fährt, sollte es doch genügen, wenn man nur die Stunde korrigiert, oder übersehe ich da was? Daß die Problematik ansonsten komplex ist, ist mir vom timezone Code aus den Unixen her gut bekannt... Man kann das beliebig übertreiben, wenn man will :-), allerdings ist es für eine Uhr sicher nicht so wichtig, ob sie das Datum auch noch 1946 mit der doppelten Sommerzeit des Besatzungsregimes im Nachkriegs- Berlin noch richtig darstellen kann... :-)
Wenn Du z.B. Deine DCF77 Uhr am 1.4. um 0:30Uhr einschaltest, must Du schon irgendwie auf den 31.3. um 23:30Uhr zurückrechnen und nicht den 1.10. um 255:30Uhr anzeigen. Nur die Sommerzeitregel brauchst Du nicht. Peter
Ja, klar, das hatte ich vergessen... Ich war nur vom laufenden Betrieb ausgegangen. Um so ekliger, daß sie kein UTC senden wie jede vernünftige sonstige Zeitquelle. :-(
Hallo Peter, da hat mir doch Dein Tipp weitergeholfen. Habe nun das Signal im 10ms Rythmus per Interrupt gescannt und den Scanvorgang mit der steigenden Flanke gestartet. Nun komme ich auf wesentlich schlüssigere Zeiten bei der Decodierung. Sieht gut aus. Wie schaut es bei uC´s eigentlich unter C mit globalen Variablen aus? Habe mal gelernt, dass diese möglichst zu vermeiden sind. Erzeugen die mehr code beim kompilieren als wenn ich das ganze per Zeiger löse? Gibt es irgend einen Hinweis was die Bits 1-14 im Zeittelegramm darstellen. Ich habe hier immer ein Low. Gruss Axel
Die Bits 1-14 haben keine offizielle Bedeutung. Codierung nach Bedarf, steht bei http://www.dcf77.de . Ich hab hier auch bislang nur 0 beobachtet. Meine DCF-Plausibilitätskontrolle funktioniert so: Ich habe eine Uhr samt Kalender programmiert, welche durch das DCF-Signal synchronisiert wird. Die gleiche Routine zählt einfach die vorletzte empfangene Zeit um eine Minute weiter und vergleicht diese mit der zuletzt empfangenen. Sind beide gleich, wird neu synchronisiert. Geht sehr zuverlässig, erkennt nur die Sommerzeitumschaltung zwei Minuten zu spät. Das kann man durch Lockerung der Überprüfung bei gesetzter Ankündigung auch noch beseitigen. Gruß Uwe http://uwe-nagel.de.vu
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.