Forum: Projekte & Code DCF77 Uhr in C mit ATtiny26


von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

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

: Bearbeitet durch Moderator
von Lupin (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Armin K. (-donald-) Benutzerseite


Lesenswert?

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.

von Helmut (Gast)


Lesenswert?

> 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.

von Peter D. (peda)


Lesenswert?

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

von Propper (Gast)


Lesenswert?

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!

von Peter D. (peda)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

Hallo peda

kann ich mal die Schaltung sehen? In der wo der MAX.. den Empfang 
stört..
Danke

von swesch (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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


von Peter D. (peda)


Lesenswert?

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

von swesch (Gast)


Lesenswert?

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


von Peter D. (peda)


Lesenswert?

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

von swesch (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von swesch (Gast)


Lesenswert?

Ich werde mein Glück noch mal alleine versuchen.

Gleich aufgeben will ich ja auch nicht.

Ich benutze den "neueren" DCF-Empfänger vom grossen C.

http://www.conrad.de/goto.php?artikel=641138
http://www2.produktinfo.conrad.com/datenblaetter/625000-649999/641138-sp-02-de-DCF-Empfaengerplatine.pdf

Kann es da evtl. Unterschiede vom Timing her zwischen den verschiedenen 
Modulen geben? ( C-alt, C-neu, Reichelt etc)

Falls ich den Fehler so nicht find dann stell ich den geänderten Code 
hier mal rein.

Stefan

von swesch (Gast)


Angehängte Dateien:

Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von swesch (Gast)


Lesenswert?

Aha.

Wenn ich das scan_dcf77 in den Interrupt verschiebe dann stimmt die 
Anzeige.

Ich versteh nur nicht warum...

Stefan

von Peter D. (peda)


Lesenswert?

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

von sven s. (Gast)


Lesenswert?

man sind die MAX7219 MAX7221 teuer .,
für das geld könnte man sich auch ein schönes lcd kaufen ...

von horst (Gast)


Lesenswert?

Hallo,

in der Routine clock() muesste doch eigentlich
stehen:
        if( LPM(MDAYS + i ) == time.day )
gruss
      horst.



void clock(void)
{
  u8 i;
  ................
  switch( time.hour ){
  case 24:
    time.hour = 0;
    time.day++;
    time.wday++;
    if( time.wday == 8 )
      time.wday = 1;
    i = time.month;
    if( i == 2 && (time.year & 3) == 0 )  // leap year
      i = 0;
    if( LPM(MDAYS+1) == time.day )
            {
               time.day = 1;
               ...............

von Peter D. (peda)


Lesenswert?

horst wrote:

> in der Routine clock() muesste doch eigentlich
> stehen:
>         if( LPM(MDAYS + i ) == time.day )


Stimmt.

Peter

von neo_87 (Gast)


Lesenswert?

kriegt man das mit C auch in einen tiny2313 (2k flash)? habe damit 
gerade ein lcd am laufen, aber das braucht irgendwie schon 725 byte!

von neo_87 (Gast)


Lesenswert?

ich ziehe die frage zurück, der 26 hat ja auch gerade mal 2k flash.

von neo_87 (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von neo_87 (Gast)


Lesenswert?

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!

von neo_87 (Gast)


Lesenswert?

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!

von Frank N. (betafrank)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

@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

von Frank N. (betafrank)


Lesenswert?

Hallo Peter,

momentan ist ein 10MHz-Quarz drin. Die Konstanten im Vergleich:
1
        // at 12MHz,  at 10MHz:
2
#define T0COUNT    (F_CPU / 1024 / 64)                    //183, 152
3
#define T0SECERR   (F_CPU - 1024L * 64 * T0COUNT)    //6912, 38528
4
#define T0COUNTSEC (T0COUNT + T0SECERR / 1024)            //189, 189
5
#define T0MINERR   (F_CPU - 1024 * (63 * T0COUNT + T0COUNTSEC)) //768, 640
6
#define T0COUNTMIN (T0COUNTSEC + (T0MINERR * 60 + 512) / 1024) //234, 227

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

von Frank N. (betafrank)


Lesenswert?

Nachtrag

Conrad-DCF-Empfängerplatine Best.Nr.641138 an langer Leine (Empfang am 
Fenster) macht 6..7 bzw. 12..13 Überläufe.

von Sebastian (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Sebastian (Gast)


Lesenswert?

Hey Peter,

Danke für deine Antwort. So wird das alles viel klarer.

Ich melde mich wieder wenn ich noch ein paar Fragen habe

MfG
Sebi

von Sebastian (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

@Sebastian,

Du hast recht. Da ist was schiefgelaufen beim Umschreiben von Keil C51 
auf WINAVR. Richtig muß es so lauten:
1
if( LPM(MDAYS+i) < time.day ){


Peter

von Sebastian (Gast)


Angehängte Dateien:

Lesenswert?

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

von Hauke R. (lafkaschar) Benutzerseite


Lesenswert?

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?

von Sebastian (Gast)


Lesenswert?

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.....

von Hauke R. (lafkaschar) Benutzerseite


Lesenswert?

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.

von Robert S. (razer) Benutzerseite


Lesenswert?

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

von Hauke R. (lafkaschar) Benutzerseite


Lesenswert?

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.

von ich (Gast)


Lesenswert?

läuft der interrupt mit 64hz oder mit 1hz?

von Peter D. (peda)


Lesenswert?

ich wrote:
> läuft der interrupt mit 64hz oder mit 1hz?

64Hz

Peter

von ich (Gast)


Lesenswert?

danke, dann läuft bei mir was falsch. heute abend mal gucken. irgendwas 
braucht zu lange.

von Ingo L. (grobian)


Lesenswert?

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??

von Malte _. (malte) Benutzerseite


Lesenswert?

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.

von Malte _. (malte) Benutzerseite


Lesenswert?

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.

von Malte _. (malte) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

von Günter D. (fluxxy)


Lesenswert?

Hallo Peter,

Kann man den Code auch zum Auslesen des Sommerzeit-Bit erweitern?
Das müsste das 17 Bit sein.

Günter

von kaffeetas (Gast)


Lesenswert?

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

von Günter D. (fluxxy)


Lesenswert?

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

von U. E. (Gast)


Lesenswert?

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
void scan_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

von Peter D. (peda)


Lesenswert?

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

von U. E. (Gast)


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und in click.c lassen sich auch nochmal 30 Byte sparen.

Ausserdem muss es doch heissen
1
if( LPM(MDAYS+1+i) == time.day ){

anstsatt
1
if( LPM(MDAYS+1) == time.day ){

Oder?

von U. E. (Gast)


Lesenswert?

Hi,
eine Frage habe ich nun doch noch:
1
void scan_dcf77( void )
2
{
3
[..]
4
      if( dcf77_period < 60 || dcf77_period > 70 )
5
        dcf77error = 1;

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

von U. E. (Gast)


Lesenswert?

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
void scan_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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

von U. E. (Gast)


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Guten Abend,
ich möchte auch mal zwei Fragen stellen:
aus DCF77.C:77:
1
  if( dcf77_period ){
2
    if( newtime.second < 60 )
3
      newtime.second++;
4
    if( dcf77_period > 120 && dcf77_period < 140 ){
5
      if( dcf77error == 0 && newtime.second == 59 ){
6
        synchronize = 0xFF;
Müsste es nicht (newtime.second < 59) sein, da sonst der Wert 60 
zustandekommen könnte, und dann nie synchronize gesetzt wird?

in TIMEBASE.C:44:
1
  TCNT0 = (u16)(256 - T0COUNT);      // reload per tick: -183
2
  if( ++ct_64Hz & 0x3F ){      // 64 ticks = one second
3
    timeflags = 1<<ONE_TICK;      // one tick over
4
    return;
5
  }
6
  TCNT0 = (u16)(256 - T0COUNTSEC);    // reload per second: -189
7
  if( timeflags & (1<< ONE_MINUTE ))
8
    TCNT0 = (u16)(256 - T0COUNTMIN);    // reload per minute: -234
Warum wird immer auf unsigned int gecastet? Ist doch nur ein 8 bit 
Timer.

von Peter D. (peda)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Danke für die Erläuterung!

von haribo (Gast)


Lesenswert?

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

von haribo (Gast)


Lesenswert?

also ich hab jetzt eine types.h runtergeladen und einfach 
reinkopiert..ich hoff es ist die richtige... :-/

von haribo (Gast)


Lesenswert?

Scheinbar ja....die Uhr läuft bereits ;)

von haribo (Gast)


Lesenswert?

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 :(

von haribo (Gast)


Lesenswert?

hmmm...bin leider immer noch nicht weiter...weiß sonst jm wer wie das 
gehn könnt?? :)

von Peter D. (peda)


Lesenswert?

Ne, das ist Bit 17:
1
u8 new_mesz;
2
3
void decode_dcf77( u8 pulse )
4
{
5
  static u8 parity = 0;
6
  u8 i;
7
  u8 *d;
8
//----------------------- MESZ 
9
  if( newtime.second == 17 )
10
    new_mesz = pulse;
11
//----------------------------
12
  i = newtime.second - 21;
13
  if( i >= sizeof( BITNO ))      // only bit 21 ... 58
14
    return;
15
  parity ^= pulse;        // calculate parity
16
  i = LPM(&BITNO[i]);
17
  if( i == 0xFF ){        // test parity
18
    if( parity )
19
      dcf77error = 1;
20
    parity = 0;
21
    return;
22
  }
23
  d = (u8 *)&newtime.minute + (i >> 4);    // byte address
24
  i &= 0x0F;          // bit number
25
  if( i == 0 )
26
    *d = 0;          // clear all, if lsb
27
  if( pulse )
28
    *d += LPM(&BMASK[i]);      // set bit
29
}


Und dann eben noch bei der Zeitübernahme das new_mesz übernehmen, wenn 
das Paket gültig war.


Peter

von haribo (Gast)


Lesenswert?

aha! Jetzt glaube ich hab ich den Code auch kapiert. DANKE PETER!!!!

von haribo (Gast)


Lesenswert?

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

von haribo (Gast)


Lesenswert?

Problem gelöst...

von Ivica S. (ivisaf)


Lesenswert?

Hallo Peter,

danke für das tolle Programm.

Das DCF-Modul ist sehr robust. Tolle Programmiertechnik.

MfG.

von Tom (Gast)


Lesenswert?

Mmmh. Der Code ist ja so gut kommentiert, wie die Opensolaris 
Kernelquellen...

von Harry L. (mysth)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

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

von Harry L. (mysth)


Lesenswert?

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:
1
/*
2
 * myinclude.h
3
 *
4
 *  Created on: 25.06.2010
5
 *      Author: harry
6
 */
7
8
#ifndef MYINCLUDE_H_
9
#define MYINCLUDE_H_
10
11
// hier kommt der Inhalt rein!
12
13
#endif /* MYINCLUDE_H_ */

Harry

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

Also ich kann alles lesen.
Ich benutzte WINRAR, da ist alles paletti.


Peter

von Harry L. (mysth)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Harry L. (mysth)


Lesenswert?

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

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Das sollte gehen (mit WINRAR entpackt und wieder gepackt).


Peter

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Das sollte gehen (mit WINRAR entpackt und wieder gepackt).

Danke, geht.

Gruß,

Frank

von Hannes (Gast)


Lesenswert?

Hi,

bastel gerade mit dem Code:

Beitrag "Re: DCF77 Uhr in C mit ATtiny26"

rum und habe eine Frage zum Timertiming:

Beitrag "Re: DCF77 Vorgehensweise"

Bitte um Rückmeldung.

H.

von Joachim B. (Gast)


Lesenswert?

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

von Ernst Jordy (Gast)


Lesenswert?

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

von Horst H. (horha)


Lesenswert?

Hallo,

wie wäre es mit etwas fertigem?
http://www.sehhelfer.de/Mit-Sprachausgabe/Wecker/Sprechender-Funk-Wecker-Time.html 
oder
http://www.techno-hilfe.de/Sprechender-Funk-Wecker-Time

Das scheint aber etwas kleine Tasten zu haben.Das Gerät kann man sicher 
zurückschicken, wenn es nicht klappt.

Mein Vater ( 91 ) ist mit Uhrzeit und Temperaturaansage von einem 
anderem Gerät sehr gut zufrieden.Zum Glück behält er noch, welchen Knopf 
er drücken muss.

von Armin K. (-donald-) Benutzerseite


Lesenswert?

Peter,
wo wird die decodierte DCF77-Zeit in die Variable newtime geschrieben?
Ich hab das noch nicht verstanden.

von Peter D. (peda)


Lesenswert?

Armin K. schrieb:
> wo wird die decodierte DCF77-Zeit in die Variable newtime geschrieben?

In dcf77.c:
1
  d = (u8 *)&newtime.minute + (i >> 4);    // byte address
2
  i &= 0x0F;          // bit number
3
  if( i == 0 )
4
    *d = 0;          // clear all, if lsb
5
  if( pulse )
6
    *d += LPM(&BMASK[i]);      // set bit


Peter

von Anton A. (bingo_)


Lesenswert?

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).

von lovem4ker (Gast)


Lesenswert?

Peter Dannegger ICH WILL EIN KIND VON DIR !!! ;-)

sau geiler code genial ^^

mfg

von Uwe S. (de0508)


Angehängte Dateien:

Lesenswert?

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Ω

: Bearbeitet durch User
von MitLeserin (Gast)


Angehängte Dateien:

Lesenswert?

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"

von Joachim B. (jar)


Lesenswert?

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....

von Teo D. (teoderix)


Lesenswert?

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.

: Bearbeitet durch User
von wendelsberg (Gast)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.