Durch eine Struktur iterieren

Ich weis nicht wie ich mich am geschicktesten ausdrücken soll. Vielleicht zeigt das Beispiel, was natürlich einen Fehler in Zeile 17 wirft, was ich versuche.

struct rgb_color {
  byte red;
  byte green;
  byte blue;
};

rgb_color color {0,0,0};

byte farbe[] {0,0,0};

void setup() {
  Serial.begin(74400);
}

void loop() {
  for(auto &i : color){
    i++;
  }
  Serial.print(color.red); Serial.print(", "); Serial.print(color.green); Serial.print(", "); Serial.println(color.blue);
  delay(1000);
  
  for(auto &i : farbe){
    i++;
  }
  Serial.print(farbe[0]); Serial.print(", "); Serial.print(farbe[1]); Serial.print(", "); Serial.println(farbe[2]);

  delay(1000);
}

Bei einem Array kann man schön auf jedes Element zugreifen, und für jedes Element ein und die selbe Rechenoperation oder Funktion ausführen.
Dies würde ich auch gern, bei einer Struktur können. Aber dies scheint nicht zu funktionieren, vermutlich auch dem Grund geschuldet, da der Inhalt einer Struktur selten aus nur ein und dem selben Datentyp besteht.
Ziel ist es eine RGB Farbe, dessen drei Werte in einer Struktur stecken, gemeinsam zu beeinflussen. Zum Beispiel dekrementieren der Werte, um ein dimmen zu Erreichen.

Bisher ist es so, das der relativ gleiche Code sich immer dreimal wiederholt. Sieht irgendwie bescheiden aus. Mal ein Ausschnitt aus dem großen Code

  rgb_color temporary = colorClockPoints;
  if(temporary.red){
    temporary.red = (uint16_t)temporary.red * WS2812.getBrightness()/100;
    if(temporary.red < 3) temporary.red = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.green){
    temporary.green = (uint16_t)temporary.green * WS2812.getBrightness()/100;
    if(temporary.green < 3) temporary.green = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.blue){
    temporary.blue = (uint16_t)temporary.blue * WS2812.getBrightness()/100;
    if(temporary.blue < 3) temporary.blue = 3 * 100 / WS2812.getBrightness();
  }

Wenn man dies mit einer for-Schleife erschlagen könnte, das es sich nicht dreimal wiederholt, wäre irgendwie schöner.

Ich hoffe, es ist verständlich was ich will.

Danke

Da hast du vollkommen Wahr!

Was du aber tun könntest, damit sowas auch mit Strukturen gültig wird:

Du könntest die Inkrement Operatoren in der Struktur definieren.

Ein kleines Beispiel dazu?

Dies würde dann wahrscheinlich nur eine Möglichkeit erschlagen. Funktionen könnte man so wahrscheinlich nicht erschlagen. Beispiel an einem Array.

enum {red,green,blue};
byte farbe[] {1,3,2};

void setup() {
  Serial.begin(74400);
}

void loop() {
  for(auto &i : farbe){
    i = doubleTheValue(i);
  }
  Serial.print(farbe[red]); Serial.print(", "); Serial.print(farbe[green]); Serial.print(", "); Serial.println(farbe[blue]);

  delay(1000);
}

byte doubleTheValue(byte i){
  return i *= 2;
}
  1. Operatoren sind auch nur Methoden/Funktionen
  2. das gilt auch für den *= Operator

Schaue mal in die EEROM Lib, oder ein beliebiges modernes C++ Grundlagenbuch

Es geht in diese Richtung, habe ich das richtig verstanden?

Geht wie folgt;

struct rgb_color {
  byte red;
  byte green;
  byte blue;
  operator++(){
    red++;
    green++;
    blue++;
  }
};

rgb_color color {0,0,0};

byte farbe[] {0,0,0};

void setup() {
  Serial.begin(74400);
}

void loop() {
  color++;
  Serial.print(color.red); Serial.print(", "); Serial.print(color.green); Serial.print(", "); Serial.println(color.blue);
    delay(1000);
}
1 Like

Das würde im Endeffekt aber auch nur die "dreifachen" Codezeilen in die Struktur verschieben.

struct rgb_color {
  byte red;
  byte green;
  byte blue;
  void doubleTheValue(){
    red   *= 2;
    green *= 2;
    blue  *= 2;
  }
};

rgb_color color {1,3,2};


void setup() {
  Serial.begin(74400);
}

void loop() {
  color.doubleTheValue();
  Serial.print(color.red); Serial.print(", "); Serial.print(color.green); Serial.print(", "); Serial.println(color.blue);
  delay(1000);
}

Was getan werden muss, muss getan werden.

Dass du deinen Wunschtraum " über eine Struktur iterieren" vergessen kannst, weißt du ja schon.

1 Like

Naja, um das dedizierte Bearbeiten der unterschiedlichen Anteile einer Struktur an einer Stelle im Code kommst Du nicht herum. Aber Du kannst den Operator natürlich zig-fach im Sketch einsetzen. ohne dort aufwendig selbst etwas zu schreiben ...

Danke euch beiden. Jetzt habe ich wieder einen Ansatzpunkt, um es vielleicht übersichtlicher zu gestallten.

Hier noch auf die Schnelle (kann combie natürlich besser :wink: ):

/*
  Forum: https://forum.arduino.cc/t/durch-eine-struktur-iterieren/1202648
  Wokwi: https://wokwi.com/projects/384755631147214849
*/
struct rgb_color {
    byte red;
    byte green;
    byte blue;
    uint16_t _brightness;
    operator++() {
      red++;
      green++;
      blue++;
    }
    operator--() {
      changeColor(red);
      changeColor(green);
      changeColor(blue);
    }
    void setBrightness(uint8_t br) {
      if (br > 0) {
        _brightness = br;
      }

    }
  private:
    changeColor(byte &col) {
        col  = (uint16_t)col * _brightness / 100;
        if (col < 3) {
          col  = 3 * 100 / _brightness;
      }
    }
};

rgb_color color {32, 64, 128, 255};

byte farbe[] {0, 0, 0};

void setup() {
  Serial.begin(74400);
  color.setBrightness(128);
}

void loop() {
  color--;
  Serial.print(color.red); Serial.print(", "); Serial.print(color.green); Serial.print(", "); Serial.println(color.blue);
  delay(1000);
}

/*
  rgb_color temporary = colorClockPoints;
  if(temporary.red){
    temporary.red = (uint16_t)temporary.red * WS2812.getBrightness()/100;
    if(temporary.red < 3) temporary.red = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.green){
    temporary.green = (uint16_t)temporary.green * WS2812.getBrightness()/100;
    if(temporary.green < 3) temporary.green = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.blue){
    temporary.blue = (uint16_t)temporary.blue * WS2812.getBrightness()/100;
    if(temporary.blue < 3) temporary.blue = 3 * 100 / WS2812.getBrightness();
  }

*/

Mit dem --Operator kannst Du dann in etwa das aufrufen, was Du mit den Farben machen wolltest, die Funktion steht nur einmal in der Struktur und wird im --Operator für die drei Farbanteile getrennt aufgerufen. Da Du eine Division durch getBrightness() in der Berechnung hast, muss man aufpassen, dort keine Null geliefert zu bekommen. Dafür habe ich mal eine interne Variable eingesetzt, die man von außen nur durch color.setBrightness() ändern sollte, da diese Funktion die Null abfängt ...

Richtig schön noch nicht, aber vielleicht ein Weg in die gewünschte Richtung ....

Zum Ausprobieren: https://wokwi.com/projects/384755631147214849

Das kann ich nicht garantieren.

Aber doch: Danke für die Blumen!

Ich kann garantieren, das ihr beide es viel besser könnt als ich!
Und tausend Danke für euer Ehrenamtliches helfen!

Das alles ist natürlich, wie immer, komplexer. Daher ja auch das bestreben es übersichtlicher und verständlicher (vor allem für mich) zu machen. Es kam schon vor das ich nach ein par Monaten Pause vor meinem Code saß und mich fragte, was hast du da eigentlich gemacht.

Es ist eine Uhr mit 200 Pixel SK9822 EC20 und 60 Pixel WS2812b. Die Helligkeit wird in den Klassen dafür einmalig gehalten. Jetzt jedem Pixel einen eigenen Helligkeitswert mit abzuspeichern, würde den Speicher mal um ganze 260 Bytes mit mehr strapazieren.

Hinzu kommt, das die Helligkeit der SK9822 Pixel schon für dir drei Farben extra gehalten werden, also 3 Bytes, um unterschiedlich helles Erscheinen von 100% Rot, 100% Grün und 100% Blau auf ein einheitliches erscheinen zu dimmen.

Ein liebevoller LDR beeinflusst die Helligkeit. Dann gibt es Pixel die nur Markierungen repräsentieren, und daher von Haus aus schon dunkler sein sollen.

Jetzt kam es zu dem Effekt, das beim abnehmen des Umgebungslichtes, und das reduzieren der Leuchtkraft der Pixel, damit sie nicht so blenden, die "Markierungspixel" einfach aus gingen, da der Mindestleuchtwert unterschritten wurde. Also die Idee, die Grundfarbe, multipliziert mit der vom LDR beeinflussten Helligkeit, zu prüfen, ob der Mindestleuchtwert unterschritten wird, und sie in diesem Fall auf den Mindestleuchtwert zu setzen.

Ja, ein Fall auf Helligkeit 0 müsste noch abgefangen werden. Wird aber eigentlich schon bei der Beeinflussung vom LDR abgefangen. Er setzt sie auf mindestens 1.

Funktionieren tut es ja inzwischen so wie es soll. Nur übersichtlicher sollte es noch werden. Es gibt noch einige Stellen die mir absolut nicht gefallen, aber eins nach dem anderen. Und wäre dann ja auch Off-Topic.


Uhr.ino

/*  WEMOS D1 mini PINOUT
 *  D0=GPIO16 Wake   Gibt beim Booten einen HIGH Impuls aus.
 *  D1=GPIO5  SCL    Normaler I/O Pin, frei verfügbar
 *  D2=GPIO4  SDA    Normaler I/O Pin, frei verfügbar
 *  D3=GPIO0         LOW beim Booten aktiviert Firmware-Upload, muss zum normalen Start offen sein oder schwach auf HIGH gezogen werden. Gibt beim Booten LOW Impulse aus. Hat einen 10 kΩ Pull-Up Widerstand.
 *  D4=GPIO2         Beim Booten serieller Ausgang, darf dabei nicht auf LOW gezogen werden. Kann nach dem Booten als normaler I/O Pin verwendet werden. Alle außer Mini v2 haben eine blaue LED, die bei LOW Pegel leuchtet. Hat 10 kΩ Pull-Up Widerstand.
 *  D5=GPIO14 SCK    Wird beim Booten schwach auf HIGH gezogen.
 *  D6=GPIO12 MISO   Wird beim Booten schwach auf HIGH gezogen.
 *  D7=GPIO13 MOSI   Wird beim Booten schwach auf HIGH gezogen.
 *  D8=GPIO15 SS     Muss beim Booten auf LOW gezogen werden. Hat 10 kΩ Pull-Down Widerstand
 *  TX=GPIO1         Beim Booten serieller Ausgang, darf dabei nicht auf LOW gezogen werden. Kann nach dem Booten als normaler I/O Pin verwendet werden.
 *  RX=GPIO3         Serieller Eingang des ESP. Ist über 470 Ω mit dem USB-UART verbunden. Wird beim Booten schwach auf HIGH gezogen.
 */
 
#include "config.h"  // SSID, Password, IP, Hostname, Persitance Settings
#ifndef STASSID
#define STASSID "SSID"
#define STAPSK  "PASSWORD"
#endif

#define NTP_SERVER "fritz.box"           
#define TIMEZONE "CET-1CEST,M3.5.0,M10.5.0/3"   

#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
ESP8266WebServer server(80);

#include <time.h>

time_t now;                         // UNIX Zeit
tm tm;                              // Struktur mit Formatierten Werten
/*  Member    Type  Meaning Range
 *  tm_sec    int   seconds after the minute  0-61* *Schaltsekunden
 *  tm_min    int   minutes after the hour  0-59
 *  tm_hour   int   hours since midnight  0-23
 *  tm_mday   int   day of the month  1-31
 *  tm_mon    int   months since January  0-11
 *  tm_year   int   years since 1900
 *  tm_wday   int   days since Sunday 0-6
 *  tm_yday   int   days since January 1  0-365
 *  tm_isdst  int   Daylight Saving Time flag
 */

#include <Adafruit_NeoPixel.h>
constexpr byte WS2812NUM {61};
constexpr byte LED_PIN {5};
constexpr byte WS2812brightness {25};
constexpr byte clockpixelnumber[] = {23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
Adafruit_NeoPixel WS2812(WS2812NUM, LED_PIN, NEO_GRB + NEO_KHZ800);

#include "sk9822ec20.h"
constexpr byte SK9822current {1};                 // Stromeinstellung (1-10)
constexpr uint16_t SK9822NUM {200};               // Anzahl der Pixel
constexpr rgb_color colorDay{255,255,10};         // Farbe für Stunden
constexpr rgb_color colorMonth{255,255,10};       // Farbe für Stunden
constexpr rgb_color colorYear{255,255,10};        // Farbe für Stunden
constexpr rgb_color colorHour{255,10,10};         // Farbe für Stunden
constexpr rgb_color colorMinute{10,255,10};       // Farbe für Minuten
constexpr rgb_color colorSecond{10,10,255};       // Farbe für Sekunden
constexpr rgb_color colorSeparator{255,255,10};   // Farbe für Trennzeichen
constexpr rgb_color colorMark{50,50,0};           // Farbe für Binär Markierung
constexpr rgb_color colorClockPoints{50,50,0};    // Farbe der 5Min Punkte auf der Uhr
constexpr rgb_color SK9822brightness{10,7,30};                   // Prozent der Leuchtkraft (RGB)
SK9822EC20 SK9822(SK9822NUM, SK9822brightness, SK9822current);     // Anzahl LEDs, Helligkeit in Prozent (RGB), Strom(1-10)

#include <ArduinoOTA.h>

uint32_t timestampPixel;
constexpr uint16_t refreshPixel {100};

/* 100 Pixel pro Reihe
   ┌--┬--┬--┐┌--┬--┬--┐┌--┐┌--┬--┬--┐┌--┬--┬--┐┌--┐┌--┬--┬--┐┌--┬--┬--┐
   │95│94│85││80│79│70││69││60│59│50││45│44│35││34││25│24│15││10│09│00│
   │96│93│86││81│78│71││68││61│58│51││46│43│36││33││26│23│16││11│08│01│
   │97│92│87││82│77│72││67││62│57│52││47│42│37││32││27│22│17││12│07│02│
   │98│91│88││83│76│73││66││63│56│53││48│41│38││31││28│21│18││13│06│03│
   │99│90│89││84│75│74││65││64│55│54││49│40│39││30││29│20│19││14│05│04│
   └--┴--┴--┘└--┴--┴--┘└--┘└--┴--┴--┘└--┴--┴--┘└--┘└--┴--┴--┘└--┴--┴--┘
*/
/* ┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐
   │10│09│00││  │09│  ││10│09│00││10│09│00││10│  │00││10│09│00││10│09│00││10│09│00││10│09│00││10│09│00││10│09│00│
   │11│  │01││11│08│  ││  │  │01││  │  │01││11│  │01││11│  │  ││11│  │  ││  │  │01││11│  │01││11│  │01││11│08│01│
   │12│  │02││  │07│  ││  │07│  ││  │07│02││12│07│02││12│07│02││12│07│02││  │07│  ││12│07│02││12│07│02││12│07│02│
   │13│  │03││  │06│  ││13│  │  ││  │  │03││  │  │03││  │  │03││13│  │03││  │06│  ││13│  │03││  │  │03││13│06│03│
   │14│05│04││  │05│  ││14│05│04││14│05│04││  │  │04││14│05│04││14│05│04││  │05│  ││14│05│04││14│05│04││14│05│04│
   └--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘
   ┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐
   │  │09│  ││10│09│  ││  │09│  ││10│09│  ││10│09│00││10│09│00││  │09│00││10│  │00││  │09│  ││10│09│00││10│  │00│
   │11│  │01││11│  │01││11│  │01││11│  │01││11│  │  ││11│  │  ││11│  │  ││11│  │01││  │08│  ││  │  │01││11│  │01│
   │12│07│02││12│07│  ││12│  │  ││12│  │02││12│07│  ││12│07│  ││12│  │  ││12│07│02││  │07│  ││  │  │02││12│07│  │
   │13│  │03││13│  │03││13│  │03││13│  │03││13│  │  ││13│  │  ││13│  │03││13│  │03││  │06│  ││13│  │03││13│  │03│
   │14│  │04││14│05│  ││  │05│  ││14│05│  ││14│05│04││14│  │  ││  │05│04││14│  │04││  │05│  ││  │05│  ││14│  │04│
   └--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘
   ┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐
   │10│  │  ││10│  │00││10│  │00││  │09│  ││10│09│  ││  │09│  ││10│09│  ││  │09│00││10│09│00││10│  │00││10│  │00│
   │11│  │  ││11│08│01││11│08│01││11│  │01││11│  │01││11│  │01││11│  │01││11│  │  ││  │08│  ││11│  │01││11│  │01│
   │12│  │  ││12│07│02││12│07│02││12│  │02││12│07│  ││12│  │02││12│07│  ││  │07│  ││  │07│  ││12│  │02││12│  │02│
   │13│  │  ││13│  │03││13│06│03││13│  │03││13│  │  ││13│  │03││13│  │03││  │  │03││  │06│  ││13│  │03││  │06│  │
   │14│05│04││14│  │04││14│  │04││  │05│  ││14│  │  ││  │05│04││14│  │04││14│05│  ││  │05│  ││  │05│  ││  │05│  │
   └--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘
   ┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐┌--┬--┬--┐
   │10│  │00││10│  │00││10│  │00││10│09│00│
   │11│  │01││11│  │01││11│  │01││11│  │  │
   │12│07│02││  │07│  ││12│07│02││  │07│  │
   │13│06│03││13│  │03││  │06│  ││  │  │03│
   │14│  │04││14│  │04││  │05│  ││14│05│04│
   └--┴--┴--┘└--┴--┴--┘└--┴--┴--┘└--┴--┴--┘

*/
enum Separator {Off, Dot, Colon, Mark};
enum Type {Date, Time, Value};
enum Format {Digit, Binary};
constexpr uint8_t numDigitPixel {15};
constexpr uint8_t numSeparatorPixel {5};
constexpr uint8_t digitPos[] = {85,70,50,35,15,0,185,170,150,135,115,100};
constexpr uint8_t separatorPos[] = {65,30,165,130};
constexpr uint16_t digit[] = {0b111111000111111, // 0
                              0b000101111100000, // 1
                              0b110011010110011, // 2
                              0b100011010111111, // 3
                              0b001110010011111, // 4
                              0b101111010111101, // 5
                              0b111111010111101, // 6
                              0b000011011100011, // 7
                              0b111111010111111, // 8
                              0b101111010111111, // 9
                              0b111111010011111, // A
                              0b111111010111011, // B
                              0b111111000111011, // C
                              0b111111000101110, // D
                              0b111111010110001, // E
                              0b111111010000001  // F
                              };

uint16_t LDRvalue {0};
constexpr uint16_t maxLDRvalue {600};  // 100% Leuchtkraft Tags
constexpr uint16_t minLDRvalue {100};  // 10% Leuchtkraft Nachts

void setup() {
  pinMode(2,OUTPUT);
  digitalWrite(2,HIGH);
  WS2812.begin();
  WS2812.show();
  WS2812.setBrightness(WS2812brightness);
  configTime(TIMEZONE, NTP_SERVER);
  setWifi();                              // -> config.h
  WiFi.begin(STASSID, STAPSK);
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
  }
  SPI.begin();
  ArduinoOTA.setHostname(Hostname);
  ArduinoOTA.begin();
  
  // -> server.ino
  server.onNotFound(handleNotFound);
  server.on("/",      handleRoot);               // send root page
  server.on("/0.htm", handleRoot);               // a request can reuse another handler
  server.on("/f.css", handleCss);                // a stylesheet                                             
  server.on("/j.js",  handleJs);                 // javscript based on fetch API to update the page
  server.on("/json",  handleJson);               // send data in JSON format
  
  server.begin();  
}

void loop() {
  ArduinoOTA.handle();
  server.handleClient();
  if(millis()-timestampPixel > refreshPixel){
    LDRvalue=analogRead(A0);
    setLDRBrightness(LDRvalue);       // Helligkeit setzen
    time(&now);                       // liest die Zeit
    localtime_r(&now, &tm);           // aktualisiert die Struktur   
    clockPixel();                     // WS2812b Ring ansteuern
    //writeRow(0,Time,DEC,Binary);      // Schreibe Reihe: Welche (0, 1), Was (Date, Time, Value(max. 6Digit)), Zahlensystem (HEX, DEC, OCT), Anzeigeformat (Digit, Binary)
    writeRow(0,Value,DEC,Digit);
    writeRow(1,Time,DEC,Digit);
    WS2812.show();                    
    SK9822.show();
    timestampPixel = millis();
  }
}

void writeRow(byte row, Type type, size_t numerative, Format form){ // Schreibe Reihe: Welche (0, 1), Was (Date, Time), Zahlensystem (HEX, DEC, OCT), Anzeigeformat (Digit, Binary)
  uint16_t temp = WS2812.getBrightness();                                         // Wert für Type Value zuweisen, Debug
  if(numerative < 6) return;                                        // nicht darstellbar auf 2 Stellen 
  struct ValueAndColor{
    byte value = 0;
    rgb_color color = colorSeparator;
  } valueAndColor[6];
  switch (type){
    case Date: valueAndColor[0].value=tm.tm_mday/numerative;
               valueAndColor[0].color=colorDay;
               valueAndColor[1].value=tm.tm_mday%numerative;
               valueAndColor[1].color=colorDay;
               valueAndColor[2].value=(tm.tm_mon+1)/numerative;
               valueAndColor[2].color=colorMonth;
               valueAndColor[3].value=(tm.tm_mon+1)%numerative;
               valueAndColor[3].color=colorMonth;
               valueAndColor[4].value=(tm.tm_year-100)/numerative;
               valueAndColor[4].color=colorYear;
               valueAndColor[5].value=(tm.tm_year-100)%numerative;
               valueAndColor[5].color=colorYear;
               writeSeparator(Dot,separatorPos[0+row*2],colorSeparator);
               writeSeparator(Dot,separatorPos[1+row*2],colorSeparator);
               break;
    case Time: valueAndColor[0].value=tm.tm_hour/numerative;
               valueAndColor[0].color=colorHour;
               valueAndColor[1].value=tm.tm_hour%numerative;
               valueAndColor[1].color=colorHour;
               valueAndColor[2].value=tm.tm_min/numerative;
               valueAndColor[2].color=colorMinute;
               valueAndColor[3].value=tm.tm_min%numerative;
               valueAndColor[3].color=colorMinute;
               valueAndColor[4].value=tm.tm_sec/numerative;
               valueAndColor[4].color=colorSecond;
               valueAndColor[5].value=tm.tm_sec%numerative;
               valueAndColor[5].color=colorSecond;
               writeSeparator(Colon,separatorPos[0+row*2],colorSeparator);
               writeSeparator(Colon,separatorPos[1+row*2],colorSeparator);
               break;
    case Value:valueAndColor[0].value=(temp/numerative/numerative/numerative/numerative/numerative)%numerative;
               valueAndColor[0].color=colorDay;
               valueAndColor[1].value=(temp/numerative/numerative/numerative/numerative)%numerative;
               valueAndColor[1].color=colorDay;
               valueAndColor[2].value=(temp/numerative/numerative/numerative)%numerative;
               valueAndColor[2].color=colorMonth;
               valueAndColor[3].value=(temp/numerative/numerative)%numerative;
               valueAndColor[3].color=colorMonth;
               valueAndColor[4].value=(temp/numerative)%numerative;
               valueAndColor[4].color=colorYear;
               valueAndColor[5].value=temp%numerative;
               valueAndColor[5].color=colorYear;
               writeSeparator(Off,separatorPos[0+row*2],colorSeparator);
               writeSeparator(Off,separatorPos[1+row*2],colorSeparator);
               break;
    default: return;
  }
  if(form==Binary){
    writeSeparator(Mark,separatorPos[0+row*2],colorMark);
    writeSeparator(Mark,separatorPos[1+row*2],colorMark);
  }
  for(uint8_t i=0; i<6; i++){
    switch(form){
      case Digit:  writeDigit(valueAndColor[i].value, digitPos[i+row*6], valueAndColor[i].color);
                   break;
      case Binary: writeBin(valueAndColor[i].value, digitPos[i+row*6], valueAndColor[i].color);
                   break;
      default: return;
    }
  }
}

void writeDigit(uint8_t number, uint8_t startPixel, rgb_color color){
  if(number>sizeof(digit)/sizeof(digit[0])-1) return;   // Begrenzen auf vorhande Zeichen
  for(uint8_t i=0; i<numDigitPixel; i++){
    bitRead(digit[number],i) ? SK9822.setPixelColor(startPixel+i,color) : SK9822.setPixelColor(startPixel+i,0,0,0);
  }
}

void writeSeparator(Separator type, uint8_t startPixel, rgb_color color){
  switch (type){
    case Off: 
      for(uint8_t i=0; i<numSeparatorPixel; i++) {
        SK9822.setPixelColor(startPixel+i,0,0,0);
      }
      break;
    case Dot:
      SK9822.setPixelColor(startPixel+0,color);
      break;
    case Colon:
      SK9822.setPixelColor(startPixel+1,color);
      SK9822.setPixelColor(startPixel+3,color);      
      break;   
    case Mark:
      for(uint8_t i=0; i<numSeparatorPixel; i++){
        SK9822.setPixelColor(startPixel+i,color);   
      }
      break;
  }
}

void writeBin(uint8_t number, uint8_t startPixel, rgb_color color){
  // 10 09 00
  // 11 08 01
  // 12 07 02
  // 13 06 03
  // 14 05 04
  constexpr byte digitRow[] = {4,5,14,3,6,13,2,7,12,1,8,11,0,9,10};                                           // Pixel Reihe für Reihe
  for(uint8_t i=0; i<5; i++){                                                                                 // für jede der 5 Reihen
    for(uint8_t j=0; j<3; j++){                                                                               // für drei Pixel nebeneinander
      if(digitRow[i*3+j]<sizeof(digitRow))                                                                    // prüfen ob das Element im Array existiert
        bitRead(number,i) ? SK9822.setPixelColor(digitRow[i*3+j]+startPixel,color)                            // wenn das Bit gesetzt, setze das Pixel
        : SK9822.setPixelColor(digitRow[i*3+j]+startPixel,SK9822.getPixelColor(digitRow[i*3+j]+startPixel));  // sonst lese den letzten Wert des pixels und schreibe ihn (durch abrunden leichtes Fadeout)
    }
  }
}

void clockPixel(){
  byte WS2812hour = tm.tm_hour;
  byte WS2812min = tm.tm_min;
  byte WS2812sec = tm.tm_sec;
  for(byte i=0; i<60; i++){     // Ausfaden gesetzter Pixel
    WS2812.setPixelColor(clockpixelnumber[i],getPixelColorRed(clockpixelnumber[i])*0.7,getPixelColorGreen(clockpixelnumber[i])*0.7,getPixelColorBlue(clockpixelnumber[i])*0.7);
  }
  rgb_color temporary = colorClockPoints;
  if(temporary.red){
    temporary.red = (uint16_t)temporary.red * WS2812.getBrightness()/100;
    if(temporary.red < 3) temporary.red = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.green){
    temporary.green = (uint16_t)temporary.green * WS2812.getBrightness()/100;
    if(temporary.green < 3) temporary.green = 3 * 100 / WS2812.getBrightness();
  }
  if(temporary.blue){
    temporary.blue = (uint16_t)temporary.blue * WS2812.getBrightness()/100;
    if(temporary.blue < 3) temporary.blue = 3 * 100 / WS2812.getBrightness();
  }
  for(byte i=0; i<60; i+=5){    // Stundenmarkierung setzen
    WS2812.setPixelColor(clockpixelnumber[i],temporary.red,temporary.green,temporary.blue);    // Farbe statisch unabhängig der Helligkeit / 3 ist Mindestwert damit ein Pixel leuchtet.
  }
  if(WS2812hour >=12){          // von 24 Stunden auf 12 Stunden wandeln
    WS2812hour = tm.tm_hour - 12;
  }
  WS2812hour = WS2812hour * 5 + WS2812min / 12;  // Position Stunden Zeiger berechnen
  if(WS2812hour < WS2812NUM) WS2812.setPixelColor(clockpixelnumber[WS2812hour],colorHour.red,colorHour.green,colorHour.blue); 
  if(WS2812min < WS2812NUM) WS2812.setPixelColor(clockpixelnumber[WS2812min],colorMinute.red,colorMinute.green,colorMinute.blue);
  if(WS2812sec < WS2812NUM) WS2812.setPixelColor(clockpixelnumber[WS2812sec],colorSecond.red,colorSecond.green,colorSecond.blue);
}

byte getPixelColorRed(byte pixel){
  uint32_t value = WS2812.getPixelColor(pixel);
  value = value << 8;
  value = value >> 24;
  return value;
}
byte getPixelColorGreen(byte pixel){
  uint32_t value = WS2812.getPixelColor(pixel);
  value = value << 16;
  value = value >> 24;
  return value;
}
byte getPixelColorBlue(byte pixel){
  uint32_t value = WS2812.getPixelColor(pixel);
  value = value << 24;
  value = value >> 24;
  return value;
}

void setLDRBrightness(uint16_t LDRvalue){
  float value = map(constrain(LDRvalue,minLDRvalue,maxLDRvalue),minLDRvalue,maxLDRvalue,10,100)/100.0;  // Wert 0.1 bis 1.0 für 10 bis 100%
  rgb_color brightnessLDR = SK9822brightness;
  brightnessLDR.red = constrain(brightnessLDR.red*value,1,100);      
  brightnessLDR.green = constrain(brightnessLDR.green*value,1,100);  
  brightnessLDR.blue = constrain(brightnessLDR.blue*value,1,100);    
  SK9822.setBrightness(brightnessLDR);
  WS2812.setBrightness(constrain(WS2812brightness*value,1,100));
}

sk9822ec20.h

#pragma once
#include <Arduino.h>
#include <SPI.h>

struct rgb_color {
  byte red;
  byte green;
  byte blue;
};

class SK9822EC20 {
private:
    byte current {1};                           // Stromeinstellung Default
    byte currentRegisterByte = current | 0b11100000;
    uint16_t NUM;                               // Variable für die Anzahl der LEDs
    rgb_color *pixel;                           // Zeiger auf den Anfang des Array für die Farbwerte der LEDs
    rgb_color brightness{100,100,100};          // Prozent der Leuchtkraft Default
    
    //private Methoden
    void startFrame(){                          // benötigt 32 0Bits
      for (uint8_t i = 0; i < 4; i++){          // 4 mal 8Bit â 2 Flanken (4*8*2) = 64 Flanken
        SPI.transfer(0);                        // sendet 16 Flanken, mit bleibenden 0 Datenpegel
      }
    }
    void sendColor(struct rgb_color color){     // schreibt die Werte des Pixels
      SPI.transfer(currentRegisterByte);
      SPI.transfer(color.blue);
      SPI.transfer(color.green);
      SPI.transfer(color.red);
    }
    void endFrame(){                            // Zum aktualiesieren muß pro LED eine Flanke (steigend oder fallend) eines 0Bits gesendet werden.  
      for (uint16_t i = 0; i < NUM; i+=16){     // pro Pixel eine Flanke. 8Bit = 16 Flanken
        SPI.transfer(0);                        // sendet 16 Flanken, mit bleibenden 0 Datenpegel
      }
    }
    
public:
    //Constructors
    SK9822EC20(uint16_t NUM, rgb_color brightness, byte current){
      this->NUM = NUM;
      this->current = constrain(current,1,10);
      currentRegisterByte = this->current | 0b11100000; 
      this->brightness = brightness;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    SK9822EC20(uint16_t NUM, rgb_color brightness){
      this->NUM = NUM;
      this->brightness = brightness;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    SK9822EC20(uint16_t NUM){
      this->NUM = NUM;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    
    //Dekonstruktor
    ~SK9822EC20(){
      free(pixel);
    }
    
    //Öffentliche Methoden
    void show(){                                // Schiebt alle Daten raus
      SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));      // Beginnt Übertragung
      startFrame();                             // 32 0Bits
      for(uint16_t i = 0; i < NUM; i++){        // Für jedes Pixel
        sendColor(pixel[i]);                    // Farbwert Rot, Grün, Blau
      }
      endFrame();                               // Aktualisiert die Pixel, abhängig der Anzahl der LEDs
      SPI.endTransaction();                     // Beendet Übertragung
    }
    rgb_color getPixelColor(uint16_t NUM){
      return pixel[NUM];
    }
    void setPixelColor(uint16_t NUM, byte red, byte green, byte blue){
      if(this->NUM < NUM) return;
      rgb_color color {red, green, blue};
      setPixelColor(NUM, color);
    }
    void setPixelColor(uint16_t NUM, rgb_color color){
      if(this->NUM < NUM) return;
      pixel[NUM].red = uint16_t(uint16_t(color.red)*uint16_t(brightness.red)/100);
      pixel[NUM].green = uint16_t(uint16_t(color.green)*uint16_t(brightness.green)/100);
      pixel[NUM].blue = uint16_t(uint16_t(color.blue)*uint16_t(brightness.blue)/100);
    }
    void setBrightness(rgb_color brightness){
      this->brightness = brightness;
    }

    rgb_color getBrightness(){
      return brightness;
    }
    
    byte getCurrent(){
      return current;
    }
    void setCurrent(uint8_t current){
      this->current = constrain(current,1,10);
      currentRegisterByte = this->current | 0b11100000; 
    }    
};

Du kannst für die Brightness natürlich auch eine globale Variable spendieren, die Du besser kontrollieren kannst, als den externen Aufruf. Oder besser: Du kannst die Klasse auch so anpassen, dass das komplette Array Teil der Klasse wird. Dann lässt sich alles in darin abarbeiten...

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