Stoppuhr-Zeitanzeige ist nicht genau

  • Ein Tastendruck wird als solcher erkannt, wenn das Signal LOW ist.

    Demnach muss das Signal = HIGH sein, wenn eine Taste nicht gedrückt ist.


    Wenn man also den Vergleich if ((digitalRead(Starttaste) || digitalRead(Stopptaste)) == LOW) { anstellt, so ergibt das folgende Wahrheitstabelle:


    AktionStarttasteStopptasteErgebnis
    Keine Taste gedrückt(HIGH ODERHIGH) =HIGH
    Nur Stopptaste gedrückt(HIGHODERLOW) =HIGH
    Nur Starttaste gedrückt(LOWODERHIGH) =HIGH
    Beide Tasten gedrückt(LOWODERLOW) =LOW


    Somit wird der IF Ausdruck nur wahr, wenn beide Tasten gedrückt sind. Deswegen wird ODER und kein AND genutzt. Vielleicht macht die Tabelle das etwas klarer... :). Um es etwas weiter zu erklären, zum zweiten Teil der Frage:


    Zitat


    Warum funktioniert das nicht mit "if (digitalRead(Starttaste) && digitalRead(Stopptaste) == LOW)?


    Das ist zu lesen wie "Wenn (digitalRead(Starttaste) == HIGH UND digitalRead(Stopptaste) == LOW). Trifft das zu, dann ist der Ausdruck wahr.

    Das heißt, die Bedingung trifft nur zu wenn die Starttaste NICHT gedrückt ist UND die Stopptaste gedrückt ist. Das ist in C/C++ etwas fies für Einsteiger aber schön für Schreibfaule die sich auskennen.


    Angenommen man hat eine Variable "Wert", die eine ganze Zahl repräsentiert und man will testen ob sie != 0 ist (also TRUE oder auch HIGH) kann geschrieben werden:


    IF(Wert) {[...]} oder IF(Wert != 0) {[...]}. Beide Ausdrücke sind äquivalent.


    Wird noch eine zweite Variable hinzugenommen ("zweiterWert") um zwei Variablen zu testen und man schreibt IF(Wert && zweiterWert == 0} bedeutet das soviel wie "Wenn Wert !=0 und zweiterWert == 0 ist, dann mach etwas".


    Wenn man jedoch IF((Wert && zweiterWert) == 0) verwendet, dann bedeutet das "Wenn das Ergebnis aus (Wert && zweiterWert) == 0 ist, dann mach etwas". Hier kann wieder eine Wahrheitstabelle nach AND aufgestellt werden. Als Ergebnis käme heraus, dass die Bedingungen 0 && 0, 0 && 1, 1 && 0 alle nicht wahr wären (also Ergebnis 0, LOW, FALSE) und nur die Bedingung 1 && 1 zutreffen würde (1, HIGH,TRUE). Auf die Tasten übertragen bedeutet das, dass der Funktionskörper der IF Bedingung bei jeder Tastendruckkombination ausgeführt wird.


    Lange Rede kurzer Sinn, ja die Klammern sind wichtig.


    Man sollte sich merken IF(Wert) {[...]} ist ein Test auf != 0,LOW,FALSE und hat als Ergebnis 1,HIGH, TRUE wenn Wert !=0 ist.

    IF(!Wert) {[...]} (man beachte das ! (bedeutet NOT)) ist ein Test auf == 0,LOW,FALSE und hat als Ergebnis 1,HIGH, TRUE wenn Wert == 0 ist.


    Bei IF(Wert) {[...]} muss man aufpassen, weil der Ausdruck ist auch dann wahr, wenn Wert eine Zahl wie 42 oder -10 (oder reelle Zahlen (float/double) wie -0.03) repräsentiert. Also alles != 0.

    Im Umkehrschluss ist IF(!Wert) {[...]} ausschließlich nur dann wahr, wenn Wert == 0 ist.


    Zur dritten Frage:

    Soweit ich weiß, kann man mit der RTC DS3231 als kleinste Einheit nur Sekunden abfragen. Wenn also auch Zehntel gestoppt werden sollen, geht das so ohne weiteres nicht. Aber evtl. kann man die Uhr als Referenz verwenden, um die Abweichungen auszugleichen.


  • Ich nehme an Du wolltest dass sowohl die Starttaste == LOW ist? if ((digitalRead(Starttaste) | | digitalRead(Stopptaste)) == LOW) {

    nicht das hier ist:

    if ( (digitalRead(Starttaste)==LOW | | digitalRead(Stopptaste)) == LOW)


    Demnach ist das if TRUE wenn die Starttaste ODER die Stopptaste gedrückt ist

    Wenn Du TRUE haben möchtest, wenn beide Tasten gedrückt werden, dann musst Du mit && verbinden.

    Bei | | ist die Bedingung TRUE wenn einer der Ausdrücke TRUE ist. Das heisst, wenn der erste Ausdruck TRUE ist muss bei | | der zweite Ausdruck nicht mehr geprüft werden.


    90 Minuten sind 5400 Sekunden 100/5400* 3 = entspicht dann einer Abweichung von 0.055% (habe ich richtig gerechnet?)

    Eine solche Abweichung ist mit einem Quarz bei einem Arduino doch sehr hoch (scheint mir). Wenn die Uhr 0.055% zu langsam geht, dann müsste der Oszillator bei 16*106 / 100 * 99.055 = 15.8488MHz stehen. Mit einem Oszilloskope oder einem Frequenzzähler liesse sich die Frequenz genauer bestimmen.
    Mein Vorschlag, probier mal einen anderen Arduino und lasse diesen auch 90 Min laufen.

    Ich weiss nicht wie die Implementierung des mS Timers beim Arduino realisiert ist. Aber ich suchte einmal lange nach einem Fehler in einem Frequenzzähler, der ab und an (das waren kurze Zeiten) immer wieder einen falschen Wert lieferte. Meistens stimmte er aber in beinahe regelmässigen Abständen war die Zeit zu kurz. Der Fehler lag, wie immer, bei mir. Um die Basiszeit einzustellen musste der Vorteiler des Timers aufgesetzt werden und ich hatte vergessen, nach Ablauf eines Intervalls diesen Vorteiler auch wieder auf 0 zu setzen. Damit setzte der Timer mit einem restlichen Wert im Vorteiler seine Arbeit fort und führte zu falschen Zeiten.

    Gruss
    Pius

  • Hallo René

    Hab deine Tipps umgesetzt. Vielen Dank.

    unsigned statt int hat nichts gebracht, auf 90 min geht die Stoppuhr immer noch 3 sek nach.

    Der Reset mit den zwei Tastern ist aber ok.

    Leider habe ich die Zeile "if ((digitalRead(Starttaste) || digitalRead(Stopptaste)) == LOW)" nicht so recht verstanden.

    "||" ist doch ein logisches ODER. Der Reset soll doch erfolgen wenn Taste 1 und Taste 2 gedrückt sind. Hat das was mit den Klammern zu tun?

    Warum funktioniert das nicht mit "if (digitalRead(Starttaste) && digitalRead(Stopptaste) == LOW)?

    Kann man ein RTC DS3231 auch für eine Stoppuhr verwenden

  • Hallo Hotte25


    Den Fehler sehe ich auch nicht direkt. Es könnte sein, dass dir ein Zahlenüberlauf einen Streich spielt. Aus diesem Grund solltest du im Zusammenhang mit millis() immer den Datentyp unsigned long anstelle von int verwenden. Du kannst einmal versuchen, ob es etwas hilft.


    Code
    1. unsigned long millisSekunde;
    2. unsigned long millisZehntel;
    3. unsigned long minute, sekunde, zehntel;
    4. int x = 0;
    5. unsigned long StartSekunde = 0;
    6. unsigned long StartZehntel = 0;
    7. int Starttaste = 7;
    8. int Stopptaste = 6;


    Für das Zurücksetzen mit beiden Tasten kannst du zum Beispiel diesen Code verwenden:


    Code
    1. if ((digitalRead(Starttaste) || digitalRead(Stopptaste)) == LOW) {
    2. minute = 0, sekunde = 0, zehntel = 0;
    3. x = 0;
    4. delay(500);
    5. return;
    6. }

    Beim Druck auf beide Tasten wird alles zurückgesetzt. Es werden keine anderen Aktionen durchgeführt, bis die Tasten wieder losgelassen werden. Daher das return. Wenn du die Tasten loslässt, wirst du es nicht schaffen, beide absolut gleichzeitig loszulassen. Damit in dieser Zeit keine Aktion gestartet wird, benötigt man eine kleine Pause (delay(500)).


    Gruss

    René

  • Hallo

    Hab mit deinen Lektionen (die sind klasse) mir einige Grundkenntnisse angeeignet. Nun habe ich eine Stoppuhr am LCD programmiert. Wahrscheinlich geht das mit noch mehr Erfahrung wesentlich besser zu lösen. Meine Stoppuhr hat jedoch eine Fehler, welchen ich nicht finde. Bei einer Laufzeit von 59 min geht die Stoppuhr 1 sek. nach. Wo liegt da der Fehler.

    Zudem möchte ich das Zurückstellen der Stoppuhr nicht mit der Resett Taste lösen, sondern mit gleichzeitigem drücken der beiden Taster. Hab aber keine Idee wie man das löst. Für einen Tipp bin ich dankbar.