Forum: Mikrocontroller und Digitale Elektronik ist meine software Uhr sauber programmiert?


von fldrms (Gast)


Angehängte Dateien:

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.

: Verschoben durch User
von Thomas F. (igel)


Lesenswert?

if (seconds == 59) //60 seconds
        {
          seconds=0;
          minutes++;
        }

Warum hat die Minute bei dir nur 59 Sekunden?

von Ro N (Gast)


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

von Thordy (Gast)


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

von Peter II (Gast)


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.

von Thordy (Gast)


Lesenswert?

Thordy schrieb:

> Ansonsten würde ich versuchen die LCD Routine nicht ständig
> aufzurufen(raus aus der while).

Sorry hab nicht richtig hingeguckt. Du rufst die garnicht ständig 
auf....

von egberto (Gast)


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

von Philipp K. (philipp_k59)


Lesenswert?

Schonmal die Frequenz vom Quarz gemessen?

Für 1 Sekunde in 20 Minuten müsste der Quarz 20.016.666Hz Takten oder 
deine Zähler sich um 16.666/256=0,065 Takte die Sekunde verzählen..

Das macht dann knapp 78 Takte in 20 Minuten.

: Bearbeitet durch User
von fldrms (Gast)


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.

von fldrms (Gast)


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.

von fldrms (Gast)


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

von Philipp K. (philipp_k59)


Lesenswert?

Andere Idee bevor hier alles den Code auseinandernimmt..

Zähle die Sekunden in einer Extra Variable komplett hoch und Vergleich 
das mit deinen Minuten*60+Sekunden.

: Bearbeitet durch User
von fldrms (Gast)


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.

von Philipp K. (philipp_k59)


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.

: Bearbeitet durch User
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.