Anfänger_LED UHR

Hello World
Hallo Forum, :slight_smile:

Die ersten kleinen Beispiele mit dem Druino habe ich hinter mich gebracht nun wollte ich mir eine LED Uhr basteln und bräuchte eure Unterstützung.
Das Problem, ich bekomme es nicht hin, dass er alle LED´s von einem 60er Pixel, welche Sekundeweise angeen sollen (tun sie auch :-)) wieder löscht. Habt Ihr eine Idee:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#include <Wire.h>       //for Clock until....
#include <DS3231.h>
DS3231 clock;
RTCDateTime dt;          //for Clock until...here

#define PIN            53 // Which pin on the Arduino is connected to the NeoPixels?
#define NUMPIXELS      60  // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 1      // set max brightness (max 64)
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() 
 {
   pixels.begin(); // Initialisieren der Pixel
   clock.begin();  // Startet die Uhr
   pixels.setBrightness(BRIGHTNESS);  //reduziert die Heligkeit auf den oberen Brigthnesswert
 }

void loop() 
{
 dt = clock.getDateTime();
 int Stu =(dt.hour);   //"stunde" gibt Stundenanzeige an
 int Min =(dt.minute);
 int Sek =(dt.second);


  pixels.setPixelColor(Sek, pixels.Color(150,0,0)); // Sekunden werden farbig angezeigt.
  pixels.setPixelColor(Min, pixels.Color(0,150,0)); // Minuten werden farbig angezeigt
  pixels.setPixelColor(Stu, pixels.Color(0,0,150)); // Stunden werden farbig angeigt
   pixels.show(); // Updated die Pixels

int i=Sek;
   for(i==60;i<60;i--){
   pixels.setPixelColor(i, pixels.Color(0,0,0)); // Soll wenn 60 sekunden um sind alle LEDs ausmachen.
   pixels.show(); // Updated die Pixels
}

   
 }

Wollte es auch mit einem Switch case probieren, aber das wurde auch nichts. EVtl. könnt Ihr helfen.

Danke

Sorry, I don’t speak German, but this might help:

for( i=0; i<60; i++ ){

  // Sekunden
  if( i <= Sek )
  {
    pixels.setPixelColor( i, pixels.Color(150,0,0)); // Sekunden werden farbig angezeigt.
  }else
  {
    pixels.setPixelColor( i, pixels.Color(0,0,0));  // >Sek, ausmachen
  }
}

Yours,
TonyWilk

void loop() 
{
  dt = clock.getDateTime();
  int Stu =(dt.hour);   //"stunde" gibt Stundenanzeige an
  int Min =(dt.minute);
  int Sek =(dt.second);

  pixels.setPixelColor(Sek, pixels.Color(150,0,0)); // Sekunden werden farbig angezeigt.
  pixels.setPixelColor(Min, pixels.Color(0,150,0)); // Minuten werden farbig angezeigt
  pixels.setPixelColor(Stu, pixels.Color(0,0,150)); // Stunden werden farbig angeigt
  pixels.show(); // Updated die Pixels
                    // Nun ausmachen bis loop() wieder lauft -- wird nicht zeigen bis pixels.show()
  pixels.setPixelColor(Sek, pixels.Color(0,0,0));   // Sekunden ausmachen
  pixels.setPixelColor(Min, pixels.Color(0,0,0));   // Minuten ausmachen
  pixels.setPixelColor(Stu, pixels.Color(0,0,0));   // Stunden ausmachen
}

zunächst: setzte bitte deinen Code in Code-Tags (Die beiden spitzen Klammern ‘</>’ links oben), dann ist er leichter lesbar.

Die Anweisung
for(i==60;i<60;i--){ist so sicher falsch.
Zum Einen syntaktisch:
(i==60 ist ein Vergleich. Eine Zuweisung wäre i=60)
zum Anderen inhaltlich:
Du beginnst bei i=60, zählst solange runter, bis i<60.
Das ist genau einmal der Fall.

zum Anderen inhaltlich:
Du beginnst bei i=60, zählst solange runter, bis i<60.
Das ist genau einmal der Fall.

Genaugenommen beginnst du bei i = 60; prüfst, ob das kleiner als 60 ist (nein) und brichst deswegen sofort ab. Der Block der for-Schleife wird kein Mal ausgeführt.

Bei meiner LED- Uhr frage ich einfach in einer for-Schleife für jede LED ab, welchen Status sie zeigen soll.

Also sinngemäß: für LED*: wenn Sekunde == i, dann LED = blau; wenn Minute == i, dann LED = grün, wenn Stunde == i, dann LED = rot, ansonsten LED = schwarz*
Ich hoffe es ist verständlich. Selbstverständlich muss man die Stunden noch auf die 60 skalieren...
Aber eine einfache LED- Uhr kann man mit 10 Zeilen schreiben.

Hi

Bei 'stehenden' Zeigern würde ich nicht die ganze Zeit im Kreis herum prüfen, welche Farbe welche LED gerade bekommen soll.
Dort würde ich prüfen, ob die gerade aktuelle Stunden-LED versetzt werden muß - wenn JA: alte LED AUS, neue LED AN.
Gleicher für Minuten und Sekunden.
Drei Prüfungen, bei Treffer je zwei Änderungen.
Mehrfachbelegung (0:0:0), oder wenn der Sekundenzeiger durch den Stundenzeiger läuft, muß man dabei entweder verodern (Blau und Rot ... gibt dann wohl Lila), oder separat behandeln.

Bei einer Uhr hatte ich ein 'schwingendes Pendel' gesehen - fand die Idee echt gelungen.
Also auf den unteren 60° schwang das Pendel mit 1Hz, war glaube ein Bausatz, man konnte die Uhr 'nur' kaufen, Sketch also nicht öffentlich.
Vll. hat ja Einer von Euch den Link - selber finde ich Ihn nicht :confused:

MfG

postmaster-ino:
Bei einer Uhr hatte ich ein 'schwingendes Pendel' gesehen - fand die Idee echt gelungen.

Gute Anregung, könnte mir zu aufregend sein, aber einen Versuch ist es wert!

Nach einem Link suche ich nicht, geht auch alleine :slight_smile:

Hi, danke für die Rückmeldungen. (Hat etwas gedauert bis ich rausfand, wie man die anzeigen kann… :-))

Okay, ich konkretisere mal meine Anfrage:
Ich wollte, dass die Sekunden vorlaufend angezeigt haben. D.h: Wenn 5 Sek um sind, sollen 5 rote LEDs leuchten und müssen entsprechend wieder nach 60 Sekunden auf weiß gesetzt werden…

Mittlerweile habe ich es so “halb” hinbekommen, dass es zumindest lauffähig ist (Überlegen und andere Wege suchen hilft manchmal:-):

// Uhr funktioniert vom Grundsatz, hat jedoch follgende Fehler: Sekunden anzeige ist nicht aktuell -stimmt nicht
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#include <Wire.h>       //for Clock until....
#include <DS3231.h>
DS3231 clock;
RTCDateTime dt;          //for Clock until...here

#define PIN            53 // Which pin on the Arduino is connected to the NeoPixels?
#define NUMPIXELS      60  // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 1      // set max brightness (max 64)
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);



void setup() 
  {
    pixels.begin(); // Initialisieren der Pixel
    clock.begin();  // Startet die Uhr
    pixels.setBrightness(BRIGHTNESS);  //reduziert die Heligkeit auf den oberen Brigthnesswert
    Serial.begin(9600); //startet die serielle Anzeige
  }

void loop() 
{
  dt = clock.getDateTime();
  int Stu =(dt.hour);   //"stunde" gibt Stundenanzeige an
  int Min =(dt.minute);
  int Sek =(dt.second);
  int x=0;
  if (Stu<12){ //gibt die Stundenanzhal im richtigen Feld wieder bis...
   Stu=Stu*5 ;
  }
  else {
    Stu=(Stu-12)*5; 
  } //gibt die Stundenanzhal im richtigen Feld wieder ...ENDE

  Serial.println(Stu);
  for (x=0;x<60; x++){ //baut Uhrenanzeige Stück für Stück auf
    pixels.setPixelColor((Min-1), pixels.Color(0,150,0));// Minuten werden farbig angezeigt mit 3 Punkten...
    pixels.setPixelColor(Min, pixels.Color(0,150,0)); 
    pixels.setPixelColor((Min+1), pixels.Color(0,150,0));// Minuten werden farbig angezeigt mit 3 Punkten...ENDE
    pixels.setPixelColor(x, pixels.Color(150,0,0)); // Sekunden werden farbig angezeigt.   
    pixels.setPixelColor(Stu, pixels.Color(0,0,150)); // Stunden werden farbig angeigt wird in dem Fall nicht von Sekunden "überschrieben", da es dannach steht
    pixels.show(); // Updated die Pixels
    delay (998);
}
  for (x=60;x>0; x--){ //löscht die ganze Anzeige wieder mit leichten zeitlichen Verzug...
  pixels.setPixelColor(x, pixels.Color(0,0,0));
  pixels.show();
  delay (10);//löscht die ganze Anzeige wieder mit leichten zeitlichen Verzug...ENDE 
}
}

@guntherb
Danke für die beiden Hinweise! (Mit dem If war wohl ne “geistige Umnachtung”…)

// Uhr funktioniert vom Grundsatz, hat jedoch follgende Fehler: Sekunden anzeige ist nicht aktuell -stimmt nicht

Zunächst habe ich mal Deinen Sketch an meine Hardware angepaßt. Sieht doch ganz gut aus!

Leider hast Du blockierend programmiert, anstatt loop() als Schleife zu nutzen. Das habe ich mal geändert:

#include <Adafruit_DotStar.h>
#include <SPI.h>         // COMMENT OUT THIS LINE FOR GEMMA OR TRINKET
#define NUMPIXELS 122 // Number of LEDs in strip
#define BRIGHTNESS 50
Adafruit_DotStar pixels = Adafruit_DotStar(NUMPIXELS, DOTSTAR_BGR);

#include <Wire.h>       //for Clock until....
#include <DS3231.h>
DS3231 clock(SDA, SCL);
Time dt;          //for Clock until...here

void setup()
{
  pixels.begin(); // Initialisieren der Pixel
  clock.begin();  // Startet die Uhr
  pixels.setBrightness(BRIGHTNESS);  //reduziert die Heligkeit auf den oberen Brigthnesswert
}

void loop()
{
  uint32_t aktMillis = millis();
  static uint32_t loeMillis = aktMillis;
  const uint32_t loeIntervall = 5;
  dt = clock.getTime();
  byte Stu = (dt.hour);  //"stunde" gibt Stundenanzeige an
  byte Min = (dt.min);
  byte Sek = (dt.sec);
  static byte x = 59, altSek = Sek;
  bool anzeige = false;
  static bool loe = false;
  if (loe || Sek != altSek)
  {
    anzeige = true;
    if (Stu < 12) { //gibt die Stundenanzhal im richtigen Feld wieder bis...
      Stu = Stu * 5 ;
    } else {
      Stu = (Stu - 12) * 5;
    } //gibt die Stundenanzhal im richtigen Feld wieder
    if (Sek == 0 && Sek != altSek)
    {
      loe = true;
    }
    if (loe) {
      if (aktMillis - loeMillis >= loeIntervall)
      {
        loeMillis = aktMillis;
        pixels.setPixelColor(x, pixels.Color(0, 0, 0));
        if (x > 1)
        {
          x--;
        } else {
          x = 59;
          loe = false;
        }
      }
    } else {
      for (byte j = 0; j < 60; j++)
      {
        if (j <= Sek)
        {
          pixels.setPixelColor(j, pixels.Color(150, 0, 0));
        } else {
          pixels.setPixelColor(j, pixels.Color(0, 0, 0));
        }
      }
    }
    pixels.setPixelColor(Min == 0 ? 59 : Min - 1, pixels.Color(0, 10, 0));
    pixels.setPixelColor(Min, pixels.Color(0, 150, 0));
    pixels.setPixelColor(Min == 59 ? 0 : Min + 1, pixels.Color(0, 10, 0));
    pixels.setPixelColor(Stu, pixels.Color(0, 0, 150));
    altSek = Sek;
  }
  if (anzeige)
  {
    pixels.show();
    anzeige = false;
  }
}

Funktioniert das, geändert auf NeoPixel, auch bei Dir?

Natürlich lassen sich Details noch optimieren.

Danke Agmue, es funktioniert soweit, nachdem ich rausgefunden habe, welche Befehle ich für meine Leds abwandeln muss. Z.b: " byte Min = (dt.min);" funktioniert nicht, sondern muss bei mir " byte Min = (dt.minute);" heißen....

Darf ich dir als Anfänger einen haufen "dummer Fragen " stellen? Denn so richtige verstehen tue ich es noch nicht. (Kein Problem, wenn du neun sagst, würde ich verstehen, mach es für mich lediglich schneller und evtl. nachvollziehbarer an die Lösung zukommen, als es mir zu versuchen ewig anzulesen.)

Warum benutzt du byte anstatt integer z.b: bei "byte Stu = (dt.hour);"?

Den Rest muss ich mir erstmal ganz genau überlegen, mit den ganzen If-Fällen :astonished:
Danke dass es nun klappt.

Weil die Stunden nicht größer als 255 werden.

Gruß Tommy

Newer:
Darf ich dir als Anfänger einen haufen "dummer Fragen " stellen?

Na klar, dafür ist ein Forum doch da, oder? Aber bitte öffentlich und an alle, da es möglicherweise Teilnehmer gibt, die es Dir besser erklären können.

Newer:
Warum benutzt du byte anstatt integer z.b: bei "byte Stu = (dt.hour);"?

Der Speicher eines Arduinos ist begrenzt, man sollte ihn sparsam nutzen. Ein UNO möchte für int zwei Bytes, während byte nur ein Byte verwendet. Da die Stunden nur 0 bis 24 bzw. umgerechnet 0 bis 60 zählen, reicht ein Byte 0 bis 255.

Dein Wunsch, die Sekunden-Anzeige verzögert zu löschen, macht den Sketch "unnötig" kompliziert.

Hi,

nach einer langen Woche kam ich nun mal wieder dazu ins Programm reinzuschauen. Noch immer muss ich mich durch die If-Verzweigungen denken, aber die ersten Fragen sind schon da... :-):

  1. Wo kann ich die Pin Belegung der DS3231 Glock ändern (kann es nicht so einfach im Quellcode finden).
  2. Woher weiß ich, dass ich bestimmte Codes abändern muss, bei spezieller Hardware z.b:
    agume: "dt.min" bei mir jedoch "dt.minute"?
  3. Würde hier nicht auch uint16_T reichen (schließlich sind es max. 1000 Millisekunden?
    uint32_t aktMillis = millis();
    static uint32_t loeMillis = aktMillis;
    *const uint32_t loeIntervall = 5; *
  4. "if (loe) {
  • if (aktMillis - loeMillis >= loeIntervall).....*
    Bedeutet dies wenn loe=true?
  1. Wenn ich "If" verwende braucht man dann nicht immer auch ein "else"? (Oder habe ich es nur übersehen?

Danke Newer

Hi

Newer:

  1. Wo kann ich die Pin Belegung der DS3231 Glock ändern (kann es nicht so einfach im Quellcode finden).

Was willst Du da ändern?
Die RTC wird per I²C abgefragt, die Pinne stehen fest.
Vdd und GND ebenso.
Die zwei übrig gebliebenen Pinne werden für die Funktion als RTC nicht gebraucht.

  1. Woher weiß ich, dass ich bestimmte Codes abändern muss, bei spezieller Hardware z.b:
    agume: "dt.min" bei mir jedoch "dt.minute"?

Das wird sich Dir wohl erst in den Innereien der verwendeten Lib erschließen.
Was wird in den Beispielen der verwendeten Lib benutzt? Das solltest Du auch nehmen.
Vll. ist in der Lib, also in Deren Ordner, auch eine Erklärung bei - meine, bei einer Lib hätte ich eine Art 'Befehls-Übersicht' gehabt.

  1. Würde hier nicht auch uint16_T reichen (schließlich sind es max. 1000 Millisekunden?
    uint32_t aktMillis = millis();
    static uint32_t loeMillis = aktMillis;
    const uint32_t loeIntervall = 5;

Jain :slight_smile:
millis() ist eine 32bit Zahl, Diese wird jede ms um 1 erhöht.
Wenn Du jetzt eine Variable nimmst, Die kleiner ist, werden die 'vorderen Bit' abgeschnitten.
Bei einem Byte wäre 254 . 255 . 0 . 1 . 2, obwohl millis() 254 . 255 . 256 . 257 . liefert.
Wenn Du sicher bist, daß Dir diese Zeitspanne ausreicht, spricht eigentlich NIchts dagegen, auch kleinere Variablen zu benutzen - muß ich mir Mal 'antun' - interessante Idee!

  1. "if (loe) {
  • if (aktMillis - loeMillis >= loeIntervall).....*
    Bedeutet dies wenn loe=true?

Die IF-Anweisung wird ausgeführt, wenn die Bedingung 'true' ist - true ist die Bedingung, wenn Diese 'nicht false' ist.
false ist leer/gleich Null.
Wenn loe ungleich Null ist, wird diese If abgearbeitet, sonst nicht.

  1. Wenn ich "If" verwende braucht man dann nicht immer auch ein "else"? (Oder habe ich es nur übersehen?

Nein
Du kannst auch nur 'Wenn dann' nutzen.
Den Else-Zweig brauchst Du ja nur, wenn statt dem 'dann' der 'sonst'-Weg genommen werden muß.
Wenn Du viele 'gleiche' IF-Abfragen hast, dann gibt es noch switch und case.

MfG

Wunderbare Erklärung, mir bleibt nur eine kleine Ergänzung zu 2:

In Deinem Sketch steht #include <DS3231.h>, weshalb nach der möglicherweise vorhandenen Dokumentation Dein zweiter Blick in diese Datei fallen sollte. Dein dritter Blick gehört dann der Datei gleichen Namens aber mit der Erweiterung cpp.

Im Sketch steht Time dt;, in meiner DS3231.cpp dann:

Time::Time()
{
 this->year = 2014;
 this->mon  = 1;
 this->date = 1;
 this->hour = 0;
 this->min  = 0;
 this->sec  = 0;
 this->dow  = 3;
}

Daraus ergibt sich dt.min.

Zu 3: Wenn die Zeiten klein genug sind, funktioniert auch ein 16 Bit Zähler. Damit kann man ein paar Bytes Speicher sparen, das werde ich mir merken :slight_smile:

Ein ganz großes Dankeschön ans Forum und besonders an postmaster-ino und agmue für die Erklärungen.
Nach dem ich mir ein Stiff und Blattpapier zur Hilfe genommen habe und die ganzen If´s "übersetzt habe.
Denke habe ich es nun soweit...

Zeit fürs nächste Projekt. ;D

Danke für die Hilfe!!