Arduino Lektion #104: SK6812 LED RGB Matrix Modul

Das RGB LED Matrix Modul SK6812 verfügt über 40 RGB LEDs vom Typ 5050.

SK6812 RGB LED Matrix Modul
SK6812 RGB LED Matrix Modul

Bezug

Das mir vorliegende Modul habe ich über ebay.de für ca. 6€ inkl. Versandkosten erstanden.

Technische Daten des SK6812 RGB LED Modul

Das Modul verfügt wie bereits erwähnt über 40 LEDs vom Typ 5050 und hat die Abmaße (L x B x H) von 69mm in der Länge, 57mm in der Breite sowie 19mm in der Höhe. Das Modul wird über den 5V Leitung gespeißt und verbraucht dabei ca. 0,46 A.

Stromverbrauch - SK6812 RGB LED Matrix Modul
Stromverbrauch – SK6812 RGB LED Matrix Modul

Das Bild ist etwas dunkel geraten da meine Kamera mit den hellen RGB LEDs nicht so richtig klar kam.

Das Modul wird einfach auf den Microcontroller gesteckt und bedeckt zunächst einmal alle Pins. Es werden jedoch die Pins nach oben durch Buchsenleisten bereitgestellt. 

SK6812 RGB LED Matrix Modul auf Keyestudio UNO
SK6812 RGB LED Matrix Modul auf Keyestudio UNO

Beispiele

Auf der Wiki-Seite https://wiki.keyestudio.com/KS0416_keyestudio_SK6812_Shield vom Hersteller findet man ein kleines Beispiel welches auf den Microcontroller hochgeladen werden kann und somit alle Funktionen des Shields aufzeigt.

Für das Programmieren des Moduls wird zusätzlich die Adafruit Bibliothek „Adafruit Neo Pixel“ benötigt welche in der Arduino IDE bequem über den Bibliotheksverwalter installiert werden kann. Wie du eine Bibliothek in der Arduino IDE installierst habe ich im gleichnamigen Beitrag Arduino IDE, Einbinden einer Bibliothek ausführlich erläutert.

Die Bibliothek zum betreiben eines NeoPixels habe ich bereits mehrfach verwendet und unter anderem im Beitrag Arduino Lektion 31: 12bit RGB NeoPixel Ring verwendet.

Beispiel I – LED Lauflicht

Basierend auf dem Beispiel vom Hersteller habe ich ein LED Lauflicht erzeugt welches jede LED einmal aufleuchten lässt zunächst in der Reihe dann in jeder Spalte.

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

//Pin zum steuern des Moduls ist am digitalen Pin D13 angeschlossen
#define PIN 13

const int MAX_PIXEL = 40; //das Modul verfügt über insgesamt 40 LEDs vom Typ 5050
Adafruit_NeoPixel strip = Adafruit_NeoPixel(MAX_PIXEL, PIN, NEO_GRB + NEO_KHZ800);

//Konstanten für die Farben
const uint32_t COLOR_RED = strip.Color(255, 0, 0);
//Wenn alle Farben auf 0 sind dann ist die LED aus
const uint32_t COLOR_NONE = strip.Color(0, 0, 0);

const int PAUSE = 125;

void setup() {
  Serial.begin(9600);
  //begin der kommunikation mit dem Modul
  strip.begin();
  strip.setBrightness(25);
  strip.show();
}

void loop() {
  lauflichtPixelFuerPixel();
  lauflichtSpaltenweise();
  lauflichtReihenweise();
}

void lauflichtPixelFuerPixel() {
  for (int pixel = 0; pixel <= MAX_PIXEL; pixel++) {
    //setzen der aktuellen Pixelposition mit der Farbe "rot"
    strip.setPixelColor(pixel, COLOR_RED);
    strip.show(); //anzeigen der Farbe
    delay(PAUSE); //eine kleine Pause
    //setzen der Farbe auf "NONE"
    strip.setPixelColor(pixel, COLOR_NONE);
    strip.show(); //anzeigen der Farbe
  }
}

void lauflichtSpaltenweise() {
  int colIndex = 0;
  for (int spalte = 0; spalte <= 8; spalte++) {
    int index = colIndex;
    for (int pixel = 0; pixel < 5; pixel++) {
      strip.setPixelColor(index, COLOR_RED);
      index = index + 8;
    }
    strip.show(); //anzeigen der Farbe
    delay(PAUSE); //eine kleine Pause
    index = colIndex;
    for (int pixel = 0; pixel < 5; pixel++) {
      strip.setPixelColor(index, COLOR_NONE);
      index = index+8;
    }
    strip.show(); //anzeigen der Farbe
    colIndex = colIndex + 1;
  }
}

void lauflichtReihenweise() {
  int rowIndex = 0;
  for (int reihe = 0; reihe <= 4; reihe++) {
    int index = rowIndex;
    for (int pixel = 0; pixel < 8; pixel++) {
      strip.setPixelColor(index+pixel, COLOR_RED);
    }
    strip.show(); //anzeigen der Farbe
    delay(PAUSE); //eine kleine Pause
    index = rowIndex;
    for (int pixel = 0; pixel < 8; pixel++) {
      strip.setPixelColor(index+pixel, COLOR_NONE);
    }
    strip.show(); //anzeigen der Farbe
    rowIndex = rowIndex + 8;
  }
}

Webseite zum steuern des RGB LED Moduls

Im ersten Beispiel habe ich gezeigt wie ein einfaches Lauflicht erzeugt werden kann. Im weiteren Verlauf könnte ich nun aufzeigen wie man verschiedene Effekte generiert jedoch ist es immer fast das gleiche man benötigt eine Schleife (oder mehr) und steuert dann die Pixel an. Ich möchte als nächstes jedoch zeigen wie du dir eine kleine Webseite erstellst und über einen ESP8266 die RGB LED Matrix steuerst.

Weboberfläche zum konfigurieren des SK6812 RGB LED Shields
Dieses Video ansehen auf YouTube.

Für dieses kleine Projekt benötigst du:

  • 1x ESP8622 (zbsp. Wemos D1 Mini),
  • 2x Breadboardkabel, männlich – männlich, 20cm.
  • 1x min. 170 Pin Breradboard

Webseite

Die Webseite enthält ein Eingabefeld für die IP Adresse des ESP sowie 2 Schaltflächen (zum Zurücksetzen und Absenden). Des Weiteren sind natürlich die einzelnen „Pixel“ auf der Seite vorhanden. 

SK6812 - Webkonfigurator
SK6812 – Webkonfigurator

Für jeden der 40 Pixel wurde jeweils ein ColorPicker eingerichtet.
Wenn der Benutzer auf einen Pixel klickt so wird ein Dialog geöffnet und es kann eine Farbe gewählt werden. 

Beim Absenden der Seite werden alle Pixel ausgewertet  und der HEX Wert der Farbe in ein RGB Wert umgerechnet. 

 

ESP866 – Programm

Der ESP dient dazu die Daten der Seite zu empfangen und auszuwerten. 

Zunächst muss eine Verbindung zum lokalen WiFi Netzwerk hergestellt werden.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid = ""; //SSID aus dem Router
const char* password = ""; //Passwort für den Zugang zum WLAN

ESP8266WebServer server(80); //Port auf welchem der Server laufen soll.

String pixels[40];

void setup() {
  delay(10); //10ms. Warten damit die Seriele Kommunikation aufgebaut wurde.
  Serial.begin(9600);
  WiFi.begin(ssid, password); //Initialisieren der Wifi Verbindung.

  while (WiFi.status() != WL_CONNECTED) { //Warten bis die Verbindung aufgebaut wurde.
    delay(500);
  }

  server.on("/sk6812", callHandleSK6812Shield);

  server.begin(); // Starten des Servers.
}

In der loop Funktion wird nur ausgeführt das der Server die anfragen vom Client behandelt.

void loop() {
  server.handleClient();
}

Die eigentliche Arbeit erledigt die Funktion „callHandleSK6812Shield“.

Hier wird zunächst über die Parameter der Adresse iteriert und die Daten in einem Array abgelegt.

Als Parameter können die einzelnen Pixelfarben oder auch einfach der Befehl „reset“ empfangen werden. Wenn also ein Parameter „reset“ empfangen wird dann wird eine interne Variable auf true gesetzt und die Schleife abgebrochen ansonsten wird das Array mit den Farben befüllt. Am Ende der Funktion wird nun geprüft ob ein „reset“ durchgeführt werden soll oder aber die Pixelfarben gesendet werden sollen. Im Fall eines „reset“ wird nur der Befehl „reset“ über die serielle Schnittstelle gesendet.

void callHandleSK6812Shield() {
  boolean doReset = false;
  for (int i = 0; i < server.args(); i++) {

    String parameterName = server.argName(i);
    String parameterValue = server.arg(i);
    //Wenn der Parametername gleich "text" ist dann...

    if (parameterName == "reset") {
      doReset = true;
      break;
    }

    if (parameterName != "test") {
      pixels[i - 1] = parameterValue;
    }
  }
  sendResult();

  if (doReset) {
    Serial.println("reset");
  } else {
    sendSerialCommands();
  }
}

Sollten jedoch die Pixelfarben gesendet werden so wird das Array mit den Pixel durchlaufen und über die Serielle Schnittstelle gesendet. Es werden jedoch nur die farbigen Pixel gesendet!

void sendSerialCommands() {
  for (int i = 0; i < 40; i++) {
    if (pixels[i] != "000000000") {

      String line = "";
      if (i < 10) {
        line += "0";
      }
      line += String(i);
      line += "-";
      line += pixels[i];
      Serial.println(line);
    }
  }

}

 

Arduino – Programm

Der Arduino UNO (in meinem Fall ein Arduino UNO von der gleichen Firma Keyestudio) empfängt die Daten per serieller Schnittstelle vom ESP und wertet diese wiederum aus.
Ich habe zusäzlich die Bibliothek „SoftwareSerial“ verwendet um auch debug Ausgaben auf der eigentlichen seriellen Schnittstelle durchführen zu können.

#include <SoftwareSerial.h>
SoftwareSerial serial(2, 3); // RX | TX

Für das ansteuern der Pixel verwende ich wie auch im ersten Beispiel die Bibliothek von Adafruit.

#include <Adafruit_NeoPixel.h>
//Pin zum steuern des Moduls ist am digitalen Pin D13 angeschlossen
#define PIN 13

const int MAX_PIXEL = 40; //das Modul verfügt über insgesamt 40 LEDs vom Typ 5050
Adafruit_NeoPixel strip = Adafruit_NeoPixel(MAX_PIXEL, PIN, NEO_GRB + NEO_KHZ800);

Zusätzlich benötigen wir als Global Konstante den Wert für die Farbe schwarz.

//Wenn alle Farben auf 0 sind dann ist die LED aus
const uint32_t COLOR_NONE = strip.Color(0, 0, 0);

In der Funktion „setup“ werden die beiden seriellen Schnittstellen mit der Geschwindigkeit von 9600baud eingerichtet / gestartet sowie die Kommunikation mit dem RGB LED Shield gestartet.

Damit ich später ein Video erzeugen kann dimme ich die LEDs mit der Funktion „setBrightness“ auf den Wert 15.

void setup() {
  Serial.begin(9600);
  serial.begin(9600);
  //begin der kommunikation mit dem Modul
  strip.begin();
  strip.setBrightness(15);
  strip.show();
}

Die Funktion „loop“ dient nun dazu die vom ESP gesendeten Daten zu empfangen und zu verarbeiten. 

Zunächst wird geprüft ob Daten empfangen werden können, wenn ja dann werden die im gesamten geladen und in der Variable „dataLine“ gespeichert.

void loop() {
  if (serial.available() > 0) {
    dataLine = serial.readString();
    dataLine.trim();

Wenn die Anzahl der Zeichen in der Datenzeile größer als 0 ist, dann werden alle nicht sichtbaren Steuerzeichen (\r & \n) aus den empfangenen Daten entfernt.

if (dataLine.length() > 0 ) {     
     dataLine.replace("\r","");
     dataLine.replace("\n","");

Als nächstes wird nun geprüft ob der Befehl „reset“ empfangen wurde. Wenn dieses so ist dann werden alle Pixel auf die Farbe Schwarz gesetzt und die Funktion loop verlassen.

if(dataLine == "reset"){
       resetPixel();
       return;
     }
void resetPixel(){
  for(int i=0;i<40;i++){
    strip.setPixelColor(i, COLOR_NONE);
  }
  strip.show();
}

Wenn nicht der Befehl „reset“ empfangen wurde dann werden die Zeilen geparst.
Eine korrekte Datenzeile enthält einen zweistelligen Index gefolgt von einem Bindestrich und den RGB Farbwert.

00-255000128
int from = 0;
int to = 12;
for (int i = 0; i < dataLine.length() / 12; i++) {
  String line = dataLine.substring(from, (to+(i*12)));
  from = from + 12;       
  int pixelIndex = line.substring(0, 2).toInt();
  String rgbValue = line.substring(3);
  int red = rgbValue.substring(0, 3).toInt();
  int green = rgbValue.substring(3, 6).toInt();
  int blue = rgbValue.substring(6,10).toInt();
  pixel(pixelIndex, red, green, blue);
}
void pixel(int pixel, int red, int green, int blue) {
  strip.setPixelColor(pixel, strip.Color(red, green, blue));
  strip.show();
}

 

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.