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;
}
};