Hello, Guest the thread was viewed4.9k times and contains 17 replies

last post from detlef at the

Arduino 7-Segment Uhr mit Taster

  • Moin,
    ich habe mir mit einem Arduino bisher einen Zähler zusammengebaut, der von 00:00 bis 23:59 zählt und dann wieder von Vorne beginnt.
    Ein Taster ist auch angeschlossen, allerdings haut das damit geplante Einstellen der Uhrzeit nicht so hin, wie ich mir das gedacht habe... Es mangelt mir einfach an Wissen und Erfahrung in C Programmierung.


    Ich habe auch noch einen Quarz 32.768, der den Takt irgendwie vorgeben soll. Aber wie.....


    Ich poste hier einfach mal den Code (der ist von wo auch immer überall zusammenkopiert)

    Ja ich weiß auch nicht was ich noch groß schreiben soll, ich hoffe einfach mal, hier die entscheidenen Tipps zu bekommen ;)
    Ich bedanke mich schon mal im Voraus =)

  • Hi,


    du kannst auf mehrere Arten an das Problem rangehen.
    a) wäre eine Timer-Routine, welche jede Sekunde ausgelöst wird. Darin könnte man dann die Uhrzeit hochzählen. Wenn du einen Arduino mit 16MHz Quarz hast (eig. alle), ist das genau genug.
    b) Nimm eine der vielen Zeit-Bibliotheken: https://github.com/PaulStoffregen/Time oder ähnliche
    c) Versuch die Zeit über millis() herauszubekommen. Hab ich aber noch nicht gemacht, und weiß nicht, wie kompliziert das ist.


    Wenn ich deinen Code richtig lese, hast du ja eine gemultiplexte Anzeige, es leuchtet also immer nur eine Ziffer und das sollte entsprechend schnell geschehen.
    Ich würde folgendes machen:
    Mach dir 3 uint8_t Variablen, "hour", "minute", "second".
    Mach dir noch eine uint8_t Variable "digit" in welcher du speicherst, bei welcher Ziffer du gerade bist
    Nimm eine Timer-Bibliothek: http://playground.arduino.cc/Code/Timer1 (habe mit dieser gute Erfahrungen) und lasse eine Funktion z.B. 100x in der Sekunde ausführen (kann man später easy erhöhen).
    Darin schreibst du jeweils die aktuelle digit auf die Anzeige (mit Modulo 10 und Teilen durch 10 geht das easy), und machst die Kathoden dazu auch an. Und die digit hochzählen und prüfen, ob sie bei 6 angekommen ist, dann wieder auf 0 setzen.


    Also quasi die Anzeige und die Zeiterfassungslogik trennen. Wenn sich in der Timer1 Routine drum gekümmert wird, dass die Zeit angezeigt wird, kannst du in deiner loop() machen, was du möchtest, auf irgendwelchen Userinput reagieren oder sich um die eigentliche Uhrzeit (siehe oben) kümmern.


    Hoffe das hilft und war nicht allzu unverständlich ;)
    Viele Grüße,
    Tobias

  • allerdings haut das damit geplante Einstellen der Uhrzeit nicht so hin, wie ich mir das gedacht habe
    [...]
    Ja ich weiß auch nicht was ich noch groß schreiben soll

    Hilfreich wäre:
    1. welches Ziel Du erreichen willst
    2. welchen Lösungsweg Du eingeschlagen hast
    3. welches Resultat Du erwartet hast
    4. welches Resultat Du stattdessen bekommen hast

  • Lustig, dass das gerade heute kommt, wo ich doch vor zwei oder drei Tagen selbst eine Uhr mit dem Arduino aufgebaut habe. Einfach nur des Bastelns und des Lernens wegen.


    Ich hab das aber auf eine andere Art und Weise gelöst, ein DS3231-RTC-Modul aus China (1,- Euro) gibt die Uhrzeit vor, gestellt wird diese automatisch beim Hochladen des Codes auf den Arduino. Diese kann man über __TIME__ (mit jeweils zwei Unterstrichen an Anfang und Ende) einsehen.


    Ist zwar ein Workaround und auch nicht 100% akkurat, das wäre eine Lösung ohne Echtzeituhr aber auch nicht.


    Ansonsten: Was genau funktioniert mit dem Taster nicht? Pulldown-Widerstand dran?


    (Disclaimer: Ich bin absolut kein Profi und hab mehr Halbwissen als Wissen in diesem Bereich)

  • Also das ist mir leider schon zu hoch.
    Mein Problem ist, dass ich es mit dem vorhandenen multiplex nicht hinbekomme die Uhrzeit gescheit einzustellen. Ich hab das schon mit

    Code
    1. int val = digitalRead(buttonPin);
    2. if (val == HIGH){
    3. digit4++;
    4. if (digit4 < 10)digit4 =0; digit3++;
    5. Serial.println("3++");
    6. if (digit3 < 5)digit3=0; digit2++;
    7. Serial.println("2++");
    8. if (digit2 < 10) digit2=0;digit1++;

    versucht, aber er scheint irgendwie nicht aus der Schleife zu gehen, selbst wenn ich sag, dass wenn dies oder jenes LOW, >2 oder, oder, oder ist und dann break; sag.
    Also dies führe ich in dem Multiplex aus, aber dann scheinen die Regeln nicht mehr zu greifen. Die Stunden können so über 23 hinaus gehen.....
    Ich habe das schon mit sämtlichen Variationen ausprobiert, aber dieses IF im Multiplex scheint nicht das richtige zu sein....


    Ich habe keine Ahnung wie das mit dem uint_8t funktionieren soll, habe mir das allerdings schon angeschaut....


    Ich habe erwartet durch Drücken des Tasters und somit mit dem Hochzählen des Minutensegments die Uhrzeit einstellen zu können. Entweter zu Beginn, beim Starten des Arduino, oder während die Uhr läuft (wäre mir persönlich am liebsten).


    Andere Hardware wollte ich mir eigentlich nicht beschaffen, da ich den ganzen Krams quasi aus einem gescheiterten Projekt übrig habe.


    Der Taster ist mit einem 10K Widerstand angeschlossen...ich glaube PullDown >_< ich weiß aber leider nicht wie ich herausfinde of PullUp oder PullDown. =(


    EDIT: Ok, ist ein PullDown Widerstand. Hab das wie hier Taster angeschlossen.


    EDIT2: Welche Möglichkeiten gibt es denn noch außer IF? Kann man sowas mit case oder irgendeiner Schleife hinbekommen?

  • Achso... das war das letzte was ich ausprobiert hatte, weil alles andere nicht funktioniert hat.
    Ich probier hier wirklich jeden Sch*** aus, auch wenns keinen Sinn macht.


    EDIT: Habs auch schon mit >= ausprobiert, haut auch nicht hin. und er zählt außerdem trotzdem über 23:59 hinaus

  • Poste mal dein ganzes Programm...
    So weiß ich nicht, was z.B. digit4 überhaupt ist.
    Ich vermute mal, digit1 und digit2 sind die Stunden, digit3 und digit4 sind die Minuten?
    Dann versuche das mal:

    Code
    1. if (digit4 > 9)digit4 =0; digit3++;
    2. if (digit3 > 5)digit3=0; digit2++;
    3. if ((digit2 > 3) and (digit1 >= 2))digit2=0; digit1=0;
    4. if ((digit2 > 9) and (digit1 < 2))digit2=0; digit1++;
  • Also dabei zählt er alle Zahlen irgendwie

  • Hm, also so auf Anhieb:
    - "break" verlässt den nächstäußeren Schleifen- oder Switch-Block. Will man zwei oder mehr Schleifen verlassen, muss man das also anders handhaben. Aber welchen Zweck hat das Verlassen der Schleife überhaupt?
    - Du tust Dir echt keinen Gefallen mit solchen Einrückungen. Ich hab das Programm zuerst mal durch "indent" gejagt, bevor ich es angesehen habe.
    - Bei sowas wie "if (condition) statement; noch_ein_statement;" bin ich mir nicht sicher, ob ich jetzt das Blocksystem erklären muss oder nochmal auf das korrekte Einrücken verweisen soll. ;)
    - Für das Hochzählen der Ziffern würde ich gar keine Schleifenstrukturen wie "for" verwenden, das täuscht nur eine Programmlogik vor, die gar nicht da ist.
    - Bist Du sicher, dass Du beim Button HIGH und LOW richtig herum verwendest? Üblicherweise sind solche Buttons Schließer gegen GND, so dass bei Betätigung der Zustand LOW gelesen wird.

  • Hatte dein Teil mit dem Button darin nicht gefunden...


    Das hier sollte eigentlich für den Button gehen:


    Hast du deinen Button mit einem Pull-Down auf Masse?
    Lief das Grundprogramm ohne Button?

  • if (digit4 > 9)digit4 =0; digit3++;

    Ich habe keine Ahnung, was das tun soll, aber fehlen da nicht die Klammern?


    if (digit4 > 9) {digit4 =0; digit3++;}


    C ist kein Commodore Basic, man darf das auch etwas übersichtlicher hinschreiben. Man rückt ein und schreibt (in der Regel) einen Befehl pro Zeile.


    Also meinst du das hier:

    Code
    1. if (digit4 > 9)
    2. {
    3. digit4 =0;
    4. digit3++;
    5. }


    oder das:

    Code
    1. if (digit4 > 9)
    2. digit4 =0;
    3. digit3++;
  • Moin,
    hab jetzt noch mal ne andere Idee gehabt, wahrscheinlich meinte Manawyrm das auch..
    Allerdings haut das nicht hin. Die Zahlen ändern sich nicht..

    Ich wollte damit die Zeit quasi vorspulen und diese For schleife beschleunigen.
    Vielleicht bekomm ich nun ja den entscheidenen Tipp?


    Ich hoffe auch, dass ich das dieses Mal einigermaßen annehmbar eingerückt habe ?( sorry....


    Also das Serial.println kommt an, wenn ich den knopf drücke. (natürlich sehr oft, da es keine Debounce Time gibt. Wie auch immer ich das da noch mit rein bekomme :schande:
    Viele Grüße und danke noch mal!

  • Durch ganz viel Hilfe von Außen hab ichs nun endlich!

  • Ich hoffe auch, dass ich das dieses Mal einigermaßen annehmbar eingerückt habe sorry....

    Kleiner Tip: Da Du scheinbar mit der Arduino-IDE unterwegs bist. CTRL-T (CMD-T unter OSX) macht da ein Autoformat des Source.
    Ueber den Codestyle von der IDE kann man streiten, aber zumindest die Einrueckung ist dann halbwegs so wie man sie erwartet...

  • Durch ganz viel Hilfe von Außen hab ichs nun endlich!

    So ungefähr sahen meine ersten Basic-Programme auch aus. :S
    Aber wenn's funktioniert. :D


    Was macht das Programm den jetzt eigentlich? Nuir das Einstellen oder auch die Anzeige der Uhrzeit?
    Die Programmlogik erschließt sich mir nicht. Aber ich programmiere ja auch erst seit 25 Jahren C. ;)


    Diese Zeile:


    for (int digit1=2; digit1 < 3; digit1++)


    kann man ersetzen durch


    digit1 = 2;


    Und das ist hier auch eine ganz verwegene Konstruktion:


    for (unsigned long verstrichen=0;verstrichen < 60000;verstrichen = millis() - startZeit)

    Kann man in C machen, macht man aber nur, wenn man nicht möchte, dass andere den Code verstehen.