Neues Modul zur Steuerung von WS2812b LED stripes

Begonnen von swhome, 03 März 2016, 13:27:41

Vorheriges Thema - Nächstes Thema

harway2007

Ich finde euren Ansatz prima .. da ich aber
a. den Raspberry 2 und 3 nutzen möchte
b. die Lösung mit Kondensator Anschluss am Raspberry nicht stabil läuft
schaut euch doch bitte mal das Modul
DIGI-DOT-Booster am SPI des Raspberry
an ...
würde das nicht alle Anschluss- und Steuerprobleme erledigen ?
Habe eine Forum parralel einen Eintrag dazu gestartet,
da ich es auf jeden Fall mit Raspberry anbinden möchte.
MFG Harway




harway2007

#16
Das Modul ist da und klappt ....
Habe 184 LEDs dran am Raspberry 2
sind noch ne Menge Fragen offen...
weiteres im Forumseintrag:
DIGI-DOT-Booster zur Ansteuerung von WS2812 LED per Raspberry
MFG Harway

Nachtrag:
einzelne LEDs mit beliebiger Farbe nach RGB

spi.writebytes([0xA2, 190, 25, 180, 254])
time.sleep(DELAY)
spi.writebytes([0xA4, 10]) 
time.sleep(DELAY)
spi.writebytes([0xB2]) 
time.sleep(DELAY)
spi.close()

exciter

Hier mal die ESP8266 Version:

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>

const char* ssid     = "XXX";
const char* password = "XXX";
WiFiServer server(80);
// Which pin on the Arduino is connected to the NeoPixels?
#define LEDPIN1           14
#define LEDPIN2           0

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS1     144
#define NUMPIXELS2     0


void reset();
// control special effects
boolean fire=false;
boolean rainbow=false;
uint16_t rainbowColor=0;

// setup network and output pins
void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println(F("Booting"));

// Initialize all pixels to 'off'
stripe_setup();
  WiFi.mode(WIFI_STA);
Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

// request receive loop
void loop() {
// listen for incoming clients
  WiFiClient client = server.available();  // Check if a client has connected
  if (client) {
    Serial.println(F("new client"));
   
    String inputLine = "";
   // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean isGet = false;
    boolean isPost = false;
    boolean isPostData = false;
    int postDataLength;
    int ledix = 0;
    int tupel = 0;
    int redLevel = 0;
    int greenLevel = 0;
    int blueLevel = 0;
   
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (isPostData && postDataLength > 0) {
          switch (tupel++) {
            case 0:
              redLevel = colorVal(c);
              break;
            case 1:
              greenLevel = colorVal(c);
              break;
            case 2:
              blueLevel = colorVal(c);
              tupel = 0;
              stripe_setPixelColor(ledix++, stripe_color(redLevel,greenLevel,blueLevel));
              break;
          }
          if (--postDataLength == 0) {
            stripe_show();
            sendOkResponse(client);
            break;
          }
        }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          if (isPost) {
            isPostData = true;
            continue;
          } else {
            // send http response
            if (isGet) {
              sendOkResponse(client);
            } else {
              client.println(F("HTTP/1.1 500 Invalid request"));
              client.println(F("Connection: close"));  // the connection will be closed after completion of the response
              client.println();
            }
            break;
          }
        }
        if (c == '\n') {
          // http starting a new line, evaluate current line
          currentLineIsBlank = true;
          Serial.println(inputLine);
         
// SET SINGLE PIXEL url should be GET /rgb/n/rrr,ggg,bbb
          if (inputLine.length() > 3 && inputLine.substring(0,9) == F("GET /rgb/")) {
            int slash = inputLine.indexOf('/', 9 );
            ledix = inputLine.substring(9,slash).toInt();
            int urlend = inputLine.indexOf(' ', 9 );
            String getParam = inputLine.substring(slash+1,urlend+1);
            int komma1 = getParam.indexOf(',');
            int komma2 = getParam.indexOf(',',komma1+1);
            redLevel = getParam.substring(0,komma1).toInt();
            greenLevel = getParam.substring(komma1+1,komma2).toInt();
            blueLevel = getParam.substring(komma2+1).toInt();
            stripe_setPixelColor(ledix, stripe_color(redLevel,greenLevel,blueLevel));
            stripe_show();
            isGet = true;
          }
          // SET PIXEL RANGE url should be GET /range/x,y/rrr,ggg,bbb
          if (inputLine.length() > 3 && inputLine.substring(0,11) == F("GET /range/")) {
            int slash = inputLine.indexOf('/', 11 );
            int komma1 = inputLine.indexOf(',');
            int x = inputLine.substring(11, komma1).toInt();
            int y = inputLine.substring(komma1+1, slash).toInt();
            int urlend = inputLine.indexOf(' ', 11 );
            String getParam = inputLine.substring(slash+1,urlend+1);
            komma1 = getParam.indexOf(',');
            int komma2 = getParam.indexOf(',',komma1+1);
            redLevel = getParam.substring(0,komma1).toInt();
            greenLevel = getParam.substring(komma1+1,komma2).toInt();
            blueLevel = getParam.substring(komma2+1).toInt();
            for(int i=x; i<=y; i++) {
              stripe_setPixelColor(i, stripe_color(redLevel,greenLevel,blueLevel));
            }
            stripe_show();
            isGet = true;
          }
          // POST PIXEL DATA
          if (inputLine.length() > 3 && inputLine.substring(0,10) == F("POST /leds")) {
            isPost = true;
          }
          if (inputLine.length() > 3 && inputLine.substring(0,16) == F("Content-Length: ")) {
            postDataLength = inputLine.substring(16).toInt();
          }
          // SET ALL PIXELS OFF url should be GET /off
          if (inputLine.length() > 3 && inputLine.substring(0,8) == F("GET /off")) {
            reset();
            isGet = true;
          }
         
          // GET STATUS url should be GET /status
          if (inputLine.length() > 3 && inputLine.substring(0,11) == F("GET /status")) {
            isGet = true;
          }
          // SET FIRE EFFECT
          if (inputLine.length() > 3 && inputLine.substring(0,9) == F("GET /fire")) {
            fire = true;
            rainbow = false;
            stripe_setBrightness(128);
            isGet = true;
          }
          // SET RAINBOW EFFECT
          if (inputLine.length() > 3 && inputLine.substring(0,12) == F("GET /rainbow")) {
            rainbow = true;
            fire = false;
            stripe_setBrightness(128);
            isGet = true;
          }
          inputLine = "";
        }
        else if (c != '\r') {
          // add character to the current line
          currentLineIsBlank = false;
          inputLine += c;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println(F("client disconnected"));
  }
  if (fire) fireEffect();
  if (rainbow) rainbowCycle();
}

// Reset stripe, all LED off and no effects
void reset() {
  for(int i=0; i<stripe_numPixels(); i++) {
    stripe_setPixelColor(i, 0);
  }
  stripe_setBrightness(255);
  stripe_show();
  fire = false;
  rainbow = false;
}

// LED flicker fire effect
void fireEffect() {
  for(int x = 0; x <stripe_numPixels(); x++) {
    int flicker = random(0,55);
    int r1 = 226-flicker;
    int g1 = 121-flicker;
    int b1 = 35-flicker;
    if(g1<0) g1=0;
    if(r1<0) r1=0;
    if(b1<0) b1=0;
    stripe_setPixelColor(x,stripe_color(r1,g1, b1));
  }
  stripe_show();
  delay(random(10,113));
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle() {
  uint16_t i;

  if (rainbowColor++>255) rainbowColor=0;
  for(i=0; i< stripe_numPixels(); i++) {
    stripe_setPixelColor(i, Wheel(((i * 256 / stripe_numPixels()) + rainbowColor) & 255));
  }
  stripe_show();
  delay(20);
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return stripe_color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return stripe_color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return stripe_color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

int colorVal(char c) {
  int i = (c>='0' && c<='9') ? (c-'0') : (c - 'A' + 10);
  return i*i + i*2;
}

void sendOkResponse(WiFiClient client) {
  client.println(F("HTTP/1.1 200 OK"));
  client.println(F("Content-Type: text/html"));
  client.println(F("Connection: close"));  // the connection will be closed after completion of the response
  client.println();
  // standard response
  client.print(F("OK,"));
  client.print(stripe_numPixels());
  client.print(F(","));
  int oncount=0;
  for(int i=0; i<stripe_numPixels(); i++) {
    if (stripe_getPixelColor(i) != 0) oncount++;
  }
  client.println(oncount);
}



Mit der vstripe aus dem Originalfile zu kompilieren. Pin, SSID, KEY, nach Bedarf anpassen.

Gruß Steffen

swhome

Das ist ja cool! Wie hast Du das technisch gelöst? LEDs an 5 Volt und einen separaten 3,3V Regler für die ESP? Und der Ausgang des ESP direkt an die erste LED?
Im Einsatz: FHEM auf Raspberry Pi mit 350 devices, hauptsächlich Homematic Wired und HM-Heizungsregler, dazu diverse Eigenbauten für Fussbodenheizung und LED Beleuchtung. Und jetzt mit Alexa!

exciter

Habe das ganze noch am labornetzteil bei 3,4V Volt laufen. Ja Ausgang vom ESP direkt auf die erste LED.
Habe das Programm auch noch erweitert mit der Adafruit neo Matrix Bibliothek. Kann nun auf eine Matrix 5x29 ws2812b LEDs, Text aus Fhem heraus schicken, bzw. readings ausgeben.
Ist aber eher alles zusammengewürfelter Code, welcher noch stark verbesserungsbedürftig ist.

tiwo85

Hallo swhome,
Cooles Projekt. Ich habe mir gleich ein paar stripes bestellt.
Wie muss die Playfile aufgebaut sein?

Mfg

Gesendet von meinem D5803 mit Tapatalk


swhome

Hi tiwo, das Playfile besteht aus beliebig vielen Zeilen mit jeweils allen Farbwerten für die LEDs.

Die Farbwerte sind komprimiert, es gibt nur 16 Helligkeiten pro Kanal, kodiert als Hexadezimalzahl. 0 = aus, F = maximale Helligkeit. Die Farbe rot mit maximaler Helligkeit ist also f00, gelb ist ff0, weiss ist fff.

Nehmen wir an, Du hast 10 LEDs und willst ein laufendes Muster aus blau und weiss darstellen, dann sieht die Datei so aus:

fff00f000fff00f000fff00f000fff
000fff00f000fff00f000fff00f000
00f000fff00f000fff00f000fff00f

Zugegeben wären unter Zuhilfenahme aller druckbaren Zeichen mehr Farben darstellbar, da war ich wohl etwas faul ;-)
Im Einsatz: FHEM auf Raspberry Pi mit 350 devices, hauptsächlich Homematic Wired und HM-Heizungsregler, dazu diverse Eigenbauten für Fussbodenheizung und LED Beleuchtung. Und jetzt mit Alexa!

juppzupp

#22
Spannendes Projekt! Gestern mal auf die Schnelle probiert, klappt einwandfrei.
Leicht erweiterbar.
Danke!

Edit : auf esp8266 mit 60 leds

swhome

Hallo allseits, vielen Dank für das feedback!

Ich habe eine neue Version des Moduls an den ersten Beitrag angehängt, die eine Farbwahl per Mausklick ermöglicht. Damit werden dann alle LED's mit der gleichen Farbe gesetzt. Es bleibt noch etwas hinter den Möglichkeiten zurück, aber ist sehr benutzerfreundlich. Bin dran noch mehr rauszuholen.

Viele Grüße
Stefan
Im Einsatz: FHEM auf Raspberry Pi mit 350 devices, hauptsächlich Homematic Wired und HM-Heizungsregler, dazu diverse Eigenbauten für Fussbodenheizung und LED Beleuchtung. Und jetzt mit Alexa!

juppzupp

Hi,

es kommt natürlich immer darauf an was man damit vor hat.....
Ich hab beim "spielen" gestern schnell "hunger" nach mehr entwickelt.
Als Beispiel : 60 LEDs in der Küche, die Abends mit dem Sonnenuntergang anfangen hoch zu dimmen.
Wenn Abfall ansteht, 5 LEDs die blinken (blau, gelb, grau).
Könnte man mit dem playfile lösen - allerdings gibt es nur einen. Attribute umschreiben per notify, at, etc. wäre möglich.
Gefällt mir noch nicht so ganz, weil die last auf fhem liegt, und der ESP eh nix zu tun hat. Auch schnellere abfolgen könnten schwierig werden.
So hab ich ich dem ESP (quick and dirty) ne blink routing spendiert, die ich von fhem aufrufe.

    if($command eq "blink")
  {
    return "Set blink needs seven parameters: <first_led> <last_led> <red> <green> <blue> <ontime> <offtime>" if ( @a != 7 );
    my $first_led=$a[0];
    $first_led=($first_led=~ m/$reDOUBLE/) ? $1:undef;
    return "first_led value ".$a[0]." is not a valid number" if (!defined($first_led));

    my $last_led=$a[1];
    $last_led=($last_led=~ m/$reDOUBLE/) ? $1:undef;
    return "last_led value ".$a[1]." is not a valid number" if (!defined($last_led));

    my $red=$a[2];
    $red=($red=~ m/$reDOUBLE/) ? $1:undef;
    return "red value ".$a[2]." is not a valid number" if (!defined($red));

    my $green=$a[3];
    $green=($green=~ m/$reDOUBLE/) ? $1:undef;
    return "green value ".$a[3]." is not a valid number" if (!defined($green));

    my $blue=$a[4];
    $blue=($blue=~ m/$reDOUBLE/) ? $1:undef;
    return "blue value ".$a[4]." is not a valid number" if (!defined($blue));

    my $ontime=$a[5];
    $ontime=($ontime=~ m/$reDOUBLE/) ? $1:undef;
    return "ontime value ".$a[5]." is not a valid number" if (!defined($ontime));

    my $offtime=$a[6];
    $offtime=($offtime=~ m/$reDOUBLE/) ? $1:undef;
    return "offtime value ".$a[6]." is not a valid number" if (!defined($offtime));

    Log 4, "set command: " . $command ." desired:". $first_led . " to " . $last_led;
    $URL .= "/blink/" . $first_led . "," . $last_led . "/" . $red . "," . $green . "," . $blue . "," . $ontime . "," . $offtime;
    $rc = LEDStripe_request($hash,$URL);
  }


passend dazu einen aufruf der nur die loops beendet, damit ich nicht den ganzen stripe reseten muss.
  if($command eq "nofx")
  {
    $URL .= "/nofx";
    LEDStripe_request($hash,$URL);
  }


Beim dimmen hab ich aufgehört, da ich mich frage, ob es vielleicht besser wäre auf fastled.h statt neopixel.h zu setzen.
Vielleicht sind meine Ideen auch zu speziell um den weg ins modul oder den sketch zu finden.

Grüße !


swhome

Hi, das mit dem Hunger geht mir genauso :-)

Playfiles wechseln mache ich auch per Attributänderung. Was die Last angeht: klar die ESP hat nix zu tun aber die Leistungsfähigkeit der Platform meines fhem ist auch deutich höher als die der ESP. Und ich muss nicht jedesmal flashen wenn sich was an der Software ändert.

Ein Dimmen mit Zeitangabe so wie die Homematic-Dimmer es können steht auch auf meiner Roadmap. Das langsame Auffahren zb. am Abend mache ich allerdings wegen der Farbvielfalt als Playfile.

Deine Blinkroutine werde ich in die nächste Version aufnehmen. Danke!

Ausserdem gibts noch ein neues Feature im Modul:

Wer das LED Netzteil nicht nur im Standby lassen sondern gern richtig ausschalten will, kann einen zusätzlichen Schaltkanal mit dem Attribut power_switch deklarieren. Das Modul wird diesen Kanal dann einschalten bevor LEDs aktiviert werden und ihn beim Kommando off wieder ausschalten.

Im Einsatz: FHEM auf Raspberry Pi mit 350 devices, hauptsächlich Homematic Wired und HM-Heizungsregler, dazu diverse Eigenbauten für Fussbodenheizung und LED Beleuchtung. Und jetzt mit Alexa!

juppzupp

;-)
Ich überschlage mich vor Ideen. Muss allerdings erstmal den nonsensfilfter anwenden...
Spiffs Filesystem auf den esp und dann den playfile local abspielen?
Wobei im Alltag die Frage ist, wie oft man schnelle Farbwechsel ala Rainbow braucht/ändert.
Vielleicht mehrere playfile Attribute so das man mit play "diman" oder play "dimaus" einfacher wählen kann?
Bzgl dimmen. Besteht bei dir auch die Idee auf fastled umzustellen?
Und kannst du deinen playfile fürs abendliche aufdimmen sharen?

Grüße!

exciter

Habe nun noch die neomatrix Library eingebunden.
Macht schon Laune, nur leider zu wenig Zeit....

swhome

Cool! Das ist ein definitiv ein no-nonsense-Feature :-)
Code aufräumen und her damit
Im Einsatz: FHEM auf Raspberry Pi mit 350 devices, hauptsächlich Homematic Wired und HM-Heizungsregler, dazu diverse Eigenbauten für Fussbodenheizung und LED Beleuchtung. Und jetzt mit Alexa!

juppzupp

kein neomatrix, aber der blinker & nofx :

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>

const char* ssid     = "XXX";
const char* password = "XXX";
WiFiServer server(80);
// Which pin on the Arduino is connected to the NeoPixels?
#define LEDPIN1           14
#define LEDPIN2           12

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS1     30
#define NUMPIXELS2     30
int xfrom;
int yto;
int myredLevel;
int mygreenLevel;
int myblueLevel;
int myOn;
int myOff;


void reset();
// control special effects
boolean fire=false;
boolean rainbow=false;
boolean blinker=false;
uint16_t rainbowColor=0;



// setup network and output pins
void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println(F("Booting"));

// Initialize all pixels to 'off'
stripe_setup();
  WiFi.mode(WIFI_STA);
Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
 
}

// request receive loop
void loop() {
// listen for incoming clients
  WiFiClient client = server.available();  // Check if a client has connected
  if (client) {
    Serial.println(F("new client"));
   
    String inputLine = "";
   // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean isGet = false;
    boolean isPost = false;
    boolean isPostData = false;
    int postDataLength;
    int ledix = 0;
    int tupel = 0;
    int redLevel = 0;
    int greenLevel = 0;
    int blueLevel = 0;
   
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (isPostData && postDataLength > 0) {
          switch (tupel++) {
            case 0:
              redLevel = colorVal(c);
              break;
            case 1:
              greenLevel = colorVal(c);
              break;
            case 2:
              blueLevel = colorVal(c);
              tupel = 0;
              stripe_setPixelColor(ledix++, stripe_color(redLevel,greenLevel,blueLevel));
              break;
          }
          if (--postDataLength == 0) {
            stripe_show();
            sendOkResponse(client);
            break;
          }
        }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          if (isPost) {
            isPostData = true;
            continue;
          } else {
            // send http response
            if (isGet) {
              sendOkResponse(client);
            } else {
              client.println(F("HTTP/1.1 500 Invalid request"));
              client.println(F("Connection: close"));  // the connection will be closed after completion of the response
              client.println();
            }
            break;
          }
        }
        if (c == '\n') {
          // http starting a new line, evaluate current line
          currentLineIsBlank = true;
          Serial.println(inputLine);
         
// SET SINGLE PIXEL url should be GET /rgb/n/rrr,ggg,bbb
          if (inputLine.length() > 3 && inputLine.substring(0,9) == F("GET /rgb/")) {
            int slash = inputLine.indexOf('/', 9 );
            ledix = inputLine.substring(9,slash).toInt();
            int urlend = inputLine.indexOf(' ', 9 );
            String getParam = inputLine.substring(slash+1,urlend+1);
            int komma1 = getParam.indexOf(',');
            int komma2 = getParam.indexOf(',',komma1+1);
            redLevel = getParam.substring(0,komma1).toInt();
            greenLevel = getParam.substring(komma1+1,komma2).toInt();
            blueLevel = getParam.substring(komma2+1).toInt();
            stripe_setPixelColor(ledix, stripe_color(redLevel,greenLevel,blueLevel));
            stripe_show();
            isGet = true;
          }
          // SET PIXEL RANGE url should be GET /range/x,y/rrr,ggg,bbb
          if (inputLine.length() > 3 && inputLine.substring(0,11) == F("GET /range/")) {
            int slash = inputLine.indexOf('/', 11 );
            int komma1 = inputLine.indexOf(',');
            int x = inputLine.substring(11, komma1).toInt();
            int y = inputLine.substring(komma1+1, slash).toInt();
            int urlend = inputLine.indexOf(' ', 11 );
            String getParam = inputLine.substring(slash+1,urlend+1);
            komma1 = getParam.indexOf(',');
            int komma2 = getParam.indexOf(',',komma1+1);
            redLevel = getParam.substring(0,komma1).toInt();
            greenLevel = getParam.substring(komma1+1,komma2).toInt();
            blueLevel = getParam.substring(komma2+1).toInt();
            for(int i=x; i<=y; i++) {
              stripe_setPixelColor(i, stripe_color(redLevel,greenLevel,blueLevel));
            }
            stripe_show();
            isGet = true;
          }
          // POST PIXEL DATA
          if (inputLine.length() > 3 && inputLine.substring(0,10) == F("POST /leds")) {
            isPost = true;
          }
          if (inputLine.length() > 3 && inputLine.substring(0,16) == F("Content-Length: ")) {
            postDataLength = inputLine.substring(16).toInt();
          }
          // SET ALL PIXELS OFF url should be GET /off
          if (inputLine.length() > 3 && inputLine.substring(0,8) == F("GET /off")) {
            reset();
            isGet = true;
          }
         
          // GET STATUS url should be GET /status
          if (inputLine.length() > 3 && inputLine.substring(0,11) == F("GET /status")) {
            isGet = true;
          }
          // SET FIRE EFFECT
          if (inputLine.length() > 3 && inputLine.substring(0,9) == F("GET /fire")) {
            fire = true;
            rainbow = false;
            stripe_setBrightness(128);
            isGet = true;
          }
          // SET RAINBOW EFFECT
          if (inputLine.length() > 3 && inputLine.substring(0,12) == F("GET /rainbow")) {
            rainbow = true;
            fire = false;
            stripe_setBrightness(128);
            isGet = true;
          }
          // SET no_effects
          if (inputLine.length() > 3 && inputLine.substring(0,9) == F("GET /nofx")) {
            rainbow = false;
            fire = false;
            blinker = false;
            isGet = true;
          }
          if (inputLine.length() > 3 && inputLine.substring(0,11) == F("GET /blink/")) {
            int slash = inputLine.indexOf('/', 11 );
            int komma1 = inputLine.indexOf(',');
            xfrom = inputLine.substring(11, komma1).toInt();
            yto = inputLine.substring(komma1+1, slash).toInt();
            int urlend = inputLine.indexOf(' ', 11 );
            String getParam = inputLine.substring(slash+1,urlend+1);
            komma1 = getParam.indexOf(',');
            int komma2 = getParam.indexOf(',',komma1+1);
            int komma3 = getParam.indexOf(',',komma2+1);
            int komma4 = getParam.indexOf(',',komma3+1);
            myredLevel = getParam.substring(0,komma1).toInt();
            mygreenLevel = getParam.substring(komma1+1, komma2).toInt();
            myblueLevel = getParam.substring(komma2+1, komma3).toInt();
           
            myOn = getParam.substring(komma3+1, komma4).toInt();
            myOff = getParam.substring(komma4+1).toInt();

            blinker = true;
            rainbow = false;
            fire = false;
           
            isGet = true;
          }
          inputLine = "";
        }
        else if (c != '\r') {
          // add character to the current line
          currentLineIsBlank = false;
          inputLine += c;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println(F("client disconnected"));
  }
  if (fire) fireEffect();
  if (rainbow) rainbowCycle();
  if (blinker) blinkerEffect();
}

// Reset stripe, all LED off and no effects
void reset() {
  for(int i=0; i<stripe_numPixels(); i++) {
    stripe_setPixelColor(i, 0);
  }
  stripe_setBrightness(255);
  stripe_show();
  fire = false;
  rainbow = false;
  blinker = false;
}

// LED flicker fire effect
void fireEffect() {
  for(int x = 0; x <stripe_numPixels(); x++) {
    int flicker = random(0,55);
    int r1 = 226-flicker;
    int g1 = 121-flicker;
    int b1 = 35-flicker;
    if(g1<0) g1=0;
    if(r1<0) r1=0;
    if(b1<0) b1=0;
    stripe_setPixelColor(x,stripe_color(r1,g1, b1));
  }
  stripe_show();
  delay(random(10,113));
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle() {
  uint16_t i;

  if (rainbowColor++>255) rainbowColor=0;
  for(i=0; i< stripe_numPixels(); i++) {
    stripe_setPixelColor(i, Wheel(((i * 256 / stripe_numPixels()) + rainbowColor) & 255));
  }
  stripe_show();
  delay(20);
}

void blinkerEffect() {
for(int i=xfrom; i<=yto; i++) {
    stripe_setPixelColor(i, stripe_color(myredLevel,mygreenLevel,myblueLevel));
  }
  stripe_show();
delay(myOn);
for(int i=xfrom; i<= yto; i++) {
    stripe_setPixelColor(i, stripe_color(0,0,0));
  }
  stripe_show();
delay(myOff);
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return stripe_color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return stripe_color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return stripe_color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

int colorVal(char c) {
  int i = (c>='0' && c<='9') ? (c-'0') : (c - 'A' + 10);
  return i*i + i*2;
}

void sendOkResponse(WiFiClient client) {
  client.println(F("HTTP/1.1 200 OK"));
  client.println(F("Content-Type: text/html"));
  client.println(F("Connection: close"));  // the connection will be closed after completion of the response
  client.println();
  // standard response
  client.print(F("OK,"));
  client.print(stripe_numPixels());
  client.print(F(","));
  int oncount=0;
  for(int i=0; i<stripe_numPixels(); i++) {
    if (stripe_getPixelColor(i) != 0) oncount++;
  }
  client.println(oncount);
}