ist meine software Uhr sauber programmiert?

Gast #4694080
Lesenswert?

Moin,

ich habe eine Uhr ohne ISR geschrieben die leider alle ~20min eine gute 
Sekunde vorgeht.

Ich benutze einen Atmega328P mit einem externen 20Mhz Quarz an xtal. Die 
Fuses sind dementsprechend gesetzt von daher gehe ich "erstmal" davon 
aus das damit nichts verkehrt ist.

Kann mir jemand sagen ob meine Zählvariablen denn vom Grundsatz stimmen 
(mal angenommen das das Quarz exakt mit 20Mhz schwingt). Ich vermute 
nämlich eher das meine Zählvariablen fehlerhaft sind.

Was habe ich programmiert:
Der Takt von 20Mhz wird durch den Prescaler von 256 des Timer0 auf genau 
78125 runtergebrochen. Würde ich den Zähler TCNT0 bei 125 wieder 
zurücksetzen könnte ich eine Hilsvariable bis 625 zählen lassen und 
hätte zumindest in der Theorie einen genauen Takt von 1sek. Leider nur 
in der Theorie :(

Danke an alle Antwortenden!

gruß f.
Angehängte Dateien:
Gast #4694102
Lesenswert?

Ich gehe schwer davon aus, dass wenn deine Routine, die Werte 
auszuschreiben ausgeführt wird, TCNT0 schon wieder über 124 ist. D.h. du 
verpasst da einen, vielleicht sogar mehrere Überlaufe. Prüfe auf >=.
Ich würde im Interrupt timer0_counter hochzählen, ein Flag setzen und in 
der Hauptschleife prüfen ...
Selbst wenn der Oszi nicht so genau ist (Temperatur, Drift, ...) ist 1s 
pro 20min definitiv zu viel ....
Gast #4694134
Lesenswert?

Thomas F. schrieb:
> if (seconds == 59) //60 seconds
>         {
>           seconds=0;
>           minutes++;
>         }
>
> Warum hat die Minute bei dir nur 59 Sekunden?

Ich glaube auch das du hier eine 60 statt der 59 eintragen musst. Du 
setzt die 59 nämlich wieder direkt auf 0 obwohl die Sekunde noch nicht 
abgelaufgen ist.

Ansonsten würde ich versuchen die LCD Routine nicht ständig 
aufzurufen(raus aus der while).
Gast #4694141
Lesenswert?

Ro N schrieb:
> Ich gehe schwer davon aus, dass wenn deine Routine, die Werte
> auszuschreiben ausgeführt wird, TCNT0 schon wieder über 124 ist. D.h. du
> verpasst da einen, vielleicht sogar mehrere Überlaufe.

nicht bei einen Vorteiler von 256.

Es wird ja in einer minischleife nur dieser wert verglichen. Das kann 
nicht das Problem sein.

Wenn das Programm irgendwann mal mehr machen musst, wird es zu einem 
Problem.
Gast #4694163
Lesenswert?

Und warum nimmst du keine ISR?
Das hätte den Vorteil, das du das ganze zeitkritische bzw. 
Counter/Vergleichs Zeugs vom Hauptprogramm getrennt hättest und dich in 
der weiteren Programmierung nicht mehr darum kümmern müsstest.

Grüße,

egberto
Gast #4694192
Lesenswert?

Moin & Danke für Eure Antworten!

Ich denke auch das im Gleichsetzen meiner Variablen der Hund begraben 
liegt.
Bei TCNT0 == 124 & timer0_counter == 624 & seconds == 59 geht mir 
jeweils ein "count" verloren.

Für eine genaue Sekunde benötige ich bei einem prescale von 256 und 
20Mhz
- 125 "Ticks" bei TCNT0 müssen lauten TCNT0 <= 125
- 625 "Ticks" bei timer0_counter müssen lauten timer0_counter <= 625
- 60 "Ticks" für eine Sekunde müssen lauten seconds <= 60

Alles natürlich unter der Annahme das der Quarz sauber tickt.

mfg f.
Gast #4694197
Lesenswert?

egberto schrieb:
> Und warum nimmst du keine ISR?
> Das hätte den Vorteil, das du das ganze zeitkritische bzw.
> Counter/Vergleichs Zeugs vom Hauptprogramm getrennt hättest und dich in
> der weiteren Programmierung nicht mehr darum kümmern müsstest.
>
> Grüße,
>
> egberto

Moin,

das wird der nächste Schritt werden. Ich wollte nur erstmal gegengeprüft 
bekommen ob denn überhaupt der Grundgedanke per Softwarelösung stimmt. 
War mir doch recht uneinig wegen den Variablen. Sprich ==124 oder <=125 
etc.
Gast #4694203
Lesenswert?

fldrms schrieb:
> - 125 "Ticks" bei TCNT0 müssen lauten TCNT0 <= 125
> - 625 "Ticks" bei timer0_counter müssen lauten timer0_counter <= 625
> - 60 "Ticks" für eine Sekunde müssen lauten seconds <= 60

- 60 "Ticks" (Sekunden) für eine Minute müssen lauten seconds <= 60
Gast #4694213
Lesenswert?

fldrms schrieb:
> fldrms schrieb:
>> - 125 "Ticks" bei TCNT0 müssen lauten TCNT0 <= 125
>> - 625 "Ticks" bei timer0_counter müssen lauten timer0_counter <= 625
> - 60 "Ticks" (Sekunden) für eine Minute müssen lauten seconds <= 60

So jetzt hab ich mich selbst verhaspelt...

hoffentlich richtig ist:
>> - 125 "Ticks" bei TCNT0 müssen lauten TCNT0 == 125
>> - 625 "Ticks" bei timer0_counter müssen lauten timer0_counter == 625
> - 60 "Ticks" (Sekunden) für eine Minute müssen lauten seconds == 60

Sonst würden die Schleifen ja für jeden Wert kleiner einmal durchlaufen 
werden. Damit würde eine Sekunde definitiv nicht mehr stimmen.
#4694245
Lesenswert?

fldrms schrieb:
> Alles natürlich unter der Annahme das der Quarz sauber tickt.

Angenommen während Du schon so schön alles auseinander klamüserst..

Der Quarz tickt nicht Sauber.. Das kann eben mal je nach Temperatur in 
den letzten 3-4 Stellen variieren. Das sind eben mal 1,5 Takte hinter 
dem Divider die Du ja schon genau zählen möchtest.

Bedeutet bei 30ppm Standard Toleranz und 20ppm Abweichung eben mal 
960.0000 Ticks in 20 Minuten.. immerhin genau eine 20/Sekunde.. Dann 
würdest Du dich spätestens in 20 Stunden wieder Fragen woher die Sekunde 
kommt.

Das Problem ist, die Quarze sind Super um Signale in einer Sekunde zu 
messen..

z.B 1uS sind ca 20 Takte.. ob da nun wegen der Grundtoleranzen/PPM 2 
mehr oder weniger rausspringen ist egal, für eine Uhr addiert sich 
dieser Fehler spätestens nach einem Tag oder 1Stunde und 3 
Temepraturschwankungen hoch.

EDIT: Übrigens ein Keramikresonator hat auch mal 10%-20%Toleranz.. das 
heisst der Tikt eben auch mal nur 19,5Mhz und ist in vielen Arduinos 
verbaut.. merkt auch keiner wenn er nicht Sekunden zählen will.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren