Forum: Mikrocontroller und Digitale Elektronik Wie genau solte eine Schachuhr sein


von Sam (Gast)


Lesenswert?

Hallo zusammen

Ich baue zurzeit eine digitale Schachuhr frage mich jetzt wie genau 
diese sein sollte, bzw. wie genau sollte eine Sekunde sein oder anders 
ausgedrückt, wie viel Sekunden darf sie nach x Stunden falschgehen.
Ich weiß genau nicht wie genau DGT oder die anderen dig. Uhren sind. Ich 
möchte aber mit ähnlicher Genauigkeit haben. Ich hab ein bisschen mit 
meinem 8Mhz Quarz rumexperimentiert und habe jetzt die Frequenz als 
Richtwert auf 7998976 Hz gestellt (kann man durch 256 teilen: 31246). 
Bisher läuft die Testuhr 40 Minuten und geht ein Bruchteil einer Sekunde 
vor.

Was meint ihr, wie genau sollte so eine Uhr sein?

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:

> Was meint ihr, wie genau sollte so eine Uhr sein?

Da es mit handelsüblichen Quarzen kein Problem darstellt eine Uhr zu 
bauen, die auch nach Tagen nicht signifikant mehr als 1 Sekunde 
abweicht, stellt sich doch dieses Problem nicht wirklich.

von Korax K. (korax)


Lesenswert?

Hallo Sam,

Da die Zeit für beide Spieler gleich lang ist und beim Turnier nicht 
länger als 0,5 bis 1h gespielt wird, ist es müssig über 
Sekundenbruchteile zu verhandeln. Quartz-Genauigkeit ist absolut 
ausreichend.

Viele Grüße, korax

von Mark B. (markbrandis)


Lesenswert?

Fra Nk schrieb:
> Hallo Sam,
>
> Da die Zeit für beide Spieler gleich lang ist und beim Turnier nicht
> länger als 0,5 bis 1h gespielt wird

Huch, seit wann das? Ich kenn das noch als "Zwei Stunden für 40 Züge"...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Was meint ihr, wie genau sollte so eine Uhr sein?
So genau, dass es keinem auffällt, dass sie ungenau geht... ;-)

> Ich hab ein bisschen mit meinem 8Mhz Quarz rumexperimentiert und habe
> jetzt die Frequenz als Richtwert auf 7998976 Hz gestellt
Das hört sich an, wie wenn du mit delays rumbastelst... :-/

> läuft die Testuhr 40 Minuten und geht ein Bruchteil einer Sekunde vor.
Weil du die Taktfrequenz zu niedrig angegeben hast?
Denn tatsächlich könnte es ja sein, dass dein Quarz schneller läuft...

von Frank (Gast)


Lesenswert?

Nimm einen 32.786er, wie in jeder Uhr und gut ist - da hat sich noch 
niemand über seine Uhr beschwert!

von micha (Gast)


Lesenswert?


von Sam (Gast)


Lesenswert?

Lothar Miller schrieb:
> Das hört sich an, wie wenn du mit delays rumbastelst... :-/

Nein, natürlich mit 8bit Timer. Sonst wär der Teiler von 256 auch nicht 
wichtig. Ich hab ein bisschen gerechnet dann probiert und so weiter, 
aber nie länger als ne Stunde laufen lassen (ich will ja heute mit der 
Zeit noch fertig werden).

56min 1/4Sekunde abweichung.

Ich denke das reicht, bei einem Tunier wären das dann eine halbe Sekunde 
bei 2 Stunden.

Genauigkeit von DGT ist:

http://www.nextag.de/DGT-Schachuhr-digital-DGT-1532161459/de/spezifikationen-html
Genauigkeit: besser als eine Sekunde pro Stunde

Das hab ich ja auch.


Wie verädert sich die Frequenz vom Quarz über Temperaturschwankungen?
z.b. zw. 15 (kalten Raum) - 35 (draußen im heißen Sommer)°C?

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:
> Lothar Miller schrieb:
>> Das hört sich an, wie wenn du mit delays rumbastelst... :-/
>
> Nein, natürlich mit 8bit Timer. Sonst wär der Teiler von 256 auch nicht
> wichtig.

Wieso Teiler? Wieso 256?

Hängst du dich an den Overflow Interrupt?

Dazu nimmt man doch den CTC, und das nach Möglichkeit von einem 16 Bit 
Timer (dann hat man weniger Arbeit :-)


http://www.mikrocontroller.net/articles/AVR-Tutorial:_Uhr
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC

von Sam (Gast)


Lesenswert?

Noch was zum Delay: Das wär ja grausam wenn bei jedem neuen Befehl die 
Uhr langsamer tickt bzw. man sie korrigieren muss.

micha schrieb:
> Siehe auch
> http://www.mikrocontroller.net/articles/AVR_-_Die_...
>

Danach hab ich es berrechnet.

Karl heinz Buchegger schrieb:
> Wieso Teiler? Wieso 256?
>
> Hängst du dich an den Overflow Interrupt?
>
> Dazu nimmt man doch den CTC, und das nach Möglichkeit von einem 16 Bit
> Timer (dann hat man weniger Arbeit :-)
>
>
> http://www.mikrocontroller.net/articles/AVR-Tutorial:_Uhr
> Siehe auch
> http://www.mikrocontroller.net/articles/AVR_-_Die_...

Ich glaub man braucht das gar nicht mit dem Rest / den CTC, denn:

bei z.b. 7999999 (schlechteste beispiel), geteilt durch den Prescaler 
256
7999999 / 256 = 31249,99609
Also fehlt bei jeder Sekunde ca. ein Timeroverflow
-> 255 Takte fehlen (0,99609*256 = 255)
Das heißt bei 7999999Hz: 256 / 7999999 = ca. 0,000032 Sekunden fehlen
 pro Sekunde. Das sind in einer Stunde *3600 = .ca. 0,1152s und an einem 
Tag *24 = ca. 2.7648s

Ich denke bei einer Schachuhr kann man das vernachlässigen (man bedenke, 
dass das das schlechteste beispiel war).

Ich werde mir die CTC trotzdem man anschauen.

PS: Ich kenne mich in der AVR programmierung wirklich nicht gut aus. 
Wenn ich was neues programmieren will, muss ich erst nachschauen wie das 
beim AVR geht. Bisher weiß ich nur wie Timer, das ganze mit den Ports 
geht. Vom Rest weiß ich nicht wie man es programmiert, sondern nur das 
es das gibt und wie es funktioniert. Mein Vorteil ist halt, dass ich C 
progammieren kann.

Noch was, korrigiert mich wenn die Rechnung nicht stimmt.

80min und fast eine halbe sekunde abweichung.

von Sam (Gast)


Lesenswert?

Sam schrieb:
> 256 / 7999999 = ca. 0,000032

müsste 255 / 7999999 = ca. 0,000031875 heißen
nach einer Stunde sind es dann 0.11475s
und nach einem Tag "nur" 2.754s

Keine wirklichen Änderungen.

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:

>
> Ich werde mir die CTC trotzdem man anschauen.

Tu das.
Funktioniert wie dein bisheriges Schema, nur dass die 256 auch noch 
variabel sind und du einen anderen Interrupt benutzt. Mehr ist es nicht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Ich hab ein bisschen mit meinem 8Mhz Quarz rumexperimentiert
> und habe jetzt die Frequenz als Richtwert auf 7998976 Hz gestellt
Wie und wo hast du diese Frequenz eingestellt?

von Sam (Gast)


Lesenswert?

Hier:
1
uint16_t quotient = 7998976 / 256;
2
    
3
    while(1) 
4
    {
5
        if(timercounter >= quotient)
6
        {

Bei F_CPU nicht, ich werde delay auch nicht verwenden, und wenn doch ist 
es egal wenn es nicht genau stimmt. Für die genaue Zeitrechnung verwende 
ich sowieso den Timer und für den MAX7219 brauch ich kein delay da er 
bis 10 Mhz ansprechbar ist.

Da bin ich mir noch nicht ganz sicher: Muss ich > oder >= benutzen?

von Korax K. (korax)


Lesenswert?

Mark Brandis schrieb:
>
> Huch, seit wann das? Ich kenn das noch als "Zwei Stunden für 40 Züge"...

Schnellschach geht bis 1h:
http://www.schachakademie.com/schachregeln/schach_schachregeln_fide_anhang_b_schnellschach.htm
Und mehr als sagen wir 2h ist unsinnig.

Wenn Du normal spielst, brauchst Du keine Uhr.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> uint16_t quotient = 7998976 / 256;
Es ist ja eigentlich schon klar, dass deine Uhr falsch geht, wenn du im 
Programm mit ungenauen und falschen Teilern rechnest...
Du hast nun mal einen Oszillator mit 8000000Hz. Und wenn du mit 
7998976Hz rechnest, dann kommt ein Fehler von 0,013% heraus.
Damit komme ich auf einen Wert von 0,42 sec Abweichung auf die 56 min. 
Das deckt sich ganz gut mit deiner Beobachtung:
> 56min 1/4Sekunde abweichung.

Also: alles im zu erwartenden grünen Bereich.... ;-)
Nicht der Controller macht den Fehler. Du hast ihn bei der Berechnung 
gemacht.

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:
> Hier:
>
>
1
> uint16_t quotient = 7998976 / 256;
2
> 
3
>     while(1)
4
>     {
5
>         if(timercounter >= quotient)
6
>         {
7
> 
8
>
>

Was genau machst du da?
Wenn du mit einem Timer und einem Interrupt arbeitest, stellt sich diese 
Frage, bzw. diese Codestelle gar nicht.
Das weiterschalten der Uhr machst du in einem Interrupt und nicht indem 
du irgendeine Variable, die ständig ihren Wert ändert, per Schleife 
überwachst.
Genau dafür sind Interrupts da! Ein Ereignis (Timer hat einen bestimmten 
Wert erreicht) tritt auf, behandle es. Und wenn sich die Behandlung ein 
wenig verzögert ist es auch nicht so schlimm, das Interrupt Flag hat 
gespeichert, dass das Eregnis aufgetreten ist und bei der nächsten 
möglichen Gelegenheit (wenn die Interrupts wieder freigegeben werden) 
wird es abgearbeitet.

von Sam (Gast)


Angehängte Dateien:

Lesenswert?

Fra Nk schrieb:
> Mark Brandis schrieb:
>>
>> Huch, seit wann das? Ich kenn das noch als "Zwei Stunden für 40 Züge"...
>
> Schnellschach geht bis 1h:
> http://www.schachakademie.com/schachregeln/schach_...
> Und mehr als sagen wir 2h ist unsinnig.
>
> Wenn Du normal spielst, brauchst Du keine Uhr.

Nein er hat völlig recht, wenn es gibt auch 2 Stunden für 40 Züge, das 
ist zurzeit die normale Bedenkzeit für Wettbewerbspartien. 
Wahrscheinlich wird aber bald 90min +30s pro Zug eingeführt. Aber ich 
werde die Uhr wahrscheinlich fast ausschließlich nur für Blitz 
einsetzen. Höchtens dann wird sie für 2 Stunden benutzt, wenn ich eine 
lange Partie Zuhause spiele (höchtens bei vereinsinternen Turnier; 
außerdem muss der Gegner einverstanden sein).

Sie geht jetzt immernoch ziemlich genau eine halbe Sekunden vor 
innerhalb 2 Stunden.

Lothar Miller schrieb:
> Das deckt sich ganz gut mit deiner Beobachtung:
>> 56min 1/4Sekunde abweichung.
>
> Also: alles im zu erwartenden grünen Bereich.... ;-)
> Nicht der Controller macht den Fehler. Du hast ihn bei der Berechnung
> gemacht.
>

Mit 8Mhz ist die Uhr nachgegangen und so geht sie vor also muss ich was 
zwischen drin ausrechnen:

7998976 * (1 + .5 / 7200) = 7999531.484 Hz

Wie gesagt bisher hab ich ausprobiert.

Karl heinz Buchegger schrieb:
> Was genau machst du da?
> Wenn du mit einem Timer und einem Interrupt arbeitest, stellt sich diese
> Frage, bzw. diese Codestelle gar nicht.
> Das weiterschalten der Uhr machst du in einem Interrupt und nicht indem
> du irgendeine Variable, die ständig ihren Wert ändert, per Schleife
> überwachst.
> Genau dafür sind Interrupts da! Ein Ereignis (Timer hat einen bestimmten
> Wert erreicht) tritt auf, behandle es. Und wenn sich die Behandlung ein
> wenig verzögert ist es auch nicht so schlimm, das Interrupt Flag hat
> gespeichert, dass das Eregnis aufgetreten ist und bei der nächsten
> möglichen Gelegenheit (wenn die Interrupts wieder freigegeben werden)
> wird es abgearbeitet.

Ich lad dir mal den ganzen Code hoch. Ich hab dir nur die 
Definitionzeilen gezeigt.

Und ja der Max hat einen Decoder aber ich möchte auch Zeichen anzeigen, 
die mit diesem nicht gehen (nur bevor du fragst wie alle die meinen Code 
sehen).

von Oliver (Gast)


Lesenswert?

Lothar Miller schrieb:
> Du hast nun mal einen Oszillator mit 8000000Hz. Und wenn du mit
> 7998976Hz rechnest, dann kommt ein Fehler von 0,013% heraus.

Der Oszillator mit einem Feld-,  Wald-, und Wiesenquarz wird alles 
mögliche haben, nur nicht genau 8000000Hz. Auch wenn da 8,00 Mhz 
draufsteht.

Insofern ist der Ansatz mit dem durch trial and error angepassten Faktor 
doch durchaus richtig.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Verleg das Hochzählen deiner Uhr in den Interrupt
1
#define F_CPU  7998976
2
3
    //Zählvariablen initialisieren       
4
volatile uint8_t seconds = 0;
5
volatile uint8_t minutes = 0;
6
7
volatile uint8_t updateDisplay = 0;
8
9
uint16_t nrCalls = 0;
10
11
ISR (TIMER0_OVF_vect)
12
{
13
  nrCalls++;
14
  if( nrCalls == F_CPU / 256 ) {    // es sind genügend Aufrufe
15
                                    // für 1 Sekunde erfolgt
16
    seconds++;
17
    if( seconds == 60 ) {
18
      seconds = 0;
19
      minutes++;
20
      if( minutes == 100 ) {
21
        minutes = 0;
22
      }
23
    }
24
25
    updateDisplay = 1;
26
  }
27
}
28
29
int main(void)
30
{
31
    //Init MAX7219
32
    SPIMasterInit();
33
    SetMode(MAX_MODE_NORMAL);
34
    SetIntensity(0x0F);
35
    SetDecodeMode(0x00);
36
    SetScanLimit(0x07);
37
    SetAll(0);
38
    
39
    //8bit Timer Init
40
    TCCR0 = (1<<CS00);          //Kein Teiler
41
    TIMSK |= (1<<TOIE0);        // Overflow Interrupt erlauben
42
    sei();                      // Global Interrupts aktivieren
43
    
44
    updateDisplay = 1;   // den ersten Update forcieren
45
    
46
    while(1) 
47
    {
48
      if( updateDisplay == 1 ) {
49
                   // die aktuelle Uhrzeit holen. Dabei aber dafür sorgen
50
                   // dass sich die nicht schnell mal ändern kann
51
        cli();
52
        uint8_t sec = seconds;
53
        uint8_t min = minutes;
54
        updateDisplay = 0;
55
        sei();
56
57
                   // ab jetzt haben wir alle Zeit der Welt die Zeit auf
58
                   // die ANzeige zu bringen
59
60
        SetDigit( 3, chars[sec % 10] );
61
        SetDigit( 2, chars[sec / 10] );
62
        SetDigit( 1, chars[min % 10] );
63
        SetDigit( 0, chars[min / 10] );
64
      }
65
    }
66
}

Und wie auch schon gesagt:
Wechsle auf den 16-Bit Timer, nimm den CTC Modus (üzugehörigen 
Interrupt) und du bist die Beschränkung, dass du die Quarzfrequenz nur 
in Vielfachen von 256 vorgeben kannst auch noch los.

von 007boris (Gast)


Lesenswert?

Ist das für ein Schachspiel nicht eigentlich egal. Die Uhr wird doch 
nach jedem Zug wieder auf Null gestellt und läuft doch für beide Spieler 
gleich "Falsch". Bitte klärt mich auf.

von 007boris (Gast)


Lesenswert?

Ok. Hab was gefunden. Sie läuft normal weiter und wird nur angehalten. 
Aber bei zwei Stunden kommt es nicht auf 1 Sekunde an. Von daher ist die 
Quarzgenauigkeit ja ausreichend.

von Karl H. (kbuchegg)


Lesenswert?

007boris schrieb:
> Ist das für ein Schachspiel nicht eigentlich egal. Die Uhr wird doch
> nach jedem Zug wieder auf Null gestellt und läuft doch für beide Spieler
> gleich "Falsch". Bitte klärt mich auf.

Im Prinzip ja.
(Die Uhr wird nicht auf 0 gestellt. Die Uhr wird von jedem Spieler für 
sich angehalten und wenn er wieder am Zug ist läuft sie weiter). 
Allerdings gibt es noch Zusatzregeln, die sagen, dass man für x Züge 
insgesamt nur eine bestimmte Zeit zur Verfügung hat.
Allerdings wird wohl kaum jemand nachmessen, ob die Uhr in 2 Stunden 2 
Sekunden zu schnell oder zu langsam gelaufen ist, da das ja für beide 
Spieler gleichermassen gilt.

War aber immer interessant zu beobachten, als im deutschen Fernsehen 
noch der Herr Pfleger Schachpartien kommentiert hat. Je näher dieses 
Zeitlimit kam, desto hektischer wurden dann schon mal Züge aus dem Ärmel 
geschüttelt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Oliver schrieb:
> Der Oszillator mit einem Feld-,  Wald-, und Wiesenquarz wird alles
> mögliche haben, nur nicht genau 8000000Hz.
Dann würde ich den Oszillator auf 8,000000MHz abgleichen und dann im 
Programm mit 8 MHz rechnen. Das lässt sich doch schön teilen:
8000000 : 200 = 40000
Also ein Timeroverflow nach jeweils 200 Takten und davon 4000, das gibt 
eine saubere Zehntelsekunde.

> Insofern ist der Ansatz mit dem durch trial and error angepassten Faktor
> doch durchaus richtig.
Hmmm...
Nur gibt es nicht viel Spielraum, denn zum Schluss wird noch durch 256 
geteilt:
>>> uint16_t quotient = 7998976 / 256;
Der qoutient ist genau gleich, ob ich da 7998976 oder 7999231 
hinschreibe. Es wird eine Pseudogenauigkeit vorgegaukelt.

von Sam (Gast)


Lesenswert?

@Karl heinz Buchegger

Du erinnerst mich an die Spieleprogrammierung mit deiner Updateprüfung.

Danke für den Tipp.
Sollte man aber nicht mit Divisionen sparsam umgehen (bei dem Prog ist 
das natürlich egal), der Atmega hat doch keine Hardwaredivision, oder 
hab ich da was falsches gehört.

F_CPU wird bei mir mit 8000000UL definiert.
Was heißt das UL. Ich hab das aus dem Inet, aber was es heißt weiß ich 
nicht.

7999488 Hz stimmt übrigens auch nicht ganz, das ist zu hoch.
Ich nehm mal (7999488 + 7998976) / 2 = 7999232

von Sam (Gast)


Lesenswert?

Lothar Miller schrieb:
> Oliver schrieb:
>> Der Oszillator mit einem Feld-,  Wald-, und Wiesenquarz wird alles
>> mögliche haben, nur nicht genau 8000000Hz.
> Dann würde ich den Oszillator auf 8,000000MHz abgleichen und dann im
> Programm mit 8 MHz rechnen. Das lässt sich doch schön teilen:
> 8000000 : 200 = 40000
> Also ein Timeroverflow nach jeweils 200 Takten und davon 4000, das gibt
> eine saubere Zehntelsekunde.

Ich hab leider keine Ahnung wie man den pf Wert der 
Anschwingkondensatoren ausrechnet.

>> Insofern ist der Ansatz mit dem durch trial and error angepassten Faktor
>> doch durchaus richtig.
> Hmmm...
> Nur gibt es nicht viel Spielraum, denn zum Schluss wird noch durch 256
> geteilt:
>>>> uint16_t quotient = 7998976 / 256;
> Der qoutient ist genau gleich, ob ich da 7998976 oder 7999231
> hinschreibe. Es wird eine Pseudogenauigkeit vorgegaukelt.

Ich weiß, dass int16 keine Gleitkommazahl ist, was würde das auch 
bringen. Deswegen nimm ich nur durch 256 teilbare Zahlen. Sollte das 
nicht reichen kann ich immer noch eine Restkorrektur einbauen wie bei 
Beitrag "Die genaue Sekunde / RTC"

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:
> @Karl heinz Buchegger
>
> Du erinnerst mich an die Spieleprogrammierung mit deiner Updateprüfung.

Der springende Punkt ist der, dass auf diese Art die Uhr auf jeden Fall 
weiter läuft, selbst wenn dein Programm etwas ganz anderes macht.

> Danke für den Tipp.
> Sollte man aber nicht mit Divisionen sparsam umgehen (bei dem Prog ist
> das natürlich egal), der Atmega hat doch keine Hardwaredivision, oder
> hab ich da was falsches gehört.

Ist in dem Fall schon ok.
Du hast 1 Sekunde Zeit um die Anzeige zu aktualisieren. Da kann man 
schon ein wenig (8-Bit) dividieren.

Grundsätzlich solltest du solche Faustregeln auch als das ansehen, als 
was sie gedacht sind: Als Faustregeln die einen Leitfaden bilden, mit 
dem erst mal nicht allzuviel schief gehen kann. Im Einzelfall kann man 
von diesen Regeln immer wieder einmal abweichen, wenn man sich über die 
Auswirkungen im klaren ist. In diesem Fall sind die Auswirkungen: 0

> F_CPU wird bei mir mit 8000000UL definiert.
> Was heißt das UL. Ich hab das aus dem Inet, aber was es heißt weiß ich
> nicht.

unsigned long

von Grolle (Gast)


Lesenswert?

Der ganze Thread ist doch Quatsch und geht am eigentlichen Problem 
vorbei.

Du musst die Uhr so machen, dass sie so hochtechnisch und 
hochwissenschaftlich und höchstpräzise aussieht wie möglich (mit 
gefrästem Schriftzug "Schachuhr CAESIUM NORMAL QUARZ", hochgenauen 
Lichtschrankentasten, gebürstetes Metallgehäuse mit Fenstern zur 
Begutachtung der Technik usw.) ist, aber trotzdem die Zeit bei DIR 
langsamer läuft als beim Gegner.

von Sam (Gast)


Lesenswert?

Grolle schrieb:
> Der ganze Thread ist doch Quatsch und geht am eigentlichen Problem
> vorbei.
>
> Du musst die Uhr so machen, dass sie so hochtechnisch und
> hochwissenschaftlich und höchstpräzise aussieht wie möglich (mit
> gefrästem Schriftzug "Schachuhr CAESIUM NORMAL QUARZ", hochgenauen
> Lichtschrankentasten, gebürstetes Metallgehäuse mit Fenstern zur
> Begutachtung der Technik usw.) ist, aber trotzdem die Zeit bei DIR
> langsamer läuft als beim Gegner.

Und wenn der Gegner entscheiden darf auf welcher Seite die Uhr steht?

Jetzt mal im Ernst, ich baue mir die Schachuhr aus 2 Zwecken:

-Weil es Spaß macht
-und weil ich dann eine Digitale uhr hab.

und nicht um zu schummeln.


Wieso schälts du die Interrupts aus?
Was wenn in dieser Zeit ein Overflow stattfindet würde?

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:

> Wieso schälts du die Interrupts aus?

Damit ich sicher gehen kann, dass das was ich von seconds und minutes 
auslese auch wirklich zusammengehört und einen Zeitstempel bildet.

(*)

> Was wenn in dieser Zeit ein Overflow stattfindet würde?

Dann wird der zugehörige Interrupt ein klein wenig verzögert und nach 
dem sei() nachgeholt. Macht aber nichts. Der Timer wird davon ja nicht 
beeinflusst und läuft unbeirrt weiter. Pünktlich zum nächsten Zeitpunkt 
wird wieder der Interrupt ausgelöst.

(*)
Das wird zwar so bei dir nicht auftreten, weil es sich vom Timing her 
nicht ausgeht. Aber folgendes Szenario

Die aktuelle Zeit sei
    3 MInuten und 59 Sekunden

du liest die Sekunden aus und kriegst klarerweise die 59.
Noch ehe du die Minuten auslesen kannst, kommt der Interrupt, der die 
Uhr um 1 Sekunde weiterschaltet. Die ISR zählt die Zeit hoch auf 4 
Minuten und 00 Sekunden.
Die ISR ist fertig und im Hauptprogramm gehts weiter mit 'Auslesen der 
Minuten'. Da kriegst du die 4.

Auf deiner Anzeige steht dann 04:59  und nicht 04:00 oder 03:59 wie es 
eigentlich richtig wäre (je nachdem was man dann als richtig ansieht)
Und alles nur, weil dir ein Interrupt zwischen die Sekunden und die 
Minuten reingefahren ist.

von Sam (Gast)


Lesenswert?

Danke, ich hab dein Prog jetzt mal getestet, aber komischerweise zeigt 
die anzeige so viele Zahlen an das man nichts erkennen kann, und wartet 
dann mit einer belibigen Zahl 1 sekunde. Die Einer der Minuten werden 
dabei immer um 1 oder 2 größer.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
5
#ifndef F_CPU
6
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
7
(z.B. durch Übergabe als Parameter zum Compiler innerhalb
8
des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
9
"nachträgliche" Definition hinweist */
10
#warning "F_CPU war noch nicht definiert, wird nun mit 8000000 definiert"
11
#define F_CPU 7998976 /* Quarz mit 8 Mhz */
12
#endif 
13
#include <util/delay.h>
14
#include <stdlib.h>
15
#include "Max7219.h"
16
17
uint8_t chars[] = {126,48,109,121,51,91,95,112,127,123};
18
19
//Zählvariablen initialisieren       
20
volatile uint8_t seconds = 0;
21
volatile uint8_t minutes = 0;
22
volatile uint8_t updateDisplay = 0;
23
uint16_t timercounter = 0; 
24
25
int main(void)
26
{
27
    //Init MAX7219
28
    SPIMasterInit();
29
    SetMode(MAX_MODE_NORMAL);
30
    SetIntensity(0x0F);
31
    SetDecodeMode(0x00);
32
    SetScanLimit(0x07);
33
    SetAll(0);
34
    
35
    //8bit Timer Init
36
    TCCR0 = (1<<CS00);          //Kein Teiler
37
    TIMSK |= (1<<TOIE0);        // Overflow Interrupt erlauben
38
    sei();                      // Global Interrupts aktivieren
39
40
    updateDisplay = 1;
41
    
42
    while(1) 
43
    {
44
        if( updateDisplay == 1 ) 
45
        {
46
                   // die aktuelle Uhrzeit holen. Dabei aber dafür sorgen
47
                   // dass sich die nicht schnell mal ändern kann
48
            cli();
49
            uint8_t sec = seconds;
50
            uint8_t min = minutes;
51
            updateDisplay = 0;
52
            sei();
53
54
                   // ab jetzt haben wir alle Zeit der Welt die Zeit auf
55
                   // die ANzeige zu bringen
56
57
            SetDigit( 3, chars[sec % 10] );
58
            SetDigit( 2, chars[sec / 10] );
59
            SetDigit( 1, chars[min % 10] + 128 ); // + 128 für den Trennpunkt
60
            SetDigit( 0, chars[min / 10] );
61
      }
62
    
63
    }
64
}
65
66
ISR (TIMER0_OVF_vect)
67
{
68
    timercounter++;
69
    if( timercounter >= 31246 ) // es sind genügend Aufrufe für 1 Sekunde erfolgt
70
    {                                      
71
        seconds++;
72
        if( seconds == 60 ) 
73
        {
74
            seconds = 0;
75
            minutes++;
76
            if( minutes == 100 ) 
77
            {
78
                minutes = 0;
79
            }
80
        }
81
        updateDisplay = 1;
82
    }
83
}

Müsste doch so stimmen, oder?

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:

> Und wenn der Gegner entscheiden darf auf welcher Seite die Uhr steht?

Da muss dann eben ein wenig clever sein :-)
Ein kleiner Magnet im Kugelschreiber vor der Uhr informiert dann die Uhr 
auf welcher Seite ich drücke :-)

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:

> Müsste doch so stimmen, oder?

Wir haben beide vergessen timercounter  in der ISR wieder auf 0 zu 
setzen.
Nachdem 1 Sekunde vorbei ist, geht ja die Zählung der ISR Aufrufe wieder 
von vorne los.
1
ISR (TIMER0_OVF_vect)
2
{
3
    timercounter++;
4
    if( timercounter >= 31246 ) // es sind genügend Aufrufe für 1 Sekunde erfolgt
5
    {
6
      timercounter = 0;
7
      ....

von Grolle (Gast)


Lesenswert?

> Und wenn der Gegner entscheiden darf auf welcher Seite die Uhr steht?

Eben, gerade DA muss ja das Entwickler-Know-how zur Entfaltung kommen.
Die gehackte Backdoor mit Geheimpasswort in der Schachuhr sozusagen.

Wir sind doch in einer Demokratie, da muss man es ja so machen wie 
unsere zahlreichen Vorbilder ganz oben und ganz unten.

"Gaming the system for your own advantage", das Motte unserer Epoche.

<sarcmarc 
url="http://02d9656.netsoljsp.com/SarcMark/modules/user/commonfiles/loadhome.do 
">

von Sam (Gast)


Lesenswert?

Hab ich echt übersehen, danke.
Sind wiedermal die Fehler an denen man stundenlang verzweifeln könnte 
und ein anderer findet sie sofort (einmal hab ich in einem anderen Prog 
ein = statt ein == gemacht, das hat wirklich stunden gedauert bis ich 
das fand).

Ich hab da noch ein anderes Problem, vielleicht hast du erfahrung damit.
Ich muss um mein Mega zu programmieren ihn manchmal fest in den Sockel 
drücken. Wie bekomm ich ihn da rein, dass er auch so bleibt, ohne ihn 
irgendwie anzukleben, bzw. zu verzinnen?

von Karl H. (kbuchegg)


Lesenswert?

verzinnen auf keinen Fall.

Was ist das für einer?
DIP Gehäuse?

Ich würde mal den IC aus dem Sockel nehmen, dann links und rechts an den 
schmalen Seiten anfassen und die Beinchen gleichmässig mit mässigem 
Druck gegen die Tischplatte ein wenig nach innen biegen. Aber nur wenig! 
Andere Seite genauso.

Scheint so, dass du einen billigen Sockel mit Blechkontakten hast, aus 
dem sich der Mega immer wieder mal ein wenig rausarbeitet.

Andere Möglichkeit: Einen Sockel mit gedrehten Kontakten kaufen und den 
in deinen Programmiersockel stecken oder überhaupt den Sockel 
austauschen. Dann sollte der Spuk auch ein Ende haben.

von Sam (Gast)


Lesenswert?

Ist Dip
der hier, nur schmaler als auf dem bild:
http://www.reichelt.de/?;ACTION=3;LA=444;GROUP=C131;GROUPID=3215;ARTICLE=8222

superflach und gedreht ist der auch, nur die Beine des Megas sind leicht 
verbogen.

von Eddy C. (chrisi)


Lesenswert?

Man bekommt auch den schiefsten Prescaler gebacken, indem man folgendes 
macht:

#define F_CLK     8000000UL   // Die Quarzfrequenz
#define PRESCALER 256         // Konfiguration des Vorteilers im Timer

unsigned long Timer = 0;

ISR (TIMER0_OVF_vect)
{
   Timer += PRESCALER;
   if (Timer >= F_CLK)
   {
      Timer -= F_CLK;
      Sekunde++;
      // usw...
   }
}

Oben bei der Quarzfrequenz darf dann auch eine tatsächlich gemessene 
Frequenz eingetragen werden, womit obszöne Genauigkeiten erreichbar sind 
;-)

von Sam (Gast)


Lesenswert?

Eddy Current schrieb:
> Oben bei der Quarzfrequenz darf dann auch eine tatsächlich gemessene
> Frequenz eingetragen werden, womit obszöne Genauigkeiten erreichbar sind
> ;-)

Die aber nicht stimmt, oder hast du ein Quarz mit der Toleranz 0%.

von Karl H. (kbuchegg)


Lesenswert?

Sam schrieb:
> Eddy Current schrieb:
>> Oben bei der Quarzfrequenz darf dann auch eine tatsächlich gemessene
>> Frequenz eingetragen werden, womit obszöne Genauigkeiten erreichbar sind
>> ;-)
>
> Die aber nicht stimmt, oder hast du ein Quarz mit der Toleranz 0%.

Was er meint ist.

Benutz es. Lass die Uhr eine Woche laufen, rechne dir die tatsächliche 
Quarzfrequenz aus und trag sie auf den Taktzyklus genau ein und alles 
ist gut.
Bei einigermassen gleichbleibender Temperatur verändert auch der Quarz 
seine Frequenz nur wenig.

Mit deinem Schema kannst die Quarzfrequenz nur in Vielfachen von 256 
einfliessen lassen. Mit seinem Schema gehts auf die Schwingung genau.

von Sam (Gast)


Lesenswert?

Achso sorry hab ich falsch verstanden. Ja das stimmt natürlich. Eine 
Woche?
Ich denke ein paar Stunden reichen, so über die Nacht, das soll ja ne 
Schachuhr werden und keine Uhr (so ne uhr fänd ich irgendwie zu einfach 
und zu primitiv).

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.