Anbei mein 8051-Code portiert auf AVR-GCC mit ATtiny26.
Der MAX7219 stört den Empfang, daher wird zur Synchronisation um 3.20
Uhr dunkel geschaltet.
Peter
Sicher das du den DCF77 empfänger mit einem gut dimensionierten RC-Glied
gut abgeblockt hast? Ansonsten kann ich mir gar nicht vorstellen warum
der MAX7219 den Empfang stören sollte. Ich hatte das gleiche Problem bei
einer LED Matrix, der RC Filter vorm Empfänger hat's behoben.
Der MAX7219 erzeugt nen Multiplextakt mit hohen Impulsströmen.
Halte ich die Ferritantenne etwa 10cm entfernt geht es auch mit Display.
Ich wollte aber nur ein kleines Gehäuse nehmen, d.h. die Ferritantenne
sitzt direkt hinter dem Display.
Ich hab den Conrad-Modul direkt an 5V, der hat ja nochmal ne
Spannungsstabilisierung und Treiberstufen.
Peter
Tolles Programm, der Code ist mal wieder typisch Peter:
Unglaublich mit wie wenig Zeilen Code man ein Programm schreiben kann.
Aber ich habe den Sinn vom MAX7219 noch nicht verstanden:
Klar ist das ein gutes IC zum Multiplexen von Siebensegment-Anzeigen
oder LED-Matrixen. Aber 6,95 EUR sind halt auch ein Wort. Da kann ja
jeder ATmega locker mithalten.
> Unglaublich mit wie wenig Zeilen Code man ein Programm schreiben kann.
Stimmt. Allerding macht diese Kürze den Code sehr kryptisch und für
einen unerfahrenen Programmierer nahezu unlesbar. Dies soll jetzt aber
keinesfalls negativ gemeint sein.
Armin K. wrote:
> Aber ich habe den Sinn vom MAX7219 noch nicht verstanden:
Ich nehme ihn gerne, weil sich dadurch das Layouten sehr vereinfacht.
Aber das Programm ist ja modular aufgebaut.
Es ist also kein Problem, ne andere Displayroutine einzufügen.
Z.B. im ADC- und im Jumbo-LED-Beispiel ist ne Multiplexanzeige mit dem
AVR drin.
Peter
Peter Dannegger wrote:
> Ich nehme ihn gerne,
Ich nehme ihn eher ungern, nehme den MAX7221 anstelle des 7219
(allerdings ist der noch teurer). Erstens hat der echtes SPI und
zweitens "Slew-Rate Limited Segment Drivers for Lower EMI". Könnte
letzteres nicht sogar auch das Problem der Störungen lösen?
Gute Arbeit, Peter, danke dafür!
Propper wrote:
>> Ich nehme ihn eher ungern, nehme den MAX7221 anstelle des 7219> (allerdings ist der noch teurer). Erstens hat der echtes SPI
Was ist daran ein Vorteil ?
Beide kann man am 8051/AVR ohne Probleme anschließen.
Ob nun Pin 12 die ganze Zeit Low oder nur am Ende ne Flanke machen muß,
ist doch völlig wurscht.
Das mit der Slew-Rate könnte tatsächlich helfen, aber ich hab eben noch
einige 7219 rumliegen, zum wegschmeißen wärs zu schade.
Immerhin synchronsiert er besser, als ein gekaufter Funkwecker, der geht
seit gestern 2 min nach, manchmal wars auch ne Stunde.
Peter
Hallo!
Ich will den Code unter meiner Umgebung (mega8) zum laufen bekommen. ;-)
Läuft aber net...
1. Frage: vom DCF-Modul den "normalen" oder den invertierenden Ausgang?
2. Frage: Mein AtMega8 läuft mit externem Quarz bei 3686400 Hz.
Was muss ich da in der timebase.c aendern?
Ich guck nur wie das Schwein ins Uhrwerk...
#define T0COUNT (XTAL 1024 64) // 183
#define T0SECERR (XTAL - 1024L 64 T0COUNT) // 6912
#define T0COUNTSEC (T0COUNT + T0SECERR / 1024) // 189
#define T0MINERR (XTAL - 1024 * (63 * T0COUNT + T0COUNTSEC)) // 768
#define T0COUNTMIN (T0COUNTSEC + (T0MINERR * 60 + 512) / 1024) // 234
vielen Dank für Eure Hilfe
Stefan
Matthias wrote:
> kann ich mal die Schaltung sehen? In der wo der MAX.. den Empfang> stört..
Schaltplan habe ich keinen.
Die 5V werden aus ner Trafo-Wandwarze mit nem 7805 gemacht und noch
220µF dahinter.
Alle ICs haben µ1-Pillen, der 7805 hat 2, also insgesamt 4 Stück.
Das Conrad DCF-77 ist mit etwa 30cm 3-adrig angeschlossen, strecke ich
die 30cm aus, gehts auch mit Anzeige an.
Peter
swesch wrote:
> 1. Frage: vom DCF-Modul den "normalen" oder den invertierenden Ausgang?
Ich habe den äußeren Anschluß freigelassen.
> 2. Frage: Mein AtMega8 läuft mit externem Quarz bei 3686400 Hz.
#define XTAL 3686400L
Peter
Hallo Peter!
>> 1. Frage: vom DCF-Modul den "normalen" oder den invertierenden Ausgang?>Ich habe den äußeren Anschluß freigelassen.
So verwende ich das DCF-Modul auch
>> 2. Frage: Mein AtMega8 läuft mit externem Quarz bei 3686400 Hz.>#define XTAL 3686400L
Reicht das schon aus???
in timebase.c wird ja im SIG_OVERFLOW0 eine "time base 1 second"
aufgesetzt:
// time base 1 second
TCNT0 = (u16)(256 - T0COUNT); // reload per tick: -183
if( ++ct_64Hz & 0x3F ){ // 64 ticks = one second
timeflags = 1<<ONE_TICK; // one tick over
return;
}
Bei dem Takt von 3686400Hz und Prescale 1024 wird TCNT0 doch alle 0,27ms
hochgezählt.
Dann dauert ja "meine" Sekunde 183 64 0,27ms = 3,253 Sekunden.
Muss da nicht doch an mehreren Stellen im Code angepasst werden.
Sorry, ich bekomm das alleine noch nicht geregelt, bin Anfänger..
Kannst Du mir da beim Anpassen helfen?
Danke
Stefan
Ja, der Kommentar stimmt natürlich nicht mehr bei nem anderen XTAL-Wert.
Also nicht -183, sondern der Wert, der aus der Formel im Define
rauskommt.
Peter
So jetzt läuft die Uhr erst mal....
Ich hab die Ausgaberoutinen auf ein LCD umgeschrieben.
Die Uhr versucht immer ein aktuelles DCF-Signal zu fangen.
(keine Displayabschaltung)
Leider zeigt's manchmal völlig falsche Uhrzeiten an.
Was ich bereits probiert habe:
- geschirmte Leitung 2m zum DCF-Modul
- "normales" Trafonetzteil
- weit ab von laufenden PC's und Monitoren etc.
Was kann ich noch tun?
Stefan
swesch wrote:
> Ich hab die Ausgaberoutinen auf ein LCD umgeschrieben.
...
> Leider zeigt's manchmal völlig falsche Uhrzeiten an.
Ohne Programm kann man dazu schlecht was sagen.
Der Fehlertest ist jedenfalls sehr streng. Er übergibt lieber keine
gültige Zeit, als eine fehlerhafte.
Bei gekauften DCF77-Weckern habe ich dazu im Gegensatz schonmal falsche
Zeiten sehen können.
Daher wird der Fehler vermutlich in Deinen Änderungen (LCD-Routine)
liegen.
Peter
So, ich noch mal!
Ich hab alles noch mal durchgeschaut. Kann leider nichts "verdächtiges"
finden.
Wie gesagt, das Projekt ist auf ATMega8 @ 3686400 Hz geändert.
Die MAX-Bibliotheken hab ich entfernt, da ich ja aufs LCD ausgebe.
Die Ausgabefunktion hab ich komplett in clock.c verschoben.
Die Anzeige enthält oft falsche Zeit und Datumswerte.
Please help ;-)
Stefan
Hmm.
Könnte vielleicht die LCD-Ausgabe zu lange dauern.
Ruf mal das scan_dcf77 im Timerinterrupt hinter dem DCF77-Empfang auf,
statt im main.
Es ist ja nur sehr wenig Code, kann man also auch direkt im Interrupt
machen, dann spielt die Main-Zeit keine Rolle mehr.
Peter
swesch wrote:
> Ich versteh nur nicht warum...
Die Routine funktionert nur, wenn sie garantiert bis zur nächsten Flanke
aufgerufen wurde, also innerhalb 100ms.
Wenn die Mainloop aber länger dauert, dann muß man sie in den Interrupt
mit reinhängen. Dann ist es egal, wie langsam die Mainloop ist.
Und wenn die Mainloop länger als 1s dauern kann, muß man auch die
clock-Routine mit in den Interrupt reinhängen.
Solange keine anderen zeitkritischen Interrupts bestehen (z.B. schnelle
Mehrkanal-Software-PWM) ist das total unkritisch.
Manche Leute hängen sogar Delays oder Divisionen mit in Interrupts rein,
das kann dann oft sehr böse ins Auge gehen.
Peter
hallo nochmal!
das von vorhin ist quatsch, der code von peter danneger soweit mit dem
lcd-kram zusammengebaut ist ja gerade mal gut 1K. die hex-grösse hat
wohl nix mit der richtigen grösse zu tun.
ich bin also dabei das auf einem tiny2313 zu versuchen, mit 4 mhz ist
der getacktet.
ich glaube alles funktioniert soweit, der sekundentakt kommt auch in der
main an, nur bei if( synchronize == 0 ) is dann wohl schluss. jetzt
möcht ich halt rausfinden, wo da das problemchen liegt. kann ja so
schwer nich sein!
könnte darum jemand bitte die funktion von der variable synchronize
erklären, mein grips lässt langsam nach, und ich wollte so gerne noch
wissen wie spät es ist!! :-)
danke schonmal!
ach so!
ich habe noch gar keine richtige ausgabe im programm. da wo die
originalen ausgabeaufrufe standen, will ich nur ein zeichen aufs display
schreiben. das würde nicht lange dauern, aber soweit kommt es ja leider
nicht.
neo_87 wrote:
> könnte darum jemand bitte die funktion von der variable synchronize> erklären
synchronize wird gesetzt, wenn scan_dcf77 ein Paket vollständig und
fehlerfrei empfangen hat, das kann 3min dauern bzw. bei Störungen länger
(vom PC weggehen oder ausschalten).
Wenn Du das STK500 benutzt, kannst Du ja mal newtime.second auf nen Port
ausgeben und mit den LEDs ansehen (1 = LED aus), der muß im Sekundentakt
von 0..58 zählen.
Peter
hallo peter, danke für deine hilfsbereitschaft!
so ganz habe ich dein programm noch nicht durchschaut aber ich bin auf
dem weg. habe es erstmal auf den aktuellen avr-gcc stand gebracht.
wahrscheinlich haben sich da fehler eingeschlichen.
könnte mal versuchen den wert auf das lcd zu schreiben. hab erstmal in
scan_dcf77 bei
if( dcf77_period )
{
PORTD ^= (1<<PD1);
...
einen pin getoggelt. das klappt auch gut, die 59. ist nicht dabei.
aber das hat ja wohl seine richtigkeit.
werde mal ein paar werte anzeigen lassen.. danke für den code!
das problem liegt bei der pulslängenprüfung für die eins
4..7 = 0
11..13 = 1
habs für die 1 mal ein bisschen vergrössert:
if( dcf77_pulse > 10 && dcf77_pulse < 15 )
damit klappt es.
noch 2 fragen: wieso castest du den wert für den 8-bit timer als u16?
und kann man sich eigentlich die vom compiler berechneten werte
irgendwie baim compilen ausgeben lassen?
so jetzt mal die zeit ausgeben. super, danke!
Hallo Peter,
beim ausprobieren Deines Codes ist mir etwas aufgefallen:
Der Timer läuft 64 Mal pro Sek. über. Somit sind die 100ms bzw.
200ms-Bitzeiten 6,4 bzw. 12,8 Überläufe lang (Nachkommastelle nur der
Theorie wegen;-). Bei mir betragen sie meist 7 bzw. 13 Überläufe.
in der Funktion scan_dcf77() testest Du die Bit-Gültigkeit auf
if( dcf77_pulse > 3 && dcf77_pulse < 8 ) bzw.
if( dcf77_pulse > 10 && dcf77_pulse < 14 ).
Da das in meinem Fall grad so an der Grenze mit der realen Überlaufzahl
liegt, wurde die Zeit eher selten erkannt. Durch hochsetzen auf
if( dcf77_pulse > 5 && dcf77_pulse < 9 ) bzw.
if( dcf77_pulse > 11 && dcf77_pulse < 15 )
klappt es super.
Vielleicht hab ich ja auch einen Denkfehler (ist schon spät...) - aber
wenn deckt der sich prima mit der Funktionssicherheit;-))
Gruß Frank
@Frank,
ich hatte angenommen, es wird abgerundet, müßte nochmal genauer in das
Programm sehen.
Welchen Quarz nimmst Du denn und welchen Empfängermodul ?
Vielleicht werden die Pulse ja durch den Empfänger etwas verschliffen.
Wie ich damals die Fenster ermittelt habe, weiß ich nicht mehr.
Hast aber recht, die sollten schon mittig um die Impulslängen liegen.
Peter
Die Ticks sind wegen Integer-Rundung von T0COUNT statt 1/64 Sekunden
1/64,25 Sekunden. 100ms benötigen demnach 6,425 Überläufe. Meine
Eingangsschutzschaltung mag etwas verschleifen, daraus resultieren wohl
die 7 bzw. 13 Überläufe. Als DCF-Quelle benutze ich momentan wegen
Empfangsproblemen den RS232-DCF77-Simulator
Beitrag "Re: DCF77-Signal generator" .
Und wer weiß, was Windows daran noch zusätzlich zeitlich verschmiert ;-)
Gruß Frank
Hey,
Ich versuche gerade mich hier durch den Code zu lesen und erst mal einen
groben Überblick zu bekommen. So ganz anfänger bin ich nicht mehr aber
noch weit vom Pro entfernt.
Habe da ein paar Verständniss-Fragen:
Könnte mir jemand erklären was diese Zeilen machen?
i = LPM(&BITNO[i]);
*d += LPM(&BMASK[i]); // set bit
Set bit?? Ich hab keine Ahnung was dieses LPM eigentlich ist.....
Thanx
Sebi
Sebastian wrote:
> Könnte mir jemand erklären was diese Zeilen machen?>> i = LPM(&BITNO[i]);>> *d += LPM(&BMASK[i]); // set bit
Jedes Bit hat eine bestimmte Bedeutung (Variable, Wert) und der Wert
steht
in der Tabelle BMASK (1,2,4,8,10,20,40 oder 80).
> Set bit?? Ich hab keine Ahnung was dieses LPM eigentlich ist.....
Ist in types.h definiert:
#define code PROGMEM
#define LPM(i) (__LPM_classic__(i))
Es ruft GCC-Macros auf, um konstante Daten im Flash zuzugreifen.
Peter
Hey, ich nochmal
Also ich finde den code klasse, kryptisch aber echt gut.
Hab noch mal die Beiträge gelesen und wollte wissen ob ich hier gerade
auf dem Schlauch stehe....
Also man will die Monatstage bei dem erreichen des Monatsmaximums
(MDAYS[monat]) wieder auf eins setzen.
Das heißt doch ich suche mir aus dem Array MDAYS[] meinen Wert und
vergleiche den dann mit time.day!?
Die im Beitrag genannte Zeile müsste dann doch heissen:
if( (LPM(MDAYS[i])+1) == time.day )
Und noch ne Frage hätte ich da:
Wenn in der DCF77.c die Variable Synchronize auf 0xFF gesetzt wird, was
geschiet dann mit ihr?
In Main wird ja nur auf 1 oder 0 geprüft.
Ich habe keine Stelle gefunden an der Synchronize auf 1 gesetzt wird...
Freue mich über ein paar Klarheiten
Sebastian
Hey,
Nachdem ich mich eine Woche mit dem Code beschäftigt habe und mein Paket
von Rei** angekommen ist, hatte ich über die Weihnachtstage endlich Zeit
mein Projekt mit der Funkuhr in Angrif zu nehmen.
Meine Idee war meiner Mom, die nicht wirklich was vom Dualsystem
versteht etwas zu 'basteln' an dem sie es lernt!
Die Idee dazu habe ich im Methematikum in Giessen gefunden, in dem eine
solche Uhr aufgebaut ist. Als ich die gesehen habe war klar: die MUSS
ich nachbauen. Also was ich dann gemacht habe ist folgendes:
Ein Board zusammen gefriemelt mit ATMega16(den hatte ich noch
rumliegen). Per SPI dann 3 Schieberegister (74HC595) ran gemacht, die
zusätzlich mit RCK an einem Port liegen um sie einzeln an zu steuern. An
die Ausgänge der Schieberegister hab ich jeweils nen Transistor der
immer 2 LED's mit 9V versorgt ran gehängt.
Dann noch ein DCF-Modul vom großen C einfach direkt an PD7 und fertig
war die Hardware.
Peters Code hab ich dann um die Ausgaberoutine erleichtert und meine
eigene dran gebastelt. Die dauert bei 12MHz nur ein paar nanoSec und
daher kein Problem in Main.
Nachdem dann endlich die ganzen Kabel verlegt waren war es Zeit für
einen Fkt. Test. Sie läuft super! Wenn ein Paket richtig Empfangen wurde
kann man sogar beobachten wie sie neu synchronisiert. Probleme gibt es
nur wenn man mal den Stecker zieht. Bis die Initialisierung wieder
klappt muss man teilweise 5-6mal Strom an - Strom aus spielen....
Wenn jemand ne Ahnung hat woran das liegt wäre ich für nen Tip dankbar.
So Bilder hab ich auch mal ran gehängt und wenn ich Zeit habe dann kann
ich auch noch mal den Code rein stellen, natürlich nur wenn das mit
Peter in Ordnung geht.
Schönes neues noch
und auf bald
Sebastian
Kannst du messen, ob das Problem am DCF77 Modul liegt, dass es einfach
keine Daten ausspuckt? So könnte man das Problem eingrenzen.
PS: Wo wohnst du? Ich war schon 2x im Mathematikum, hab die Uhr noch
nicht gesehen, muss also relativ neu sein oder?
Hey,
Hab ne LED am DCF77 Modul. Manchmal spuckt es nix aus und das ändert
sich auch dann nicht mehr. Hab das mal so 30min einfach laufen lassen.
Strom aus Strom an und wenn man Glück hat dauert so ca 4sec und dann
spuckt es was aus. Nur LED's der Anzeige gehn nicht an. Strom aus Strom
an und mit noch mehr Glück funst es enlich....
Die Uhr dürfte schon mehr als 3 Jahre stehen. Hab die das erste mal
gesehen als ich angefangen habe zu studieren. Wohne ausserhalb von
Giessen irgendwo hinter der Army Base....
Die Uhr steht ganz oben rechts.....
Hmm das mit den 3 Jahren kommt etwa hin ... kurz davor war ich das
letzte mal da (noch mit der Schule).
Zum Thema:
Da die DCF77 Module sehr wenig strom ziehen kann man eigentlich ohne
Probleme einen RC Filter davor hängen um Störungen durch die
Versorungsspannung zu minimieren.
Ich hab hier nur nen DCF77 Modul von Reichelt, das Spuckt eigentlich
schon nach wenigen Sekunden was aus. Das Modul hat aber auch nur nen
Bockkondensator in der nähe.
Warum der Code nicht tut kann man leider ohne Code nicht direkt
überprüfen ;)
Aber sonst: schöne Uhr und vor allem nicht so klein wie all die anderen
Uhren in dieser Form !
PS: Ich wohne bei Marburg.
Hallo,
Ich hab jetzt auch ein DCF 77 Modul an mein STK500 gehängt. Als Ausgabe
benutz ich ein LCD Display an Port D. Das DCF Modul hängt an PC2. Leider
funktioniert das Ganze noch nicht ganz. Es wird nie mit der DCF77 Zeit
synchronisiert.
Ich benutz einen Mega 8 mit 8 Mhz internen Takt. Die normale Uhr zählt
brav nach oben.
In der Main habe ich folgenden Code auskommentiert:
1
/* if( synchronize == 0 )
2
continue;
3
if( synchronize == 1 && time.hour == 3 ){
4
if( time.minute == 20 )
5
6
if( time.minute == 28 )
7
synchronize = 2;
8
continue;
9
}
10
if( time.hour == 4 )
11
synchronize = 1;*/
Im Code toggle ich eine Led nach if( dcf77_period )
Da blinkt die Led ordentlich. Ich geb auch newtime.second auf dem
Display aus. Die Variable zählt aber nur sporadisch nach oben (nicht im
Sekundentakt)
Die Variable synchronize bleibt immer 0.
Weiß jemand woran es liegen kann?
Danke im Voraus
Gruß Robert
Vielleicht schlechter Empfang?
Die spannungsversorgung vom STK500 kann auch schuld sein, die module
sind SEHR empfindlich gegen spannungsschwankungen.
mal nen RC filter in der VCC leitung probieren.
Versuche von Peter den Code zum laufen zu bringen bekomme aber immer
eine Fehlermeldung:
AVR PROGRAMME__ ASSEMBLER\tn12def.inc(141): error: F: Unknown
instruction or macro
die Zeile sieht da so aus :
.equ E2END = 3F
was mache ich da falsch??
Hallo,
ich bin gerade dabei den Code zu verstehen, da ich ihn auf einen Tiny44V
portieren möchte. Außerdem soll die Uhr Batteriebetrieben funktionieren.
Also AVR Takt runter auf 250Khz und den DCF Empfänger die meiste Zeit
vom Strom getrennt. Die Uhr soll nur den Wochentag (7 LEDs) anzeigen,
also kommt es auf ein paar Sekunden +- nicht an.
Den Timebase Teil habe ich verstanden.
Syncronize sorgt dafür, dass das Display ausgeht, wenn knapp 24 Std kein
korrekter Empfang mehr vorlag und danach wieder an. Eine weitere
Funktion scheint es nicht zu geben.
Müsste ich mit dem Pulslängenvergleich nicht auch Probleme bekommen? Der
interne Oszillator darf ja +-10% abweichen.
Hallo nochmal,
also der Code funktioniert bei 1MHZ super. Aber gibt es irgend einen
Grund, warum er bei 500kHZ oder 250KHz nicht AVR Takt nicht
synchonisieren möchte?
Ich habe verschiedenes Versucht
1. Takt auf 500kHz und XTAL angepasst
2. Takt auf 250khz Teiler für Timer0 auf 64, XTAL und Formeln angepasst
3. Takt auf 250khz, XTAL auf 1MHZ gelassen, Formeln unverändert gelassen
aber Teiler für Timer0 auf 256 reduziert.
Um die Toleranz zu erhöhen habe ich die beiden Zeitgschranken zum Bit
erkennen jeweils um +1 und -1 vergrößert.
Die Hauptschleife besteht nur aus ein paar if Abfragen zum Port setzen
und andschließendem aktivieren des Idle Modus des Controllers.
Hier jetzt meine Version basierend auf der von Peter, für einen Tiny44V
(oder auch Tiny24V..). Die Ansteurung des MAX7219 wurde entfernt.
7 LEDs zeigen jeweils an, welcher Wochentag gerade ist. Ideal für ältere
vergessliche Leute, für die kaufbare LCD Uhren zu schwer lesbar sind.
Nach dem Synchronisieren liegt der Stromverbauch bei 487µA (inclusive
~360µA für eine LED), damit müsste die Schaltung bis zu 4000 Stunden =
~5 Monate mit zwei 2000mAh Akkus laufen (meist aber wohl weniger wegen
der Selbstentladung).
Ich hatte zunächst versucht den Stromverbrauch durch Absenken des Taktes
auf 32kHz nach dem Synchronisieren weiter zu reduzieren und zum
Weiterlaufen der Uhr nur noch sekündlich ein Wake-Up des Kontrollers
auszuführen. Aber dies hatte auf den Stromverbauch keinen messbaren
Einfluss, so dass ich dies wieder sein gelassen habe.
Hallo Peter,
versuche gerade deinen Code auf einen Tiny2313 umzustricken. Der gleiche
Timer soll auch das Multiplexen der 7Segmentanzeigen übernehmen. (Man
kann ja nie wissen für was man den anderen Timer noch braucht ;-) )
Der Gedanke ist:
Timer0 Frequenz = 1024Hz;
Das DCF Signal nur in jedem 16. Durchlauf prüfen. (8Bit Variablen)
Zum Verständnis "richtigerweise" müßte doch die DCF77 Abfrage nach dem
setzen von TCNT0 geschehen. Ich sehe ein das die paar Takte um das dcf
Signal abzutasten an der Genauigkeit so gut wie keinen Einfluß haben,
aber da ich das 7Segment Multiplexing auch noch im ISR machen muß kommen
da noch ein paar Takte dazu. Möchte nur sicher gehen das ich da keinem
Gedankenfehler aufsitze :-)
Ich hoffe ich muss die Anzeige nicht abschalten für den Empfang mit dem
Pollin Modul da prasselts immer noch (100µF,100nF,Akkubetrieb) ganz
schön auf den 5V rum!
Grüße
kaffeetas
Hallo,
ich brauche für eine ganz simple Einschaltverzögerung für ein kurzes
anliegendes Signal von 1-1,5 Sekunden (bzw. einstellbar in 0,1 sec).
Mit diesem Programm lässt kann man einfach einen Port 1 bis 2 Sekunden
einschalten.
1
...
2
(timeflags&1<<ONE_SECOND){
3
...
Was muss ich in der timebase.c an den Timer ändern oder erweitern,
um die 0,1 Sekunden einstellen zu können?
Grüsse, Günter
Hi,
bei mir klappt der Empfang ganz ausgezeichnet. Allerdings ist mir
unklar, warum die Variable synchronize außer bei der Initialisierung an
keiner Stelle im Code auf 0 gesetzt wird.
Damit ist der Empfang nach dem ersten richtig empfangenen Paket (d.h.
einer vollen Minute) immer ok- oder? Ich hätte erwartet, daß irgendwo
die Variable dcf77error ausgewertet wird.
Z.B. am Ende der Funktion scan_dcf77(), ich habe hier zwei Zeilen
eingefügt, damit bei einem Fehler (dcf77error) auch synchronize auf 0
gesetzt wird:
1
voidscan_dcf77(void)
2
{
3
[..]
4
if(dcf77_period<60||dcf77_period>70)
5
dcf77error=1;
6
}
7
dcf77_period=0;
8
}
9
// added: <-----------------------
10
if(dcf77error)
11
synchronize=0;
12
}
Oder steckt irgendwo ein Denkfehler?
Grüße
schnack
C. D. schrieb:
> Hi,> bei mir klappt der Empfang ganz ausgezeichnet. Allerdings ist mir> unklar, warum die Variable synchronize außer bei der Initialisierung an> keiner Stelle im Code auf 0 gesetzt wird.
Das ist schon richtig so.
0 bedeutet, warte bis eine gültige Zeit empfangen wurde und schalte dann
das Display ein.
Danach wird nur bei Bedarf um 3.20Uhr das Display ausgeschaltet für
neuen Empfang.
Peter
Hi Peter,
hm. Jetzt wird es mir klar. In Deinem Originalcode läuft die Uhr ganz
normal weiter, wenn keine DCF77-Information vorliegt und übernimmt die
empfangene Zeit nur dann, wenn diese gültig ist.
Ich versuche den Code so zu nutzen, daß die empfangene Zeit nur dann
veröffentlicht wird, wenn sie auf einem validierten Empfang beruht, d.h.
wenn kein gültiger Empfang, dann soll der Code "schweigen" - ich habe
auch keine Uhranzeige angeschlossen, sondern der Code soll in ein
Netzwerk nur dann seine Zeit melden, wenn auf sie Verlaß ist. Deswegen
auch meine Nachfrage wegen dcf77error.
Grüße
schnack
Helmut schrieb:
>> Unglaublich mit wie wenig Zeilen Code man ein Programm schreiben kann.>> Stimmt. Allerding macht diese Kürze den Code sehr kryptisch und für> einen unerfahrenen Programmierer nahezu unlesbar. Dies soll jetzt aber> keinesfalls negativ gemeint sein.
Naja, ich würd mich nicht als unerfahren bezeichnen... das alles
auseinander zu klabüstern (regelrechte Header etc.) und die magischen
Zahlen rausfischen nimmt schon was Zeit in Anspruch.
Übrigens lässt sich
1
time.second=0;
2
time.minute=newtime.minute;
3
time.hour=newtime.hour;
4
time.wday=newtime.wday;
5
time.day=newtime.day;
6
time.month=newtime.month;
7
time.year=newtime.year;
platzsparender und übersichtlicher (allerdings etwas langsamer)
formulieren als
1
time=newtime;
2
time.second=0;
Macht für die paar Zeilchen immerhin rund 30 Bytes.
Johann
Warum ist der erlaubte Bereich für die Periodenlänge so groß gewählt? In
einer idealen Welt kommt als dcf77_period 64 heraus, oder? Ich kann
einsehen, wenn dies nur mit +/- 1 Ticks gelingt - aber hier sind es
gleich 4-5 Ticks.
Ich habe mal spaßeshalber (XTAL=3686400, T2COUNT=56, T2COUNTSEC=72) mit
1
if(dcf77_period<63||dcf77_period>65)
2
dcf77error=1;
gearbeitet, klappt anscheinend auch und vermittelt mir eine strengere
Fehlerprüfung.
Grüße
schnack
Hi,
> also der Code funktioniert bei 1MHZ super. Aber gibt es irgend einen> Grund, warum er bei 500kHZ oder 250KHz nicht AVR Takt nicht> synchonisieren möchte?
Ich weiß nicht, ob die Frage noch aktuell ist. Meine Deutung für das
Problem ist: Bei sehr kleinen Taktfrequenzen werden die Counter-Werte
für T0COUNT auch sehr klein, bei 250kHz ist T0COUNT 3 mit einem sehr
großen Rundungsfehler (ungerundet nämlich: 3,8). Es läuft dann gegen
Ende einer Sekunde ein großer Fehler auf, der mit T0COUNTSEC von 55
(ungerundet 55,1) korrigiert wird.
Ein normaler Tick hat dann eine Dauer von 3*1024/250000 = 0,0122s.
In
1
voidscan_dcf77(void)
2
{
3
if(dcf77_pulse){
4
if(dcf77_pulse>3&&dcf77_pulse<8){
5
decode_dcf77(0);
6
}else{
7
if(dcf77_pulse>10&&dcf77_pulse<14){
8
decode_dcf77(1);
9
}else{
10
dcf77error=1;
11
}
12
}
13
dcf77_pulse=0;
14
}
15
[..]
werden die ermittelten Pulslängen auf 0/1 abgebildet - zumindest wird
es versucht. Eine '0' bedeutet eine Absenkung des Pegels für 0,1
Sekunden, d.h. ca. 6,4 Ticks (wenn ein Tick exakt 1/64 Sekunde = 0,0156s
dauert).
Wenn ein Tick dagegen 0,0122s dauert, enspricht eine '0' ca. 8,2 Ticks.
Wie man im Code sehen kann, ist die Prüfung damit nicht mehr
erfolgreich.
Der Fangbereich für die '0' und '1' -Erkennung ist also dem Fehler
geschuldet, der für unterschiedliche XTAL-Frequenzen aufläuft.
Grüße
schnack
C. D. schrieb:
> Hi,>> also der Code funktioniert bei 1MHZ super. Aber gibt es irgend einen>> Grund, warum er bei 500kHZ oder 250KHz nicht AVR Takt nicht>> synchonisieren möchte?>> [...] Eine '0' bedeutet eine Absenkung des Pegels für 0,1> Sekunden, d.h. ca. 6,4 Ticks (wenn ein Tick exakt 1/64 Sekunde = 0,0156s> dauert).> Wenn ein Tick dagegen 0,0122s dauert, enspricht eine '0' ca. 8,2 Ticks.> Wie man im Code sehen kann, ist die Prüfung damit nicht mehr> erfolgreich.
Der Empfänger ist eben ausgelegt für 64 DCF-Ticks pro Sekunde. Bei einer
anderen Tick-Anzahl kann man also nicht erwarten, daß er noch
reibungslos funktioniert. Man kann die "magischen Zahlen", die in der
Integritätsprüfung auftauchen, jedoch einfach herausparametrisieren
durch Makro(s), das die Anzahl DCF-Ticks pro Sekunde enthält.
Johann
Hi,
> Der Empfänger ist eben ausgelegt für 64 DCF-Ticks pro Sekunde. Bei einer> anderen Tick-Anzahl kann man also nicht erwarten, daß er noch> reibungslos funktioniert.
ich meine, daß die "Tick-Zahl" sich nicht ändert, also stets bei 64
liegt. Allerdings vergröbert sich die Granularität, mit der das
Interrupt-Handling diese Zeitbasis erzeugen kann, wenn XTAL sinkt - wie
oben beschrieben.
> Man kann die "magischen Zahlen", die in der> Integritätsprüfung auftauchen, jedoch einfach herausparametrisieren> durch Makro(s), das die Anzahl DCF-Ticks pro Sekunde enthält.
Zahl der Ticks für die Pulslängen 0,1s und 0,2s ist wohl gemeint.
So kann man es allgemein machen. Alternativ (man bekommt ein Gefühl für
die Zahlen) kann man einfach mal für "sein" XTAL die Pulslängen in
Tick-Einheiten mit dem Taschenrechner bestimmen.
Noch Gedanke dazu:
Wegen des Rundungsfehlers gibt es für XTAL=250kHz noch ein anderes
Problem.
Es gibt 63 Ticks der Länge 0,012288. Danach folgt ein "Monster-Tick" der
Länge 55*1024/250000 = 0,225s, damit 64 Ticks wieder eine Sekunde sind..
Probe: 63*0,01288s + 1*0,2253s = (fast 1 Sekunde ).
Wenn man ein wenig Pech hat, wird man nun nie synchronisieren können,
selbst, wenn man die Pulslängen angepaßt hat. Denn während des
Monster-Ticks ist der Empfänger blind für Flankenänderungen. Und da
dieser länger dauert als 0,2 Sekunden (maximale Pulslänge ist ja gerade
0,2s für die '1'), ist XTAL=250kHz nicht wirklich angeraten, oder...:
T0COUNT wird nicht mehr fest gewählt, sondern über einen Tick-Index
parametrisiert. Dann wird der Rundungsfehler zumindest verkleinert, hat
aber auch Auswirkungen auf die übrigen Konstanten..
Fazit: Wer sich in XTAL-Grenzbereiche vorwagt, muß sich den Code genau
anschauen und ggf. Änderungen durchführen.
Grüße
schnack
C. D. schrieb:
> Noch Gedanke dazu:> Wegen des Rundungsfehlers gibt es für XTAL=250kHz noch ein anderes> Problem.
Man kann doch problemlos eine andere Tick-Anzahl implementieren, zB 100
Ticks/Sekunde. Der Algorithmus ändert sich dadurch nicht (bis auf das &
0x3f an einer Stelle, was man minimalinvasiv ändern kann, und die paar
magischen Zahlen).
Es ist immer eine gute Idee, eine solche IRQ-Rate zu wählen, die keine
Moiré-Effekte irgendwo erzeugt.
Johann
Gast schrieb:
> Müsste es nicht (newtime.second < 59) sein, da sonst der Wert 60> zustandekommen könnte, und dann nie synchronize gesetzt wird?
Ne, 60 muß möglich sein, um Störimpulse zu erkennen.
Es ist eigentlich unnötig, da eine Anzahl von 256 + 59 Störimpulsen
nicht möglich ist, ohne die Pulslängen- und Abstandstests zu
überschreiten.
> Warum wird immer auf unsigned int gecastet? Ist doch nur ein 8 bit> Timer.
Dann gibt es ne Warnung, wenn 8Bit nicht mehr ausreicht.
Peter
Hallo Peter,
ich würde gern deine DCF77 Code in mein Projekt einbinden. Leider
bekomme ich eine Fehlermeldung:
../main.h:4:19: error: types.h: No such file or directory
Ich schaffe es einfach nicht diese "types.h" mit einzubinden. Damit
fehlen mir die Ausführungen zu LPM etc....
Ich benutze das AVRStudio mit dem GCC Compiler. Was könnte ich nur
machen?
Außerdem erkennt er u8 nicht. Aber ich denke das ersetzen von u8 mit
uint8_t dürfte das Problem lösen.
bitte um Hilfe!
mfg haribo
Hallo Peter,
hätte eine Frage zu deinem Code:
habe das ganze am laufen und es funktioniert einwandfrei. Nun möchte ich
aber nicht nur Zeit und Datum auslesen sondern auch ob gerade Sommerzeit
oder Winterzeit ist. Das müsste in Sekunde 37 übertragen werden soviel
ich weiß. Wo bzw wie muss ich an deinem code ansetzen um diese Info zu
bekommen?? würde sie gern abspeichern.... da dein Code beim decoden des
Signals sehr komplex ist steige ich nicht wirklich dahinter wie ich das
vernünftig lösen könnte. Bitte um Hife :(
hallo,
woran könnte es blos liegen dass bei mir mit Peters Uhr desöfteren mal
eine Sekunde verloren geht?!?! :(
Gibt man die Sekunden fortlaufend auf einem Display aus so passiert es
von Zeit zu Zeit dass die Sekundenzahl nicht inkrementiert wird.
Scheinbar kommt das timeflag ONE_SECOND nicht. Außerdem kommt das
timeflag ONE_MINUTE in der main Schleife auch nicht immer.
Habe das Ganze mit eine 4MHz Quarz nachgebaut.
mfG
Tom schrieb:> Mmmh. Der Code ist ja so gut kommentiert, wie die Opensolaris> Kernelquellen...
Peters Code ist sicher alles andere, als gut dokumentiert, gut
strukturiert oder für jemand der GNU-Code gewohnt ist, gut
lesbar....aber eines muss man ihm lassen:
Seine Methoden sind hocheffizient und platzsparend...
Das hier ist nicht der erste Code-Schnipsel von Peter, den ich verwende;
und jedesmal musste ich den Code erstmal komplett aufräumen.
Aber, Peter dafür zu kritisieren, find ich unangemessen.
Der Umfang seiner hier veröffentlichen Projekte sollte es jedem, der ein
wenig Erfahrung mit C hat erlauben, sich da reinzudenken. Wem das nicht
gelingt, der sollte sich erstmal mit C-Grundlagen beschäftigen!
Es geht mit C noch sehr viel schlimmer! (20KB langer "Einzeiler")
Harry
Harald L. schrieb:> Das hier ist nicht der erste Code-Schnipsel von Peter, den ich verwende;> und jedesmal musste ich den Code erstmal komplett aufräumen.
Kannst Du bitte mal so ein aufgeräumtes Codebeispiel zum Vergleich
posten?
Peter
Hallo Peter,
ich bin gestern auf deine DCF77uhr gestossen, und hab die für meine
Zwecke angepasst.
LED-Ausgabe o.Ä. brauch ich in meinem Projekt nicht.
Was ich im wesentlichen gemacht habe:
* Dateinamen die nur aus Großbuchstaben bestehen sind unter Linux ein
absolutes NoGo. Daher werden zunächst alle Dateien in Namen mit
Kleinbuchstaben umbenannt.
* Du definierst in deiner types.h eigene Typen für die gängigen
Integers. In den Atmel Headern findet sich aber bereits uint8_t, int8_t
usw. Um den Code auch nach längerer Zeit lesbar und verständlich zu
halten, hab ich alle Var-Definitionen auf die Atmel-Typen umgestellt.
* alle wichtigen Includes in eine Header-Datei zu schreiben, spart zwar
ein wenig Tipperei, aber macht den Code nicht gerade übersichtlicher.
* das Thema "Code-Formatierung" sprech ich jetzt mal gar nicht an. Das
macht Eclipse für mich auf Knopfdruck ;)
In dem ZIP-File ist kein Makefile, da ich mit Eclipse arbeite. In dem
ZIP-File ist der vollständige Inhalt meines Projektordner nach dem "make
clean".
Ich hoffe, daß du deinen Code noch wiedererkennst. ;)
Selbstverständlich hab ich alle Hinweise auf den Autor im Code belassen.
Harry
Eins hab ich noch vergessen:
Alle Includes sollten durch entsprechende #define- und
#ifdef-Kombinationen vor mehrfachem Einbinden geschützt werde. Als Code
sieht das dann so aus:
Harald L. schrieb:> Ich hoffe, daß du deinen Code noch wiedererkennst. ;)
Ich heisse zwar nicht Peter, aber das Zip-Archiv ist irgendwie kaputt,
denn ich konnte da zunächst gar nix erkennen ;-)
- filzip unter Windows zeigt nur leere Ordner
- unzip-Kommando-Version unter Windows zeigt zwar Dateien, die kann
man aber nicht auspacken, da die Dateien im zip-Archiv mit absoluten
Pfaden gespeichert sind.
- 7zip unter Windows kann es unter Anzeige eine unleserlichen
Hauptordners.
- unzip-Komando-Version unter Linux entpackt dann die Dateien - unter
Angabe von:
warning: stripped absolute path spec from dcf77.cproject
.... (usw).
Wer beim Programmieren auf Portabilität/Lesbarkeit achtet, sollte auch
beim Erstellen eines Zip-Archivs eine gewisse Sorgfalt an den Tag legen
;-)
Gruß,
Frank
Frank M. schrieb:> Wer beim Programmieren auf Portabilität/Lesbarkeit achtet, sollte auch> beim Erstellen eines Zip-Archivs eine gewisse Sorgfalt an den Tag legen> ;-)
Sorry, ich versteh dein Problem nicht. Bei mir geht das problemlos.
Ich hab allerdings auch keine Möglichkeit das unter WinDoof zu testen.
Harry
Harald L. schrieb:> Sorry, ich versteh dein Problem nicht. Bei mir geht das problemlos.
Dann packe die zip-Datei unter Linux wieder aus und versuche, die dabei
ausgedruckten Warnings zu verstehen.
> Ich hab allerdings auch keine Möglichkeit das unter WinDoof zu testen.
Das hat überhaupt nichts mit "WinDoof" zu tun.
Das Erstellen von tar- oder zip-Archiven mit absoluten Pfaden darin(!)
ist ein absolutes NoGo und gilt als nicht sehr "höflich". Damit haben
sich schon oft Admins in der Vergangenheit unter Unix/Linux/Windows
wichtige Systemdateien überschrieben. Deshalb wurde dann auch schon vor
vielen Jahren beim GNU-Tar und auch unzip unter Unix/Linux das Strippen
von führenden Slashes eingebaut - abweichend vom System-V-tar, welcher
auch heutzutage noch unter bestimmten Unix-Derivaten Dateien mit
absoluten Pfaden gnadenlos überschreibt.
Gruß,
Frank
Frank M. schrieb:> Deshalb wurde dann auch schon vor> vielen Jahren beim GNU-Tar und auch unzip unter Unix/Linux das Strippen> von führenden Slashes eingebaut - abweichend vom System-V-tar, welcher> auch heutzutage noch unter bestimmten Unix-Derivaten Dateien mit> absoluten Pfaden gnadenlos überschreibt.>> Gruß,>> Frank
Stimmt!....ich hatte es mir bequem gemacht, und Eclipse das Archiv
erzeugen lassen. Daß der "führende Slashes" einbaut, war mir -ehrlich
gesagt- gar nicht bewusst.
Stellt aber heute auch nirgendwo mehr ein Problem dar(s.o.). Die
einzigen Warnungen, die beim manuellen Entpacken auftauchen beziehen
sich eben auf das Entfernen dieses Slash am Anfang.
Harry
Harald L. schrieb:> Was ich im wesentlichen gemacht habe:
so habs mal bei mir eingebaut, nun meckert ASTUDIO
../__dcf77.h:20: warning: useless storage class specifier in empty
declaration
extern struct time;
extern struct newtime;
verstehe es gerade nicht
muss ich typedef oder das struckt an dieser Stelle nochmal erklären ?
irgendwie weiss das Proggi ja nicht wie struct aussieht an dieser Stelle
da es an anderer Stelle bekannt gemacht wurde....
gruss
jar
Hallo DCF77 Profis!
Ich habe mit großem Interesse Eure Postings gelesen und so gut wie
nichts verstanden.
Hier meine Bitte / Frage.
Kann mir jemand gegen Bezahlung eine Uhr mit LEDs oder LCDs bauen, die
eigentlich nur den Wochentag (MONTAG...) anzeigen soll, aber das mit
einer Größe von 30 bis 50mm. Um ein Gehäuse würde ich mich kümmern.
Hintergrund ist der, dass meien Mutter (89) sich mit den Wochentagen
schwer tut, und auch nicht mehr gut sehen kann.
Leider gibt es im Netz nicht vernünftiges, es sei denn man gibt 400€ bis
600€ aus. :-(
Über eine Antwort würde ich mich freuen!
Ernst
Harald L. schrieb:> Hallo Peter,> ich bin gestern auf deine DCF77uhr gestossen, und hab die für meine> Zwecke angepasst.> LED-Ausgabe o.Ä. brauch ich in meinem Projekt nicht.
Super, es hat nach kürzester Zeit geklappt mit einem Funkmodul von
Pollin und Atmega 128.
Ich habe mich schon seit Wochen mit dem Funkmodul rumgeärgert!
1min 40sec bis zum Empfang (auf dem Schreibtisch mit Monitoren und
ungeschirmtem Zeug drumherum).
Hier noch ein paar Bilder vom Aufbau.
Basis ist ein eHaJo atmega32u4 Board mit LUFA CDC Bootloader, ein
martübliches LCD JHD162A und ein DCF77 Empfangsmodul.
Das DCF77 Empfangsmodul erhält über eine Diode (BAT43) und ein CRC Glied
seine Versorgungsspannung von ~5V, da ich die 5V gerade über den USB Bus
beziehe.
C1,C2 = 10µF
R = 100Ω
Eine Variante in C++
************************************************************************
*****
basierend auf Code von Peter Dannegger als Beispiel und zum direkten
Vergleich.
Ich hoffe, mein Zip-File funktioniert..
@Moby
************************************************************************
*****
ich kann ASM und lese und benutze mit Interesse die Beiträge von
Bernhard S. Beitrag "DCF77 Simulator Generator Encoder Atmega8 Assembler"
ich wollte mal eine Rückmeldung geben.
Ich nutze ja nun auch gerne den Code am Arduino weil er so schön knapp
ist mit allen Prüfungen.
Meine Impulse sind aber etwas verkürzt also habe ich die 1 0 Schwellen
anpassen müssen, dabei stellte sich heraus das heute 2014 erkannt wurde
trotz Paritätsprüfung....
Wenn der Code NUR Parität und Plausibilität prüft, wirst Du da immer
nach 5min bis 5h, bei heftigeren Störungen, irgendeinen plausiblen
Blödsinn sehen.
Ich habe mich gestern mit dem Code beschaeftigt und bin darauf
gestossen, dass der Verlust des Signals nicht zum Loeschen von
synchronize fuehrt.
In der timebase.c muss die Behandlung des Signalverlustes ergaenzt
werden, aus:
1
SIGNAL (SIG_OVERFLOW0)
2
{
3
static u8 dcf77_time, old_dcf77;
4
// DCF77 receive
5
if( dcf77_time != 0xFF ) // stop on 0xFF
6
dcf77_time++; // count ticks
muss werden:
1
SIGNAL (TIMER0_OVF_vect)
2
{
3
static uint8_t dcf77_time, old_dcf77;
4
// DCF77 receive
5
if( dcf77_time != 0xFF ){ // stop on 0xFF
6
dcf77_time++; // count ticks
7
}else{
8
dcf77_period = dcf77_time; // for error processing in dcf77.c
9
};
Damit wird dann in dcf77.c in der Zweig fuer die Fehlerbehandlung (ab
Zeile 95) erst wirksam.
wendelsberg