Arraystructs oder doch anders - Wordclock

Guten Tag zusammen,

bei meinem Projekt zu einer Wordclock habe ich meinen Code nun schon ein paar mal überarbeitet. Hat etwas gedauert, da ich bisher immer nur sehr gelegentlich programmiere. Möchte mich dennoch immer gerne verbessern und würde deshalb gerne eure Meinung zu meiner derzeitigen Version, und Verbesserungsvorschläge, erfahren.

Für die Wordclock sollen, wie vielleicht bekannt, bestimmte LED´s angesteuert werden. Für die Stunden und Minuten war es bisher recht sauber und übersichtlich. Was nicht sehr effizient war, war die Zuordnung der Wörter zu den jeweiligen Zeiten.

Im alten Code sah es in etwa so aus:

  //UpdateWords - 5er-Schritte

  byte x = rtc_minutes_new / 5;

  if(x == 1 || x ==  5 || x == 7 || x == 11) { OutputTime(Words[fuenf_vn]  ); } //Es ist "fünf nach/vor", fünf vor/nach halb.
  if(x == 2 || x == 10)                      { OutputTime(Words[zehn_vn]   ); } //Es ist zehn vor/nach.

im aktuellem so:

struct Time_Words {
  byte trigger_size;
  byte trigger[5];
  byte led_size;
  byte led[7];
};
  //100 = immer an
Time_Words Words[] = {
  { 1, { 100                }, 2, { 0, 1                       }}, //es
  { 1, { 100                }, 3, { 3, 4, 5                    }}, //ist
  { 1, { 0                  }, 4, { 99, 100, 101               }}, //uhr
  { 4, { 10, 15, 20, 35     }, 4, { 33, 34, 35, 36             }}, //nach
  { 5, { 25, 40, 45, 50, 55 }, 3, { 41, 42, 43                 }}, //vor
  { 3, { 25, 30, 35         }, 4, { 44, 45, 46, 47             }}, //halb
  { 2, { 15, 45             }, 7, { 26, 27, 28, 29, 30, 31, 32 }}, //viertel_vn
  { 2, { 20, 40             }, 7, { 11, 12, 13, 14, 15, 16, 17 }}, //zwanzig_vn
  { 4, { 5, 25, 35, 55      }, 4, { 7, 8, 9, 10                }}, //fuenf_vn
  { 2, { 10, 50             }, 4, { 18, 19, 20, 21             }}  //zehn_vn
 };

void setup() {

}

void loop() {


 }

void CalcOutput() {
//Words
  byte minutes = 7;      //Bsp. - zum testen
  byte &x = minutes;    //Bsp. - zum testen

  for (byte i = 0; i <= sizeof Words/sizeof Words[0]; i++) {
    for (byte j = 0; j <= Words[i].trigger_size; j++) {
      if (Words[i].trigger[j] == x || Words[i].trigger[j] == 100) {
          UpdateClock(Words[i].trigger[j]);
        } else {
          break;
        }
      } 
    }
 }
void UpdateClock(const byte& led) { //Möglicherweise eine Anpassung von "const byte&" zu "const Time_Words& word" nötig
  pixels.setPixelColor(led, pixels.Color(100, 100, 100));
 }

DIe "trigger" sind die Wörter die zur jeweiligen Uhrzeit ausgegeben werden sollen. Denke der Rest ist selbsterklärend. Sonst bitte fragen.

Danke & Gruß :slight_smile:

für mich sieht es so aus als würdest du nun zwei Angaben in deinem Struct verschränken:

  • Wie ein Wort gebildet wird
  • Bei welchen Minuten welches Wort angezeigt werden soll.

*)

Ich würde das nicht kombinieren und getrennt lassen.
Dann kannst auch einfacher verschiedene "Versionen" der Textausgaben realisieren.

Wenn dir dein jetztiger Code mit den if (a || b || C) nicht gefällt, dann kannst du das ja in ein array geben.
Andererseits musst doch zugeben, das ist doch gut lesbar - und damit einfach wartbar.

*) Außerdem definierst du dir einen magic number 100. Andererseits gibst du redundant die Länge der genutzten Pixel und die jeweilgen Pixel an. Da hätte ich eher eine Magic-Number für ein nicht genutztes Pixel verwendet und mir die Längenangabe gespart.

Geht Deine Uhr bei Minute 11, 16, 21, 26 .... in Betrieb, hast Du ein Problem.

Ich halte das für zu aufwändig.
Mach ein switch/case mit range und fertig.

Hallo noiasca,

danke erst einmal!

Deine erste Aussage kann ich nicht ganz nachvollziehen. Die Wörter sollen immer gleich gebildet werden, nur eben in einer anderen Kombination. Das Wort "vor" benötige ich bspw. bei fünf vor/nach, viertel vor/nach usw.

Die erste Schleife geht dann alle Zeilen durch und schaut in jeder, ob der aktuelle Wert, in der jeweiligen Zeile, in der Spalte trigger gelistet ist. Ist der Wert nicht vorhanden, soll die nächste Zeile untersucht werden. Damit keine Leerstellen durchsucht werden, habe ich ja die Größen der Arrays angegeben, bzw. die Anzahl der Elemente.

Das sollte eigentlich kein Problem sein. Das Array und die Schleifen sind auch noch nicht 100%ig aufeinander abgestimmt.

Es geht mir nur um die Struktur/Logik...

Meinst du bzgl. der Switch-Cases, dass ich für jeden Case mehrere Werte angeben sollte, und die in einem Array stehen könnten?

Klingt gut. Hatte bisher nicht darüber nachgedacht. Wird dann aber auch wieder größer, oder? Dafür vermutlich übersichtlicher.

Meinst du mit der MagicNumber, dass da dann aufgehört werden soll zu zählen?

{{ 10, 50, 100 }, { 18, 19, 20, 21, 100 }} //zehn_vn

Da hatte ich tatsächlich auch drüber nachgedacht. Fand es aber irgendwie doof. Viellelcht ja unberechtigt. Ein großes Argument wäre wahrscheinlich, dass die schleife wesentlich unkomplizierter/übersichtlicher wäre?!

100 wird hier aber für´s dauerhafte schalten genutzt.

Aber danke noch einmal! :slight_smile:

Ok, dann bin ich sowieso falsch.
Meine Uhrsprache ist eine andere. Ich kenne kein 20 vor/nach - da gehts dann mit der Logik bei mir nicht :slight_smile:

Ich würde das ganz einfach bauen:

  switch (minute)
  {
    case  3 ...  7:  // 5 nach um
    case 23 ... 27:  // 5 vor halb
    case 33 ... 37:  // 5 nach halb
    case 53 ... 57:  // 5 vor um
      fuenf();
      break;
    case  8 ... 12:  // 10 nach um
    case 18 ... 22:  // 10 vor halb
    case 38 ... 42:  // 10 nach halb
    case 48 ... 52:  // 10 vor um
      zehn();
      break;
    case 13 ... 17:  // viertel nach
    case 43 ... 47:  // viertel vor
      viertel();
      break;
    case 28 ... 32:
      halb();
      break;
    case 0 ... 2:
    case 58 ... 60:
      um();
  }

  switch (minute)
  {
    case 3...12:  // 5 & 10 nach um
    case 33...42: // 5 & 10 nach halb
      nach();
      break;
    case 18 ... 27: // 5 & 10 vor halb 
    case 48 ... 57: // 5 & 10 vor um
      vor();
      break;
  }

und dann die jeweiligen Funktionen zum füllen...

Danke für deine Mühe. Aber das ist doch total viel Arbeit...
Geht es nicht gerade darum in der Programmierung, effizient zu sein. Also dass sich Codezeilen nicht 100fach wiederholen?

Naja, der Weg ist das Ziel :wink:
Ich greife dafür jede Minute ab.
Wenn davor geprüft wird, ob die aktuelle Minute != der letzten Minute ist, schreib ich genau 1x je Minute und bekomme alle Zeiten.
Es gibt keine Codedopplungen und keine MagicNumbers.

ich habe dein Code Ansinnen schon verstanden.
Aber mir gefällt eben die Kombination Trigger --> Pixel des Wortes nicht.

so, oder ich hätte halt die nicht genutzten Pixel auf eine Konstante, z.B. uu für unused

aber wie gesagt, ich würde die Minuten trigger und Pixel eben nicht in eine Struktur packen.

alles mit Augenmaß. Lieber ein lesbarer Switch-case als mehrere for-Schleifen die man in 6 Monaten nicht mehr durchblickt.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.