WS2812 - Farbe in Variable speichern

Hallo Leute,

ich habe ein Problem womit ich nicht weiterkomme. Vielleicht könnt ihr mir ja dabei helfen.

Ich habe eine 10x10 große Matrix aus WS2812 RGB LED's in einem Raster unter einer Plexiglasplatte. In jedem Kästchen befindet sich eine Platine (also insgesamt 100 Stk.) mit einer RGB LED, einer IR LED und einem IR Detektor. Ich möchte ein "Malprogramm" schreiben. Man wählt also eine Farbe aus indem man ein Kästchen in der untersten Reihe mit der gewünschten Farbe berührt. Jetzt soll diese Farbe gespeichert werden und nun alle Kästchen welche ich berühre in der Farbe färben die ich ausgewählt hatte.
Die Frage ist bei mir wie ich die Farbe in einer Variable speichern kann und so den andere LED's diese Farbe auch zuweisen kann.

Der Code sieht bis jetzt so aus:

#include <Wire.h>
#include <Centipede.h>

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>

Centipede CS;

// Grundeinstellung

#define PIN            7

#define NUMPIXELS      100

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval1 = 1;


const byte touchSensor1 = 1; //CS.portRead(1);
const byte touchSensor2 = 2;
const byte touchSensor3 = 3;
...
const byte touchSensor100 = 100;

// ----------------------------------------------------------------------------------------------------

void setup() {
  
  
  // Bibliothekstart
  
  Wire.begin();
  
  CS.initialize();
  
  pixels.begin();
  
  // Pinbelegung
  
  CS.pinMode(touchSensor1, INPUT);
  CS.pinMode(touchSensor2, INPUT);
  CS.pinMode(touchSensor3, INPUT);
  ...
  CS.pinMode(touchSensor100, INPUT);
  
  pinMode(7, OUTPUT);
  
  // Grundform

  pixels.setPixelColor(29, pixels.Color(255,0,0));
     delay(delayval1);
  pixels.setPixelColor(30, pixels.Color(255,255,0));
     delay(delayval1);
  pixels.setPixelColor(49, pixels.Color(0,255,0));
     delay(delayval1);
  pixels.setPixelColor(50, pixels.Color(0,255,255));
     delay(delayval1);
  pixels.setPixelColor(69, pixels.Color(0,0,255));
     delay(delayval1);
  pixels.setPixelColor(70, pixels.Color(255,0,255));
     delay(delayval1);
  pixels.setPixelColor(89, pixels.Color(255,255,255));
     delay(delayval1);
  pixels.setPixelColor(90, pixels.Color(0,0,0));
     delay(delayval1);
  
  pixels.show();
  
}

// ----------------------------------------------------------------------------------------------------

void loop() {
  
  const byte buttonState1 = CS.digitalRead(touchSensor1);
  const byte buttonState2 = CS.digitalRead(touchSensor2);
  const byte buttonState3 = CS.digitalRead(touchSensor3);
  ...
  const byte buttonState100 = CS.digitalRead(touchSensor100);

          .
          .
          .

Mit dieser Zeile wird der LED 29 die Farbe ROT zugewiesen,

pixels.setPixelColor(29, pixels.Color(255,0,0));
pixels.show();

also muss ich eigentlich ja "255,0,0" als Farbe ROT speichern können. Bei der Umsetzung scheitert es jedoch bei mir.

Würde mich sehr über eine kleine Hilfe freuen!

Vielen Dank schon mal im Voraus
leon2212

If I understand your post correctly, it appears that you have a limited number of colors (say 10) in the bottom row.
If that is the case, associate the colors with the digits 0...9.

For example red = (255,0,0) = color #0, green = (0,255,0) = color #1, yellow = (255,255,0) = color #2, etc.

These can be stored in a two dimensional array (called a "look up table") as follows:

unsigned char colortable[3][10] = { {255,0,0}, {0,255,0}, {255,255,0}, ... }; //red, green, yellow, ...

Then it is an easy matter to set a given pixel, given its assigned color digit. To set pixel #29 to green:

pixels.setPixelColor(29, pixels.Color(colortable[0][1],colortable[1][1],colortable[2][1]));

Bau dir ein Struct auf, was du beschreibst oder aber speicher den Wert als Hexwert.

const byte touchSensor1 = 1; //CS.portRead(1);
const byte touchSensor2 = 2;
const byte touchSensor3 = 3;
...
const byte touchSensor100 = 100;

zuerstmal benutze Arrays, die kannst Du mit dem Index ansprechen und nicht jeden Wert einzeln schreiben zu müssen.

byte touchSensor[101];
byte buttonState[101];
...
for(int i=1;i<=100; i++)
{
const byte touchSensor[i] = i;
}

und später

void loop() {
...
  for(int i=1;i<=100; i++)
{
const byte buttonState[i] = CS.digitalRead(touchSensor[i]);
}

Verwende ein 2 dimensionales Array um die Farben zu speichern so wie jremington es vorgeschlagen hat.

Ich befürchte auch, daß Dir der RAM-speicher knapp wird. wahrscheinlich brauchst Du einen Arduino MEGA

Viele Grüße Uwe

So,
ich habe jetzt schon mal den Code umgeschrieben wie du meintest mit den for-Schleifen aber jetzt wird mir eine solche Fehlermeldung angezeigt, was habe ich falsch gemacht?

#include <Wire.h>
#include <Centipede.h>

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>

Centipede CS;

// Grundeinstellung

#define PIN            7

#define NUMPIXELS      100

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval1 = 1;

for(int a=1;a<=100; a++)
{
const byte touchSensor[a] = a;
}

// ----------------------------------------------------------------------------------------------------

void setup() {
  
  // Serielle Schnittstelle

  Serial.begin(9600);
  
  // Bibliothekstart
  
  Wire.begin();
  
  CS.initialize();
  
  pixels.begin();
  
  // Pinbelegung
  
  for(int b=1;b<=100; b++)
  {
  CS.pinMode(touchSensor[b], INPUT);
  }
  
  pinMode(7, OUTPUT);
  
  // Grundform
  
  pixels.setPixelColor(29, pixels.Color(50,0,0));
     delay(delayval1);
  pixels.setPixelColor(30, pixels.Color(50,50,0));
     delay(delayval1);
  pixels.setPixelColor(49, pixels.Color(0,50,0));
     delay(delayval1);
  pixels.setPixelColor(50, pixels.Color(0,50,50));
     delay(delayval1);
  pixels.setPixelColor(69, pixels.Color(0,0,50));
     delay(delayval1);
  pixels.setPixelColor(70, pixels.Color(50,0,50));
     delay(delayval1);
  pixels.setPixelColor(89, pixels.Color(50,50,50));
     delay(delayval1);
  pixels.setPixelColor(90, pixels.Color(0,0,0));
     delay(delayval1);
  
  pixels.show();
  
}

// ----------------------------------------------------------------------------------------------------

void loop() {
  
  for(int c=1;c<=100; c++)
  {
  const byte buttonState[c] = CS.digitalRead(touchSensor[c]);
  }

}

Fehlermeldung:

Build-Optionen wurden verändert, alles wird neu gebaut
Malen_2.0.ino:19:1: error: expected unqualified-id before 'for'
Malen_2.0.ino:19:13: error: 'a' does not name a type
Malen_2.0.ino:19:21: error: 'a' does not name a type
Malen_2.0.ino: In function 'void setup()':
Malen_2.0.ino:44:14: error: 'touchSensor' was not declared in this scope
Malen_2.0.ino: In function 'void loop()':
Malen_2.0.ino:78:46: error: 'touchSensor' was not declared in this scope
Malen_2.0.ino:78:60: error: variable-sized object 'buttonState' may not be initialized
Fehler beim Kompilieren.

leon2212

Ich glaube Du mußt mal die Basis von C lernen.

Du mußt die Variablen zuerst deklarieren (je nach gebrauch außerhalb oder innerhalb einer Funktion) und dann benutzen.
So wie Du die Variablen deklarierst funktioniert das nicht. Du kannst nicht 100 mal das array deklarieren. Außerdem muß das For innerhalb einer funktion ( zb setup()) sein.

Grüße Uwe

Tut mir leid das ich da gerade nicht ganz durchblicke aber ich verstehe es halt gerade echt nicht, vielleicht kannst du mir ja mal ein Beispiel geben wie es sich richtig gehört?!

danke
leon2212

Das aller einfachste ist das:

const unsigned long RED = 0xFF0000;
const unsigned long GREEN = 0x00FF00;
const unsigned long BLUE = 0x0000FF;

Man kann sich auch eine Color Klasse schreiben:

class Color
{
public:
  Color(int r, int g, int b)
  {
    this->r = r;
    this->g = g;
    this->b = b;
  }

  operator unsigned long()  //Cast Operator überladen
  {
    return ((unsigned long)r << 16) | ((unsigned long)g << 8) | b;
  };

  byte r;
  byte g;
  byte b;
};

Dann kann man sich Farben anlegen:

Color RED (255, 0, 0);
Color GREEN (0, 255, 0);
Color BLUE (0, 0, 255);

Test-Ausgabe:

Serial.println(RED, HEX);
Serial.println(GREEN, HEX);
Serial.println(BLUE, HEX);

Durch den überladenen Cast Operator kann man hier direkt das Objekt an print() übergeben. Ansonsten bräuchte man irgendeine Zugriffs-Methode wie value()

Damit kann man dann einfach die Neopixel setPixelColor() Methoden aufrufen:

    setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
    setPixelColor(uint16_t n, uint32_t c),

Es gibt eine Version mit RGB und eine die einen 32 Bit Wert nimmt

Man könnte auch FastLED nehmen und müsste das Rad dann nicht neu erfinden... :wink:

Aber das Projekt ist nicht direkt das klassische Anfängerprojekt. Ohne C Grundlagen wird das frustrierend werden.

Also: mit den Basics anfangen, Tutorials durchrackern und dann Schritt für Schritt besser werden.

Zur konkreten Aufgabenstellung: Ich würde ein 2 dimensionales Array nehmen für die IR Sensoren. Selbige auslesen und die momentanen Werte im Array ablegen.

Ein weiteres 2 dimensionales Array für die RGB Daten jeder LED. (Meinetwegen auch ein eindimensionales).

Ablauf im Loop:

  1. IR Daten einlesen
  2. In Abhängigkeit der IR Daten die LED Daten berechnen - also Helligkeit oder Farbe oder sonstwas mappen.
  3. LED Array an LEDs senden.

Und keine Delays, nirgends, dafür gibt es keinen nachvollziehbaren Grund.

Gruß,

Helmuth

Danke euch allen, ich habe jetzt alles verstanden was ich gebraucht habe und konnte es auch erfolgreich anwenden

leon2212