From 920070745d857c79878618f9513934595a9e75fa Mon Sep 17 00:00:00 2001 From: starcalc Date: Mon, 27 Feb 2017 17:51:18 +0100 Subject: [PATCH 01/14] Added OTA-Update (with effect), spiral-effect, larson-scabber. Source indented --- pixelprojektor/pixelprojektor.ino | 754 +++++++++++++++++++----------- 1 file changed, 485 insertions(+), 269 deletions(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index dbeb8fd..8ff47e5 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -1,60 +1,66 @@ -#include +#include // homie lib from: https://github.com/marvinroger/homie-esp8266/ #include +#include #ifdef __AVR__ - #include +#include #endif -#define PIN 2 //data pin for ws2812 +#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 #define FPS 15 -uint8_t effect=0; +uint8_t effect = 0; #define EFFECT_NONE 0 #define EFFECT_SMOOTH 1 -uint8_t movingPoint_x=3; -uint8_t movingPoint_y=3; -uint8_t wheelPos=0; -uint8_t wheelPosSlow=0; //for slower wheelPos increment than 1 -int wheelSpeed=16; //16=+1/frame -int smoothing=80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. -int strength=50; //how much pixels to apply color to +uint8_t movingPoint_x = 3; +uint8_t movingPoint_y = 3; +uint8_t wheelPos = 0; +uint8_t wheelPosSlow = 0; //for slower wheelPos increment than 1 +int wheelSpeed = 16; //16=+1/frame +int smoothing = 80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. +int strength = 50; //how much pixels to apply color to #define EFFECT_SPIRAL 2 #define EFFECT_RANDOMFADE 3 -int fadespeedmax=5; //1 to 255 +#define EFFECT_CHASE 4 +#define EFFECT_RADAR 5 +#define EFFECT_LARSON 6 +int fadespeedmax = 5; //1 to 255 -int iconCountStart=0; //for percentage calculation -int iconCountdown=0; //0=off -uint8_t iconchar=0; //last displayed char -int32_t iconcolor=0; //last icon color +int iconCountStart = 0; //for percentage calculation +int iconCountdown = 0; //0=off +uint8_t iconchar = 0; //last displayed char +int32_t iconcolor = 0; //last icon color + +uint16_t Index; // current step within the pattern +// int Index = 0; // Step for Effect (e.g. chase) +// int state = 0; // Direction for Larson Scanner (spiral) +enum direction { FORWARD, REVERSE }; // Direction +direction Direction; // direction to run the pattern - - - - /* the values in this array are a 8x8 bitmap font for ascii characters */ static uint64_t font[128] = { /************************************************************************ -* font.c -* Copyright (C) Lisa Milne 2014 -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* See the GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see -************************************************************************/ + font.c + Copyright (C) Lisa Milne 2014 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + ************************************************************************/ 0x7E7E7E7E7E7E0000, /* NUL */ 0x7E7E7E7E7E7E0000, /* SOH */ 0x7E7E7E7E7E7E0000, /* STX */ @@ -184,7 +190,7 @@ static uint64_t font[128] = { 0x324C000000, /* ~ */ 0x7E7E7E7E7E7E0000 /* DEL */ }; - + Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); @@ -198,29 +204,73 @@ uint8_t pixelR_buffer[NUMPIXELS]; uint8_t pixelG_buffer[NUMPIXELS]; uint8_t pixelB_buffer[NUMPIXELS]; -long lastMillis=0; -long fpsdelay=1000/FPS; +long lastMillis = 0; +long fpsdelay = 1000 / FPS; -int xyToPos(int x, int y){ //convert x y pixel position to matrix position - if (y%2==0){ - return (y*8+x); - }else{ - return (y*8+(7-x)); - } +int xyToPos(int x, int y) { //convert x y pixel position to matrix position + if (y % 2 == 0) { + return (y * 8 + x); + } else { + return (y * 8 + (7 - x)); + } } -int numToPos(int num){ //convert pixel number to actual 8x8 matrix position - int x=num%8; - int y=num/8; - return xyToPos(x,y); +int numToPos(int num) { //convert pixel number to actual 8x8 matrix position + int x = num % 8; + int y = num / 8; + return xyToPos(x, y); +} + +int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix position in a spiral + int findx = 7; + int findy = 0; + int stepsize = 7; // initial value (0..7) + int stepnumber = 0; // each "step" should be used twice + int count = -1; + int dir = 1; // direction: 0 = incX, 1=incY, 2=decX, 3=decY + if (num < 8) { + return num; // trivial + } + for (int i = 8; i <= num; i++) + { + count++; + if (count == stepsize) { + count = 0; + // Change direction + dir++; + stepnumber++; + if (stepnumber == 2) { + stepsize -= 1; + stepnumber = 0; + } + if (dir == 4) { + dir = 0; + } + } + switch (dir) { + case 0: + findx++; + break; + case 1: + findy++; + break; + case 2: + findx--; + break; + case 3: + findy--; + break; + } + } + return xyToPos(findx, findy); } uint32_t wheel(byte WheelPos) { WheelPos = 255 - WheelPos; - if(WheelPos < 85) { + if (WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } - if(WheelPos < 170) { + if (WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } @@ -231,7 +281,7 @@ uint32_t wheel(byte WheelPos) { void led_fill(uint32_t c) { - for (int i=0; i < strip.numPixels(); i++) { + for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); } strip.show(); @@ -239,8 +289,8 @@ void led_fill(uint32_t c) void led_random() { - for (int i=0; i < strip.numPixels(); i++) { - strip.setPixelColor(i, wheel(random(0,255))); + for (int i = 0; i < strip.numPixels(); i++) { + strip.setPixelColor(i, wheel(random(0, 255))); } strip.show(); } @@ -248,10 +298,10 @@ void led_random() void showBuffer() { - for (int i=0; i < strip.numPixels(); i++) { - pixelR[i]=pixelR_buffer[i]; - pixelG[i]=pixelG_buffer[i]; - pixelB[i]=pixelB_buffer[i]; + for (int i = 0; i < strip.numPixels(); i++) { + pixelR[i] = pixelR_buffer[i]; + pixelG[i] = pixelG_buffer[i]; + pixelB[i] = pixelB_buffer[i]; strip.setPixelColor(i, pixelR[i], pixelG[i], pixelB[i]); } strip.show(); @@ -259,53 +309,53 @@ void showBuffer() uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) { - uint16_t sum=0; - uint8_t count=0; - if (i>=8){ //up - sum+=array[i-8]; + uint16_t sum = 0; + uint8_t count = 0; + if (i >= 8) { //up + sum += array[i - 8]; count++; } - if (i<(64-8)){ //down - sum+=array[i+8]; + if (i < (64 - 8)) { //down + sum += array[i + 8]; count++; } - if (i>=1){ //left - sum+=array[i-1]; + if (i >= 1) { //left + sum += array[i - 1]; count++; } - if (i<(64-1)){ //right - sum+=array[i+1]; + if (i < (64 - 1)) { //right + sum += array[i + 1]; count++; } /* - if (i>=(8+1)){ //up left + if (i>=(8+1)){ //up left sum+=array[i-8-1]; count++; - } - if (i<(64-8-1)){ //down left + } + if (i<(64-8-1)){ //down left sum+=array[i+8-1]; count++; - } - if (i>=(8-1)){ //up right + } + if (i>=(8-1)){ //up right sum+=array[i-8+1]; count++; - } - if (i<(64-8+1)){ //down right + } + if (i<(64-8+1)){ //down right sum+=array[i+8+1]; count++; - }*/ - return sum/count; + }*/ + return sum / count; } void led_smooth() { - for (int i=0; i < strip.numPixels(); i++) { + for (int i = 0; i < strip.numPixels(); i++) { //uint8_t avgbrightness=pixelR_buffer[i]/3+pixelG_buffer[i]/3+pixelB_buffer[i]/3; - pixelR_buffer[i]=(smoothing/100.0)*pixelR[i] + (1.0-(smoothing/100.0))*getAverage(pixelR,i, 0,0); - pixelG_buffer[i]=(smoothing/100.0)*pixelG[i] + (1.0-(smoothing/100.0))*getAverage(pixelG,i, 0,0); - pixelB_buffer[i]=(smoothing/100.0)*pixelB[i] + (1.0-(smoothing/100.0))*getAverage(pixelB,i, 0,0); + pixelR_buffer[i] = (smoothing / 100.0) * pixelR[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelR, i, 0, 0); + pixelG_buffer[i] = (smoothing / 100.0) * pixelG[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelG, i, 0, 0); + pixelB_buffer[i] = (smoothing / 100.0) * pixelB[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelB, i, 0, 0); } showBuffer(); @@ -313,149 +363,266 @@ void led_smooth() void led_movingPoint() { - uint32_t c=wheel(wheelPos); - wheelPosSlow+=wheelSpeed; - wheelPos=(wheelPos+ (wheelPosSlow/10) )%255; - wheelPosSlow=wheelPosSlow%16; - + uint32_t c = wheel(wheelPos); + wheelPosSlow += wheelSpeed; + wheelPos = (wheelPos + (wheelPosSlow / 10) ) % 255; + wheelPosSlow = wheelPosSlow % 16; + uint8_t r = (uint8_t)(c >> 16); uint8_t g = (uint8_t)(c >> 8); uint8_t b = (uint8_t)c; - movingPoint_x=movingPoint_x+8+random(-random(0,1+1),random(0,1+1)+1); - movingPoint_y=movingPoint_y+8+random(-random(0,1+1),random(0,1+1)+1); - if (movingPoint_x<8){ - movingPoint_x=8-movingPoint_x; - }else if (movingPoint_x>=16){ - movingPoint_x=22-movingPoint_x; - }else{ - movingPoint_x-=8; + movingPoint_x = movingPoint_x + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); + movingPoint_y = movingPoint_y + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); + if (movingPoint_x < 8) { + movingPoint_x = 8 - movingPoint_x; + } else if (movingPoint_x >= 16) { + movingPoint_x = 22 - movingPoint_x; + } else { + movingPoint_x -= 8; } - if (movingPoint_y<8){ - movingPoint_y=8-movingPoint_y; - }else if (movingPoint_y>=16){ - movingPoint_y=22-movingPoint_y; - }else{ - movingPoint_y-=8; + if (movingPoint_y < 8) { + movingPoint_y = 8 - movingPoint_y; + } else if (movingPoint_y >= 16) { + movingPoint_y = 22 - movingPoint_y; + } else { + movingPoint_y -= 8; } - uint8_t startx=movingPoint_x; - uint8_t starty=movingPoint_y; + uint8_t startx = movingPoint_x; + uint8_t starty = movingPoint_y; - for (int i=0;i=16){ - movingPoint_x=22-movingPoint_x; - }else{ - movingPoint_x-=8; + for (int i = 0; i < strength; i++) { + + movingPoint_x = startx + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); + movingPoint_y = starty + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); + + if (movingPoint_x < 8) { + movingPoint_x = 8 - movingPoint_x; + } else if (movingPoint_x >= 16) { + movingPoint_x = 22 - movingPoint_x; + } else { + movingPoint_x -= 8; } - - if (movingPoint_y<8){ - movingPoint_y=8-movingPoint_y; - }else if (movingPoint_y>=16){ - movingPoint_y=22-movingPoint_y; - }else{ - movingPoint_y-=8; + + if (movingPoint_y < 8) { + movingPoint_y = 8 - movingPoint_y; + } else if (movingPoint_y >= 16) { + movingPoint_y = 22 - movingPoint_y; + } else { + movingPoint_y -= 8; } - - if (pixelR[xyToPos(movingPoint_x,movingPoint_y)]r){ - pixelR[xyToPos(movingPoint_x,movingPoint_y)]--; + + if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] < r) { + pixelR[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] > r) { + pixelR[xyToPos(movingPoint_x, movingPoint_y)]--; } - if (pixelG[xyToPos(movingPoint_x,movingPoint_y)]g){ - pixelG[xyToPos(movingPoint_x,movingPoint_y)]--; + if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] < g) { + pixelG[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] > g) { + pixelG[xyToPos(movingPoint_x, movingPoint_y)]--; } - if (pixelB[xyToPos(movingPoint_x,movingPoint_y)]b){ - pixelB[xyToPos(movingPoint_x,movingPoint_y)]--; + if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] < b) { + pixelB[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] > b) { + pixelB[xyToPos(movingPoint_x, movingPoint_y)]--; } } - - + + //pixelR[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelR[xyToPos(movingPoint_x,movingPoint_y)]+0.5*r; //pixelG[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelG[xyToPos(movingPoint_x,movingPoint_y)]+0.5*g; //pixelB[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelB[xyToPos(movingPoint_x,movingPoint_y)]+0.5*b; - movingPoint_x=startx; - movingPoint_y=starty; - + movingPoint_x = startx; + movingPoint_y = starty; + } void bufferClear() { - for (int i=0; i < strip.numPixels(); i++) { - pixelR_buffer[i]=0; - pixelG_buffer[i]=0; - pixelB_buffer[i]=0; + for (int i = 0; i < strip.numPixels(); i++) { + pixelR_buffer[i] = 0; + pixelG_buffer[i] = 0; + pixelB_buffer[i] = 0; } } +void led_chase() +{ + Index += 1; + if (Index > 255) { + Index = 1; + } + // for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel + for (int q = 0; q < 3; q++) { + for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { + strip.setPixelColor(i + q, wheel( (i + Index) % 255)); //turn every third pixel on + } + strip.show(); + + delay(49); + + for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { + strip.setPixelColor(i + q, 0); //turn every third pixel off + } + } +} + + + +void led_radar() +{ + // "Sweep" in cirles... + // line(0,0,950*cos(radians(iAngle)),-950*sin(radians(iAngle))); +} + +// Calculate 50% dimmed version of a color (used by led_larson()) +uint32_t DimColor(uint32_t color) +{ + // Shift R, G and B components one bit to the right + uint32_t Dimcolor = strip.Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); + return Dimcolor; +} + +// Returns the Red component of a 32-bit color +uint8_t Red(uint32_t color) +{ + return (color >> 16) & 0xFF; +} + +// Returns the Green component of a 32-bit color +uint8_t Green(uint32_t color) +{ + return (color >> 8) & 0xFF; +} + +// Returns the Blue component of a 32-bit color +uint8_t Blue(uint32_t color) +{ + return color & 0xFF; +} + +void Increment() +{ + if (Direction == FORWARD) + { + Index++; + if (Index >= (strip.numPixels() - 1) * 2) + { + Index = 0; + } + } + else // Direction == REVERSE + { + --Index; + if (Index <= 0) + { + Index = (strip.numPixels() - 1) * 2 - 1; + } + } +} + + +void led_larson() +{ + int EyeSize = 5; + uint32_t rgb[3] = {0}; + wheelPos++; + if (wheelPos >= 256) { + wheelPos = 0; + } + int Color1 = wheel(wheelPos); + + for (int i = 0; i < strip.numPixels(); i++) + { + int realpos = numToSpiralPos(i); + if (i == Index) // Scan Pixel to the right + { + strip.setPixelColor(realpos, Color1); + } + else if (i == ((strip.numPixels() - 1) * 2) - Index) // Scan Pixel to the left + { + strip.setPixelColor(realpos, Color1); + } + else // Fading tail + { + strip.setPixelColor(realpos, DimColor(strip.getPixelColor(realpos))); + } + } + + strip.show(); + Increment(); +} + + void led_spiral() { + int every = 4; wheelPos++; - for (int i=0; i < strip.numPixels(); i++) { - //strip.setPixelColor(i,wheel((wheelPos+i*5)%255)); - - + int qp = Index % every; + Index++; + if (Index >= strip.numPixels()-1) { + Index = 0; + } + int q = Index % every; + for (uint16_t i = 0; i < strip.numPixels(); i = i + every) { + strip.setPixelColor(numToSpiralPos(i + q), wheel( (i + Index * 4) % 255)); //turn every "every" pixel on + } + for (uint16_t i = 0; i < strip.numPixels(); i = i + every) { + strip.setPixelColor(numToSpiralPos(i + qp), 0); //turn every "every" pixel off } strip.show(); + } void led_randomfade() { - for (int i=0; i < strip.numPixels(); i++) { - pixelR_buffer[i]+=random(0,random(0,fadespeedmax+1)+1); //use buffer red channel for color wheel - strip.setPixelColor(i,wheel(pixelR_buffer[i])); + for (int i = 0; i < strip.numPixels(); i++) { + pixelR_buffer[i] += random(0, random(0, fadespeedmax + 1) + 1); //use buffer red channel for color wheel + strip.setPixelColor(i, wheel(pixelR_buffer[i])); } strip.show(); } void led_icon(uint8_t fontchar, uint32_t iconcolor) { - for (int i=0; i < strip.numPixels(); i++) { - uint64_t mask=1LL<<(uint64_t)i; + for (int i = 0; i < strip.numPixels(); i++) { + uint64_t mask = 1LL << (uint64_t)i; - if ( (font[fontchar]&mask) == 0){ - strip.setPixelColor(numToPos(i),strip.Color(0, 0, 0)); //bit is 0 at pos i - }else{ + if ( (font[fontchar]&mask) == 0) { + strip.setPixelColor(numToPos(i), strip.Color(0, 0, 0)); //bit is 0 at pos i + } else { - float _brightness=1.0- ( (iconCountStart-iconCountdown)*1.0/iconCountStart ); - uint8_t _r=(uint8_t)(iconcolor >> 16); - uint8_t _g=(uint8_t)(iconcolor >> 8); - uint8_t _b=(uint8_t)iconcolor; - strip.setPixelColor(numToPos(i),strip.Color(_r*_brightness,_g*_brightness,_b*_brightness)); //bit is 1 at pos i + float _brightness = 1.0 - ( (iconCountStart - iconCountdown) * 1.0 / iconCountStart ); + uint8_t _r = (uint8_t)(iconcolor >> 16); + uint8_t _g = (uint8_t)(iconcolor >> 8); + uint8_t _b = (uint8_t)iconcolor; + strip.setPixelColor(numToPos(i), strip.Color(_r * _brightness, _g * _brightness, _b * _brightness)); //bit is 1 at pos i } - + } strip.show(); } void set_randomBuffer() { - for (int i=0; i < strip.numPixels(); i++) { - uint32_t c=wheel(random(0,256)); - pixelR_buffer[i]=(uint8_t)(c >> 16); - pixelG_buffer[i]=(uint8_t)(c >> 8); - pixelB_buffer[i]=(uint8_t)c; + for (int i = 0; i < strip.numPixels(); i++) { + uint32_t c = wheel(random(0, 256)); + pixelR_buffer[i] = (uint8_t)(c >> 16); + pixelG_buffer[i] = (uint8_t)(c >> 8); + pixelB_buffer[i] = (uint8_t)c; } } -uint32_t parseColor(String value){ - if (value.charAt(0)=='#'){ //solid fill - String color=value.substring(1); +uint32_t parseColor(String value) { + if (value.charAt(0) == '#') { //solid fill + String color = value.substring(1); int number = (int) strtol( &color[0], NULL, 16); - + // Split them up into r, g, b values int r = number >> 16; @@ -467,7 +634,7 @@ uint32_t parseColor(String value){ //Serial.print(" b=");Serial.println(b); return strip.Color(r, g, b); - } + } return 0; } @@ -476,124 +643,138 @@ bool effectHandler(const HomieRange& range, const String& value) { Homie.getLogger() << "-> " << value << endl; int sep = value.indexOf("|"); - String command=value.substring(0,sep); - String parameters=value.substring(sep+1); + String command = value.substring(0, sep); + String parameters = value.substring(sep + 1); Homie.getLogger() << "command=" << command << " parameters=" << parameters << endl; - - if (command.equals("fill")){ - effect=EFFECT_NONE; + + if (command.equals("fill")) { + effect = EFFECT_NONE; led_fill(parseColor(parameters)); - }else if (command.equals("off")){ - effect=EFFECT_NONE; + } else if (command.equals("off")) { + effect = EFFECT_NONE; led_fill(strip.Color(0, 0, 0)); - }else if (command.equals("random")){ - effect=EFFECT_NONE; + } else if (command.equals("random")) { + effect = EFFECT_NONE; led_random(); - }else if (command.equals("set")){ //example: set|37#ff003a - effect=EFFECT_NONE; - int x=parameters.substring(0,1).toInt(); - int y=parameters.substring(1,2).toInt(); - String cstr=parameters.substring(2,9); - strip.setPixelColor(xyToPos(x,y), parseColor(cstr)); + } else if (command.equals("set")) { //example: set|37#ff003a + effect = EFFECT_NONE; + int x = parameters.substring(0, 1).toInt(); + int y = parameters.substring(1, 2).toInt(); + String cstr = parameters.substring(2, 9); + strip.setPixelColor(xyToPos(x, y), parseColor(cstr)); strip.show(); - }else if (command.equals("smooth")){ //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 + } else if (command.equals("smooth")) { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 int sepparam = parameters.indexOf("|"); - int p1=parameters.substring(0,sepparam).toInt(); - String parameters_part2=parameters.substring(sepparam+1); + int p1 = parameters.substring(0, sepparam).toInt(); + String parameters_part2 = parameters.substring(sepparam + 1); sepparam = parameters_part2.indexOf("|"); - int p2=parameters_part2.substring(0,sepparam).toInt(); - int p3=parameters_part2.substring(sepparam+1).toInt(); - wheelSpeed=16; //default, speed=+1 /frame - if (p1>0){ - wheelSpeed=p1; + int p2 = parameters_part2.substring(0, sepparam).toInt(); + int p3 = parameters_part2.substring(sepparam + 1).toInt(); + wheelSpeed = 16; //default, speed=+1 /frame + if (p1 > 0) { + wheelSpeed = p1; } - smoothing=80; - if (p2>0){ - smoothing=p2; + smoothing = 80; + if (p2 > 0) { + smoothing = p2; } - strength=50; - if (p3>0){ - strength=p3; + strength = 50; + if (p3 > 0) { + strength = p3; } Homie.getLogger() << "-- p1=" << p1 << " p2=" << p2 << " p3=" << p3 << endl; - effect=EFFECT_SMOOTH; + effect = EFFECT_SMOOTH; bufferClear(); showBuffer(); strip.show(); - }else if (command.equals("spiral")){ - effect=EFFECT_SPIRAL; + } else if (command.equals("spiral")) { + effect = EFFECT_SPIRAL; + Index = 0; bufferClear(); showBuffer(); strip.show(); - }else if (command.equals("clearbuffer")){ + } else if (command.equals("clearbuffer")) { bufferClear(); showBuffer(); strip.show(); - }else if (command.equals("randomfade")){ //example: randomfade|5 + } else if (command.equals("randomfade")) { //example: randomfade|5 int sepparam = parameters.indexOf("|"); - int p1=parameters.substring(0,sepparam).toInt(); - fadespeedmax=5; - if (p1>0){ - fadespeedmax=p1; + int p1 = parameters.substring(0, sepparam).toInt(); + fadespeedmax = 5; + if (p1 > 0) { + fadespeedmax = p1; } - effect=EFFECT_RANDOMFADE; + effect = EFFECT_RANDOMFADE; set_randomBuffer(); //initialize random - }else if (command.equals("randombuffer")){ + } else if (command.equals("randombuffer")) { set_randomBuffer(); //set random showBuffer(); + } else if (command.equals("chase")) { + effect = EFFECT_CHASE; + bufferClear(); + showBuffer(); + strip.show(); + } else if (command.equals("radar")) { + effect = EFFECT_RADAR; + Index = 0; + bufferClear(); + showBuffer(); + strip.show(); + } else if (command.equals("larson")) { + effect = EFFECT_LARSON; + Index = 0; + bufferClear(); + showBuffer(); + strip.show(); } - - - - return true; } bool pixelsHandler(const HomieRange& range, const String& value) { - - String remaining=value; - int i=0; - effect=EFFECT_NONE; - do{ - String current=remaining.substring(0,7); + + String remaining = value; + int i = 0; + effect = EFFECT_NONE; + do { + String current = remaining.substring(0, 7); Homie.getLogger() << i << ":" << current << endl; - uint32_t currentcolor=parseColor(current); + uint32_t currentcolor = parseColor(current); strip.setPixelColor(i, currentcolor); i++; - - remaining=remaining.substring(7); - - }while(remaining.length()>2 && (i 2 && (i < strip.numPixels())); Homie.getLogger() << " filling rest with black" << endl; - while(i0){ //icon effect active - + if (lastMillis + fpsdelay < currentMillis) { + if (iconCountdown > 0) { //icon effect active iconCountdown--; - led_icon(iconchar,iconcolor); - - - - }else{ - - switch(effect){ + led_icon(iconchar, iconcolor); + } else { + switch (effect) { case EFFECT_SMOOTH: led_movingPoint(); led_smooth(); - break; + break; case EFFECT_SPIRAL: led_spiral(); - break; + break; case EFFECT_RANDOMFADE: led_randomfade(); - break; + break; + case EFFECT_CHASE: + led_chase(); + break; + case EFFECT_RADAR: + led_radar(); + break; + case EFFECT_LARSON: + led_larson(); + break; } - } - - lastMillis=currentMillis; + lastMillis = currentMillis; } - + } From 1e73f4d49f52bd3b00c725876bac9011670cea09 Mon Sep 17 00:00:00 2001 From: starcalc Date: Tue, 28 Feb 2017 22:56:04 +0100 Subject: [PATCH 02/14] NeoPatterns added, font extracted --- pixelprojektor/NeoPatterns.cpp | 293 +++++++++++++++++++++++++++++++++ pixelprojektor/NeoPatterns.h | 59 +++++++ pixelprojektor/font.h | 150 +++++++++++++++++ 3 files changed, 502 insertions(+) create mode 100644 pixelprojektor/NeoPatterns.cpp create mode 100644 pixelprojektor/NeoPatterns.h create mode 100644 pixelprojektor/font.h diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp new file mode 100644 index 0000000..91cea44 --- /dev/null +++ b/pixelprojektor/NeoPatterns.cpp @@ -0,0 +1,293 @@ +#include "NeoPatterns.h" + +NeoPatterns::NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()) : + Adafruit_NeoPixel(pixels, pin, type) +{ + OnComplete = callback; +} + +void NeoPatterns::Update(){ + if((millis() - lastUpdate) > Interval) // time to update + { + lastUpdate = millis(); + switch(ActivePattern) + { + case RAINBOW_CYCLE: + RainbowCycleUpdate(); + break; + case THEATER_CHASE: + TheaterChaseUpdate(); + break; + case COLOR_WIPE: + ColorWipeUpdate(); + break; + case SCANNER: + ScannerUpdate(); + break; + case FADE: + FadeUpdate(); + break; + case RANDOM_FADE: + RandomFadeUpdate(); + break; + case NONE: + break; + default: + break; + } + } +} + +void NeoPatterns::Increment() +{ + if (Direction == FORWARD) + { + Index++; + if (Index >= TotalSteps) + { + Index = 0; + if (OnComplete != NULL) + { + OnComplete(); // call the comlpetion callback + } + } + } + else // Direction == REVERSE + { + --Index; + if (Index <= 0) + { + Index = TotalSteps-1; + if (OnComplete != NULL) + { + OnComplete(); // call the comlpetion callback + } + } + } +} + +void NeoPatterns::Reverse(){ + if (Direction == FORWARD) + { + Direction = REVERSE; + Index = TotalSteps-1; + } + else + { + Direction = FORWARD; + Index = 0; + } +} + +void NeoPatterns::None(){ + if(ActivePattern != NONE) { + clear(); + show(); + } + ActivePattern = NONE; +} + +void NeoPatterns::RainbowCycle(uint8_t interval, direction dir){ + ActivePattern = RAINBOW_CYCLE; + Interval = interval; + TotalSteps = 255; + Index = 0; + Direction = dir; +} + +void NeoPatterns::RainbowCycleUpdate() +{ + for(int i=0; i< numPixels(); i++) + { + setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255)); + } + show(); + Increment(); +} + +void NeoPatterns::TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir){ + ActivePattern = THEATER_CHASE; + Interval = interval; + TotalSteps = numPixels(); + Color1 = color1; + Color2 = color2; + Index = 0; + Direction = dir; +} +void NeoPatterns::TheaterChaseUpdate(){ + for(int i=0; i< numPixels(); i++) + { + if ((i + Index) % 3 == 0) + { + setPixelColor(i, Color1); + } + else + { + setPixelColor(i, Color2); + } + } + show(); + Increment(); +} + +void NeoPatterns::ColorWipe(uint32_t color, uint8_t interval, direction dir) +{ + ActivePattern = COLOR_WIPE; + Interval = interval; + TotalSteps = numPixels(); + Color1 = color; + Index = 0; + Direction = dir; +} + +// Update the Color Wipe Pattern +void NeoPatterns::ColorWipeUpdate() +{ + setPixelColor(Index, Color1); + show(); + Increment(); +} + +// Initialize for a SCANNNER +void NeoPatterns::Scanner(uint32_t color1, uint8_t interval, bool colorful) +{ + ActivePattern = SCANNER; + Interval = interval; + TotalSteps = (numPixels() - 1) * 2; + Color1 = color1; + Index = 0; + wPos = 0; + this->colorful = colorful; +} + +// Update the Scanner Pattern +void NeoPatterns::ScannerUpdate() +{ + if(colorful) { + Color1 = Wheel(wPos); + if(wPos >= 255) { + wPos =0; + } + else { + wPos++; + } + } + for (int i = 0; i < numPixels(); i++) + { + if (i == Index) // Scan Pixel to the right + { + setPixelColor(i, Color1); + } + else if (i == TotalSteps - Index) // Scan Pixel to the left + { + setPixelColor(i, Color1); + } + else // Fading tail + { + setPixelColor(i, DimColor(getPixelColor(i))); + } + } + show(); + Increment(); + +} + +void NeoPatterns::Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir) +{ + ActivePattern = FADE; + Interval = interval; + TotalSteps = steps; + Color1 = color1; + Color2 = color2; + Index = 0; + Direction = dir; +} + +// Update the Fade Pattern +void NeoPatterns::FadeUpdate() +{ + // Calculate linear interpolation between Color1 and Color2 + // Optimise order of operations to minimize truncation error + uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps; + uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps; + uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps; + + ColorSet(Color(red, green, blue)); + show(); + Increment(); +} + +void NeoPatterns::RandomFade(uint8_t interval ){ + ActivePattern = RANDOM_FADE; + Interval = interval; + TotalSteps = 255; + Index = 0; +} +void NeoPatterns::RandomFadeUpdate(){ + ColorSet(Wheel(Index)); + Increment(); +} + +void NeoPatterns::SetColor1(uint32_t color){ + Color1 = color; +} +void NeoPatterns::SetColor2(uint32_t color){ + Color2 = color; +} + +// Calculate 50% dimmed version of a color (used by ScannerUpdate) +uint32_t NeoPatterns::DimColor(uint32_t color) +{ + // Shift R, G and B components one bit to the right + uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); + return dimColor; +} + +// Set all pixels to a color (synchronously) +void NeoPatterns::ColorSet(uint32_t color) +{ + for (int i = 0; i < numPixels(); i++) + { + setPixelColor(i, color); + } + show(); +} + +// Returns the Red component of a 32-bit color +uint8_t NeoPatterns::Red(uint32_t color) +{ + return (color >> 16) & 0xFF; +} + +// Returns the Green component of a 32-bit color +uint8_t NeoPatterns::Green(uint32_t color) +{ + return (color >> 8) & 0xFF; +} + +// Returns the Blue component of a 32-bit color +uint8_t NeoPatterns::Blue(uint32_t color) +{ + return color & 0xFF; +} + +// Input a value 0 to 255 to get a color value. +// The colours are a transition r - g - b - back to r. +uint32_t NeoPatterns::Wheel(byte WheelPos) +{ + WheelPos = 255 - WheelPos; + if(WheelPos < 85) + { + return Color(255 - WheelPos * 3, 0, WheelPos * 3); + } + else if(WheelPos < 170) + { + WheelPos -= 85; + return Color(0, WheelPos * 3, 255 - WheelPos * 3); + } + else + { + WheelPos -= 170; + return Color(WheelPos * 3, 255 - WheelPos * 3, 0); + } +} diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h new file mode 100644 index 0000000..68e470b --- /dev/null +++ b/pixelprojektor/NeoPatterns.h @@ -0,0 +1,59 @@ +#include + +// Pattern types supported: +enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE }; +// Patern directions supported: +enum direction { FORWARD, REVERSE }; + +class NeoPatterns : public Adafruit_NeoPixel +{ +public: +NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()); + +void Update(); + +void Reverse(); +void None(); +void RainbowCycle(uint8_t interval, direction dir = FORWARD); +void RainbowCycleUpdate(); +void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD); +void TheaterChaseUpdate(); +void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD); +void ColorWipeUpdate(); +void Scanner(uint32_t color1, uint8_t interval = 40,bool colorful = false); +void ScannerUpdate(); +void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD); +void FadeUpdate(); +void RandomFade(uint8_t interval = 100); +void RandomFadeUpdate(); + +void SetColor1(uint32_t color); +void SetColor2(uint32_t color); +//Utilities +void ColorSet(uint32_t color); +uint8_t Red(uint32_t color); +uint8_t Green(uint32_t color); +uint8_t Blue(uint32_t color); +uint32_t Wheel(byte WheelPos); + +private: + +// Member Variables: +pattern ActivePattern; // which pattern is running +direction Direction; // direction to run the pattern + +unsigned long Interval; // milliseconds between updates +unsigned long lastUpdate; // last update of position + +uint32_t Color1, Color2; // What colors are in use +uint16_t TotalSteps; // total number of steps in the pattern +uint16_t Index; // current step within the pattern + +byte wPos; +bool colorful; + +uint32_t DimColor(uint32_t color); +void Increment(); +void (*OnComplete)(); // Callback on completion of pattern + +}; diff --git a/pixelprojektor/font.h b/pixelprojektor/font.h new file mode 100644 index 0000000..9b2094c --- /dev/null +++ b/pixelprojektor/font.h @@ -0,0 +1,150 @@ + +/* the values in this array are a 8x8 bitmap font for ascii characters */ +static uint64_t font[128] = { + /************************************************************************ + font.c + Copyright (C) Lisa Milne 2014 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + ************************************************************************/ + 0x7E7E7E7E7E7E0000, /* NUL */ + 0x7E7E7E7E7E7E0000, /* SOH */ + 0x7E7E7E7E7E7E0000, /* STX */ + 0x7E7E7E7E7E7E0000, /* ETX */ + 0x7E7E7E7E7E7E0000, /* EOT */ + 0x7E7E7E7E7E7E0000, /* ENQ */ + 0x7E7E7E7E7E7E0000, /* ACK */ + 0x7E7E7E7E7E7E0000, /* BEL */ + 0x7E7E7E7E7E7E0000, /* BS */ + 0x0, /* TAB */ + 0x7E7E7E7E7E7E0000, /* LF */ + 0x7E7E7E7E7E7E0000, /* VT */ + 0x7E7E7E7E7E7E0000, /* FF */ + 0x7E7E7E7E7E7E0000, /* CR */ + 0x7E7E7E7E7E7E0000, /* SO */ + 0x7E7E7E7E7E7E0000, /* SI */ + 0x7E7E7E7E7E7E0000, /* DLE */ + 0x7E7E7E7E7E7E0000, /* DC1 */ + 0x7E7E7E7E7E7E0000, /* DC2 */ + 0x7E7E7E7E7E7E0000, /* DC3 */ + 0x7E7E7E7E7E7E0000, /* DC4 */ + 0x7E7E7E7E7E7E0000, /* NAK */ + 0x7E7E7E7E7E7E0000, /* SYN */ + 0x7E7E7E7E7E7E0000, /* ETB */ + 0x7E7E7E7E7E7E0000, /* CAN */ + 0x7E7E7E7E7E7E0000, /* EM */ + 0x7E7E7E7E7E7E0000, /* SUB */ + 0x7E7E7E7E7E7E0000, /* ESC */ + 0x7E7E7E7E7E7E0000, /* FS */ + 0x7E7E7E7E7E7E0000, /* GS */ + 0x7E7E7E7E7E7E0000, /* RS */ + 0x7E7E7E7E7E7E0000, /* US */ + 0x0, /* (space) */ + 0x808080800080000, /* ! */ + 0x2828000000000000, /* " */ + 0x287C287C280000, /* # */ + 0x81E281C0A3C0800, /* $ */ + 0x6094681629060000, /* % */ + 0x1C20201926190000, /* & */ + 0x808000000000000, /* ' */ + 0x810202010080000, /* ( */ + 0x1008040408100000, /* ) */ + 0x2A1C3E1C2A000000, /* * */ + 0x8083E08080000, /* + */ + 0x81000, /* , */ + 0x3C00000000, /* - */ + 0x80000, /* . */ + 0x204081020400000, /* / */ + 0x1824424224180000, /* 0 */ + 0x8180808081C0000, /* 1 */ + 0x3C420418207E0000, /* 2 */ + 0x3C420418423C0000, /* 3 */ + 0x81828487C080000, /* 4 */ + 0x7E407C02423C0000, /* 5 */ + 0x3C407C42423C0000, /* 6 */ + 0x7E04081020400000, /* 7 */ + 0x3C423C42423C0000, /* 8 */ + 0x3C42423E023C0000, /* 9 */ + 0x80000080000, /* : */ + 0x80000081000, /* ; */ + 0x6186018060000, /* < */ + 0x7E007E000000, /* = */ + 0x60180618600000, /* > */ + 0x3844041800100000, /* ? */ + 0x3C449C945C201C, /* @ */ + 0x1818243C42420000, /* A */ + 0x7844784444780000, /* B */ + 0x3844808044380000, /* C */ + 0x7844444444780000, /* D */ + 0x7C407840407C0000, /* E */ + 0x7C40784040400000, /* F */ + 0x3844809C44380000, /* G */ + 0x42427E4242420000, /* H */ + 0x3E080808083E0000, /* I */ + 0x1C04040444380000, /* J */ + 0x4448507048440000, /* K */ + 0x40404040407E0000, /* L */ + 0x4163554941410000, /* M */ + 0x4262524A46420000, /* N */ + 0x1C222222221C0000, /* O */ + 0x7844784040400000, /* P */ + 0x1C222222221C0200, /* Q */ + 0x7844785048440000, /* R */ + 0x1C22100C221C0000, /* S */ + 0x7F08080808080000, /* T */ + 0x42424242423C0000, /* U */ + 0x8142422424180000, /* V */ + 0x4141495563410000, /* W */ + 0x4224181824420000, /* X */ + 0x4122140808080000, /* Y */ + 0x7E040810207E0000, /* Z */ + 0x3820202020380000, /* [ */ + 0x4020100804020000, /* */ + 0x3808080808380000, /* ] */ + 0x1028000000000000, /* ^ */ + 0x7E0000, /* _ */ + 0x1008000000000000, /* ` */ + 0x3C023E463A0000, /* a */ + 0x40407C42625C0000, /* b */ + 0x1C20201C0000, /* c */ + 0x2023E42463A0000, /* d */ + 0x3C427E403C0000, /* e */ + 0x18103810100000, /* f */ + 0x344C44340438, /* g */ + 0x2020382424240000, /* h */ + 0x800080808080000, /* i */ + 0x800180808080870, /* j */ + 0x20202428302C0000, /* k */ + 0x1010101010180000, /* l */ + 0x665A42420000, /* m */ + 0x2E3222220000, /* n */ + 0x3C42423C0000, /* o */ + 0x5C62427C4040, /* p */ + 0x3A46423E0202, /* q */ + 0x2C3220200000, /* r */ + 0x1C201804380000, /* s */ + 0x103C1010180000, /* t */ + 0x2222261A0000, /* u */ + 0x424224180000, /* v */ + 0x81815A660000, /* w */ + 0x422418660000, /* x */ + 0x422214081060, /* y */ + 0x3C08103C0000, /* z */ + 0x1C103030101C0000, /* { */ + 0x808080808080800, /* | */ + 0x38080C0C08380000, /* } */ + 0x324C000000, /* ~ */ + 0x7E7E7E7E7E7E0000 /* DEL */ +}; + From 8160c4e83cc62197201b883ad4438e204fbd3c47 Mon Sep 17 00:00:00 2001 From: starcalc Date: Tue, 28 Feb 2017 22:57:30 +0100 Subject: [PATCH 03/14] NeoPatterns added, font extracted --- pixelprojektor/pixelprojektor.ino | 152 +----------------------------- 1 file changed, 2 insertions(+), 150 deletions(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index 8ff47e5..aa31426 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -2,6 +2,8 @@ // homie lib from: https://github.com/marvinroger/homie-esp8266/ #include #include +#include "NeoPatterns.h" +#include "font.h" #ifdef __AVR__ #include #endif @@ -37,160 +39,10 @@ int32_t iconcolor = 0; //last icon color uint16_t Index; // current step within the pattern // int Index = 0; // Step for Effect (e.g. chase) // int state = 0; // Direction for Larson Scanner (spiral) -enum direction { FORWARD, REVERSE }; // Direction direction Direction; // direction to run the pattern -/* the values in this array are a 8x8 bitmap font for ascii characters */ -static uint64_t font[128] = { - /************************************************************************ - font.c - Copyright (C) Lisa Milne 2014 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - ************************************************************************/ - 0x7E7E7E7E7E7E0000, /* NUL */ - 0x7E7E7E7E7E7E0000, /* SOH */ - 0x7E7E7E7E7E7E0000, /* STX */ - 0x7E7E7E7E7E7E0000, /* ETX */ - 0x7E7E7E7E7E7E0000, /* EOT */ - 0x7E7E7E7E7E7E0000, /* ENQ */ - 0x7E7E7E7E7E7E0000, /* ACK */ - 0x7E7E7E7E7E7E0000, /* BEL */ - 0x7E7E7E7E7E7E0000, /* BS */ - 0x0, /* TAB */ - 0x7E7E7E7E7E7E0000, /* LF */ - 0x7E7E7E7E7E7E0000, /* VT */ - 0x7E7E7E7E7E7E0000, /* FF */ - 0x7E7E7E7E7E7E0000, /* CR */ - 0x7E7E7E7E7E7E0000, /* SO */ - 0x7E7E7E7E7E7E0000, /* SI */ - 0x7E7E7E7E7E7E0000, /* DLE */ - 0x7E7E7E7E7E7E0000, /* DC1 */ - 0x7E7E7E7E7E7E0000, /* DC2 */ - 0x7E7E7E7E7E7E0000, /* DC3 */ - 0x7E7E7E7E7E7E0000, /* DC4 */ - 0x7E7E7E7E7E7E0000, /* NAK */ - 0x7E7E7E7E7E7E0000, /* SYN */ - 0x7E7E7E7E7E7E0000, /* ETB */ - 0x7E7E7E7E7E7E0000, /* CAN */ - 0x7E7E7E7E7E7E0000, /* EM */ - 0x7E7E7E7E7E7E0000, /* SUB */ - 0x7E7E7E7E7E7E0000, /* ESC */ - 0x7E7E7E7E7E7E0000, /* FS */ - 0x7E7E7E7E7E7E0000, /* GS */ - 0x7E7E7E7E7E7E0000, /* RS */ - 0x7E7E7E7E7E7E0000, /* US */ - 0x0, /* (space) */ - 0x808080800080000, /* ! */ - 0x2828000000000000, /* " */ - 0x287C287C280000, /* # */ - 0x81E281C0A3C0800, /* $ */ - 0x6094681629060000, /* % */ - 0x1C20201926190000, /* & */ - 0x808000000000000, /* ' */ - 0x810202010080000, /* ( */ - 0x1008040408100000, /* ) */ - 0x2A1C3E1C2A000000, /* * */ - 0x8083E08080000, /* + */ - 0x81000, /* , */ - 0x3C00000000, /* - */ - 0x80000, /* . */ - 0x204081020400000, /* / */ - 0x1824424224180000, /* 0 */ - 0x8180808081C0000, /* 1 */ - 0x3C420418207E0000, /* 2 */ - 0x3C420418423C0000, /* 3 */ - 0x81828487C080000, /* 4 */ - 0x7E407C02423C0000, /* 5 */ - 0x3C407C42423C0000, /* 6 */ - 0x7E04081020400000, /* 7 */ - 0x3C423C42423C0000, /* 8 */ - 0x3C42423E023C0000, /* 9 */ - 0x80000080000, /* : */ - 0x80000081000, /* ; */ - 0x6186018060000, /* < */ - 0x7E007E000000, /* = */ - 0x60180618600000, /* > */ - 0x3844041800100000, /* ? */ - 0x3C449C945C201C, /* @ */ - 0x1818243C42420000, /* A */ - 0x7844784444780000, /* B */ - 0x3844808044380000, /* C */ - 0x7844444444780000, /* D */ - 0x7C407840407C0000, /* E */ - 0x7C40784040400000, /* F */ - 0x3844809C44380000, /* G */ - 0x42427E4242420000, /* H */ - 0x3E080808083E0000, /* I */ - 0x1C04040444380000, /* J */ - 0x4448507048440000, /* K */ - 0x40404040407E0000, /* L */ - 0x4163554941410000, /* M */ - 0x4262524A46420000, /* N */ - 0x1C222222221C0000, /* O */ - 0x7844784040400000, /* P */ - 0x1C222222221C0200, /* Q */ - 0x7844785048440000, /* R */ - 0x1C22100C221C0000, /* S */ - 0x7F08080808080000, /* T */ - 0x42424242423C0000, /* U */ - 0x8142422424180000, /* V */ - 0x4141495563410000, /* W */ - 0x4224181824420000, /* X */ - 0x4122140808080000, /* Y */ - 0x7E040810207E0000, /* Z */ - 0x3820202020380000, /* [ */ - 0x4020100804020000, /* */ - 0x3808080808380000, /* ] */ - 0x1028000000000000, /* ^ */ - 0x7E0000, /* _ */ - 0x1008000000000000, /* ` */ - 0x3C023E463A0000, /* a */ - 0x40407C42625C0000, /* b */ - 0x1C20201C0000, /* c */ - 0x2023E42463A0000, /* d */ - 0x3C427E403C0000, /* e */ - 0x18103810100000, /* f */ - 0x344C44340438, /* g */ - 0x2020382424240000, /* h */ - 0x800080808080000, /* i */ - 0x800180808080870, /* j */ - 0x20202428302C0000, /* k */ - 0x1010101010180000, /* l */ - 0x665A42420000, /* m */ - 0x2E3222220000, /* n */ - 0x3C42423C0000, /* o */ - 0x5C62427C4040, /* p */ - 0x3A46423E0202, /* q */ - 0x2C3220200000, /* r */ - 0x1C201804380000, /* s */ - 0x103C1010180000, /* t */ - 0x2222261A0000, /* u */ - 0x424224180000, /* v */ - 0x81815A660000, /* w */ - 0x422418660000, /* x */ - 0x422214081060, /* y */ - 0x3C08103C0000, /* z */ - 0x1C103030101C0000, /* { */ - 0x808080808080800, /* | */ - 0x38080C0C08380000, /* } */ - 0x324C000000, /* ~ */ - 0x7E7E7E7E7E7E0000 /* DEL */ -}; - Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); From 8fd25937d5a2ee3d69a67ce40f664d8127929347 Mon Sep 17 00:00:00 2001 From: starcalc Date: Tue, 28 Feb 2017 23:00:16 +0100 Subject: [PATCH 04/14] Small test (URL removed) --- pixelprojektor/pixelprojektor.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index aa31426..cea4080 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -1,5 +1,4 @@ #include -// homie lib from: https://github.com/marvinroger/homie-esp8266/ #include #include #include "NeoPatterns.h" @@ -9,7 +8,6 @@ #endif #define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) - #define NUMPIXELS 64 #define FPS 15 From 99e5762296e5b262987a78a70ff9eb0b82891b4a Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 00:02:17 +0100 Subject: [PATCH 05/14] Refactoring: scanner, randomscanner (color-changing scanner), larsonspiral, none working --- pixelprojektor/NeoPatterns.cpp | 478 +++++++++++++++++------------- pixelprojektor/NeoPatterns.h | 81 ++--- pixelprojektor/pixelprojektor.ino | 226 +++++++++++--- 3 files changed, 496 insertions(+), 289 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index 91cea44..8b834fe 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -1,293 +1,363 @@ #include "NeoPatterns.h" NeoPatterns::NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()) : - Adafruit_NeoPixel(pixels, pin, type) + Adafruit_NeoPixel(pixels, pin, type) { - OnComplete = callback; + OnComplete = callback; } -void NeoPatterns::Update(){ - if((millis() - lastUpdate) > Interval) // time to update - { - lastUpdate = millis(); - switch(ActivePattern) - { - case RAINBOW_CYCLE: - RainbowCycleUpdate(); - break; - case THEATER_CHASE: - TheaterChaseUpdate(); - break; - case COLOR_WIPE: - ColorWipeUpdate(); - break; - case SCANNER: - ScannerUpdate(); - break; - case FADE: - FadeUpdate(); - break; - case RANDOM_FADE: - RandomFadeUpdate(); - break; - case NONE: - break; - default: - break; - } - } +void NeoPatterns::Update() { + if ((millis() - lastUpdate) > Interval) // time to update + { + lastUpdate = millis(); + switch (ActivePattern) + { + case RAINBOW_CYCLE: + RainbowCycleUpdate(); + break; + case THEATER_CHASE: + TheaterChaseUpdate(); + break; + case COLOR_WIPE: + ColorWipeUpdate(); + break; + case SCANNER: + ScannerUpdate(); + break; + case FADE: + FadeUpdate(); + break; + case RANDOM_FADE: + RandomFadeUpdate(); + break; + case NONE: + break; + default: + break; + } + } } void NeoPatterns::Increment() { - if (Direction == FORWARD) - { - Index++; - if (Index >= TotalSteps) - { - Index = 0; - if (OnComplete != NULL) - { - OnComplete(); // call the comlpetion callback - } - } - } - else // Direction == REVERSE - { - --Index; - if (Index <= 0) - { - Index = TotalSteps-1; - if (OnComplete != NULL) - { - OnComplete(); // call the comlpetion callback - } - } - } + if (Direction == FORWARD) + { + Index++; + if (Index >= TotalSteps) + { + Index = 0; + if (OnComplete != NULL) + { + OnComplete(); // call the comlpetion callback + } + } + } + else // Direction == REVERSE + { + --Index; + if (Index <= 0) + { + Index = TotalSteps - 1; + if (OnComplete != NULL) + { + OnComplete(); // call the comlpetion callback + } + } + } } -void NeoPatterns::Reverse(){ - if (Direction == FORWARD) - { - Direction = REVERSE; - Index = TotalSteps-1; - } - else - { - Direction = FORWARD; - Index = 0; - } +void NeoPatterns::Reverse() { + if (Direction == FORWARD) + { + Direction = REVERSE; + Index = TotalSteps - 1; + } + else + { + Direction = FORWARD; + Index = 0; + } } -void NeoPatterns::None(){ - if(ActivePattern != NONE) { - clear(); - show(); - } - ActivePattern = NONE; +void NeoPatterns::None() { + if (ActivePattern != NONE) { + clear(); + show(); + } + ActivePattern = NONE; } -void NeoPatterns::RainbowCycle(uint8_t interval, direction dir){ - ActivePattern = RAINBOW_CYCLE; - Interval = interval; - TotalSteps = 255; - Index = 0; - Direction = dir; +/****************** Effects ******************/ + +void NeoPatterns::RainbowCycle(uint8_t interval, direction dir) { + ActivePattern = RAINBOW_CYCLE; + Interval = interval; + TotalSteps = 255; + Index = 0; + Direction = dir; } void NeoPatterns::RainbowCycleUpdate() { - for(int i=0; i< numPixels(); i++) - { - setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255)); - } - show(); - Increment(); + for (int i = 0; i < numPixels(); i++) + { + setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255)); + } + show(); + Increment(); } -void NeoPatterns::TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir){ - ActivePattern = THEATER_CHASE; - Interval = interval; - TotalSteps = numPixels(); - Color1 = color1; - Color2 = color2; - Index = 0; - Direction = dir; +void NeoPatterns::TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir) { + ActivePattern = THEATER_CHASE; + Interval = interval; + TotalSteps = numPixels(); + Color1 = color1; + Color2 = color2; + Index = 0; + Direction = dir; } -void NeoPatterns::TheaterChaseUpdate(){ - for(int i=0; i< numPixels(); i++) - { - if ((i + Index) % 3 == 0) - { - setPixelColor(i, Color1); - } - else - { - setPixelColor(i, Color2); - } - } - show(); - Increment(); +void NeoPatterns::TheaterChaseUpdate() { + for (int i = 0; i < numPixels(); i++) + { + if ((i + Index) % 3 == 0) + { + setPixelColor(i, Color1); + } + else + { + setPixelColor(i, Color2); + } + } + show(); + Increment(); } void NeoPatterns::ColorWipe(uint32_t color, uint8_t interval, direction dir) { - ActivePattern = COLOR_WIPE; - Interval = interval; - TotalSteps = numPixels(); - Color1 = color; - Index = 0; - Direction = dir; + ActivePattern = COLOR_WIPE; + Interval = interval; + TotalSteps = numPixels(); + Color1 = color; + Index = 0; + Direction = dir; } // Update the Color Wipe Pattern void NeoPatterns::ColorWipeUpdate() { - setPixelColor(Index, Color1); - show(); - Increment(); + setPixelColor(Index, Color1); + show(); + Increment(); } // Initialize for a SCANNNER -void NeoPatterns::Scanner(uint32_t color1, uint8_t interval, bool colorful) +void NeoPatterns::Scanner(uint32_t color1, uint8_t interval, bool colorful, bool spiral) { - ActivePattern = SCANNER; - Interval = interval; - TotalSteps = (numPixels() - 1) * 2; - Color1 = color1; - Index = 0; - wPos = 0; - this->colorful = colorful; + ActivePattern = SCANNER; + Interval = interval; + TotalSteps = (numPixels() - 1) * 2; + Color1 = color1; + Index = 0; + wPos = 0; + this->colorful = colorful; + this->spiral = spiral; } // Update the Scanner Pattern void NeoPatterns::ScannerUpdate() { - if(colorful) { - Color1 = Wheel(wPos); - if(wPos >= 255) { - wPos =0; - } - else { - wPos++; - } - } - for (int i = 0; i < numPixels(); i++) - { - if (i == Index) // Scan Pixel to the right - { - setPixelColor(i, Color1); - } - else if (i == TotalSteps - Index) // Scan Pixel to the left - { - setPixelColor(i, Color1); - } - else // Fading tail - { - setPixelColor(i, DimColor(getPixelColor(i))); - } - } - show(); - Increment(); + if (colorful) { + Color1 = Wheel(wPos); + if (wPos >= 255) { + wPos = 0; + } + else { + wPos++; + } + } + for (int i = 0; i < numPixels(); i++) + { + int finalpos; + if (spiral) { + finalpos = numToSpiralPos(i); + } + else + { + finalpos=i; + } + if (i == Index) // Scan Pixel to the right + { + setPixelColor(finalpos, Color1); + } + else if (i == TotalSteps - Index) // Scan Pixel to the left + { + setPixelColor(finalpos, Color1); + } + else // Fading tail + { + setPixelColor(finalpos, DimColor(getPixelColor(finalpos))); + } + } + show(); + Increment(); } void NeoPatterns::Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir) { - ActivePattern = FADE; - Interval = interval; - TotalSteps = steps; - Color1 = color1; - Color2 = color2; - Index = 0; - Direction = dir; + ActivePattern = FADE; + Interval = interval; + TotalSteps = steps; + Color1 = color1; + Color2 = color2; + Index = 0; + Direction = dir; } // Update the Fade Pattern void NeoPatterns::FadeUpdate() { - // Calculate linear interpolation between Color1 and Color2 - // Optimise order of operations to minimize truncation error - uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps; - uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps; - uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps; + // Calculate linear interpolation between Color1 and Color2 + // Optimise order of operations to minimize truncation error + uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps; + uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps; + uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps; - ColorSet(Color(red, green, blue)); - show(); - Increment(); + ColorSet(Color(red, green, blue)); + show(); + Increment(); } -void NeoPatterns::RandomFade(uint8_t interval ){ - ActivePattern = RANDOM_FADE; - Interval = interval; - TotalSteps = 255; - Index = 0; +void NeoPatterns::RandomFade(uint8_t interval ) { + ActivePattern = RANDOM_FADE; + Interval = interval; + TotalSteps = 255; + Index = 0; } -void NeoPatterns::RandomFadeUpdate(){ - ColorSet(Wheel(Index)); - Increment(); +void NeoPatterns::RandomFadeUpdate() { + ColorSet(Wheel(Index)); + Increment(); } -void NeoPatterns::SetColor1(uint32_t color){ - Color1 = color; +/****************** Helper functions ******************/ + +void NeoPatterns::SetColor1(uint32_t color) { + Color1 = color; } -void NeoPatterns::SetColor2(uint32_t color){ - Color2 = color; +void NeoPatterns::SetColor2(uint32_t color) { + Color2 = color; } // Calculate 50% dimmed version of a color (used by ScannerUpdate) uint32_t NeoPatterns::DimColor(uint32_t color) { - // Shift R, G and B components one bit to the right - uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); - return dimColor; + // Shift R, G and B components one bit to the right + uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); + return dimColor; } // Set all pixels to a color (synchronously) void NeoPatterns::ColorSet(uint32_t color) { - for (int i = 0; i < numPixels(); i++) - { - setPixelColor(i, color); - } - show(); + for (int i = 0; i < numPixels(); i++) + { + setPixelColor(i, color); + } + show(); } // Returns the Red component of a 32-bit color uint8_t NeoPatterns::Red(uint32_t color) { - return (color >> 16) & 0xFF; + return (color >> 16) & 0xFF; } // Returns the Green component of a 32-bit color uint8_t NeoPatterns::Green(uint32_t color) { - return (color >> 8) & 0xFF; + return (color >> 8) & 0xFF; } // Returns the Blue component of a 32-bit color uint8_t NeoPatterns::Blue(uint32_t color) { - return color & 0xFF; + return color & 0xFF; } // Input a value 0 to 255 to get a color value. -// The colours are a transition r - g - b - back to r. +// The colors are a transition r - g - b - back to r. uint32_t NeoPatterns::Wheel(byte WheelPos) { - WheelPos = 255 - WheelPos; - if(WheelPos < 85) - { - return Color(255 - WheelPos * 3, 0, WheelPos * 3); - } - else if(WheelPos < 170) - { - WheelPos -= 85; - return Color(0, WheelPos * 3, 255 - WheelPos * 3); - } - else - { - WheelPos -= 170; - return Color(WheelPos * 3, 255 - WheelPos * 3, 0); - } + WheelPos = 255 - WheelPos; + if (WheelPos < 85) + { + return Color(255 - WheelPos * 3, 0, WheelPos * 3); + } + else if (WheelPos < 170) + { + WheelPos -= 85; + return Color(0, WheelPos * 3, 255 - WheelPos * 3); + } + else + { + WheelPos -= 170; + return Color(WheelPos * 3, 255 - WheelPos * 3, 0); + } } + +// Convert x y pixel position to matrix position +uint8_t NeoPatterns::xyToPos(int x, int y) { + if (y % 2 == 0) { + return (y * 8 + x); + } else { + return (y * 8 + (7 - x)); + } +} + +// Convert pixel number to actual 8x8 matrix position in a spiral +uint8_t NeoPatterns::numToSpiralPos(int num) { + int edge = (int)sqrt(numPixels()); + int findx = edge-1; // 7 + int findy = 0; + int stepsize = edge-1; // initial value (0..7) + int stepnumber = 0; // each "step" should be used twice + int count = -1; + int dir = 1; // direction: 0 = incX, 1=incY, 2=decX, 3=decY + if (num < edge) { + return num; // trivial + } + for (int i = edge; i <= num; i++) + { + count++; + if (count == stepsize) { + count = 0; + // Change direction + dir++; + stepnumber++; + if (stepnumber == 2) { + stepsize -= 1; + stepnumber = 0; + } + if (dir == 4) { + dir = 0; + } + } + switch (dir) { + case 0: + findx++; + break; + case 1: + findy++; + break; + case 2: + findx--; + break; + case 3: + findy--; + break; + } + } + return xyToPos(findx, findy); +} + + diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index 68e470b..032f217 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -7,53 +7,56 @@ enum direction { FORWARD, REVERSE }; class NeoPatterns : public Adafruit_NeoPixel { -public: -NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()); + public: + NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)()); -void Update(); + void Update(); -void Reverse(); -void None(); -void RainbowCycle(uint8_t interval, direction dir = FORWARD); -void RainbowCycleUpdate(); -void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD); -void TheaterChaseUpdate(); -void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD); -void ColorWipeUpdate(); -void Scanner(uint32_t color1, uint8_t interval = 40,bool colorful = false); -void ScannerUpdate(); -void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD); -void FadeUpdate(); -void RandomFade(uint8_t interval = 100); -void RandomFadeUpdate(); + void Reverse(); + void None(); + void RainbowCycle(uint8_t interval, direction dir = FORWARD); + void RainbowCycleUpdate(); + void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD); + void TheaterChaseUpdate(); + void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD); + void ColorWipeUpdate(); + void Scanner(uint32_t color1, uint8_t interval = 40, bool colorful = false, bool spiral = false); + void ScannerUpdate(); + void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD); + void FadeUpdate(); + void RandomFade(uint8_t interval = 100); + void RandomFadeUpdate(); -void SetColor1(uint32_t color); -void SetColor2(uint32_t color); -//Utilities -void ColorSet(uint32_t color); -uint8_t Red(uint32_t color); -uint8_t Green(uint32_t color); -uint8_t Blue(uint32_t color); -uint32_t Wheel(byte WheelPos); + void SetColor1(uint32_t color); + void SetColor2(uint32_t color); + //Utilities + void ColorSet(uint32_t color); + uint8_t Red(uint32_t color); + uint8_t Green(uint32_t color); + uint8_t Blue(uint32_t color); + uint32_t Wheel(byte WheelPos); + uint8_t numToSpiralPos(int num); + uint8_t xyToPos(int x, int y); -private: + private: -// Member Variables: -pattern ActivePattern; // which pattern is running -direction Direction; // direction to run the pattern + // Member Variables: + pattern ActivePattern; // which pattern is running + direction Direction; // direction to run the pattern -unsigned long Interval; // milliseconds between updates -unsigned long lastUpdate; // last update of position + unsigned long Interval; // milliseconds between updates + unsigned long lastUpdate; // last update of position -uint32_t Color1, Color2; // What colors are in use -uint16_t TotalSteps; // total number of steps in the pattern -uint16_t Index; // current step within the pattern + uint32_t Color1, Color2; // What colors are in use + uint16_t TotalSteps; // total number of steps in the pattern + uint16_t Index; // current step within the pattern -byte wPos; -bool colorful; + byte wPos; + bool colorful; + bool spiral; -uint32_t DimColor(uint32_t color); -void Increment(); -void (*OnComplete)(); // Callback on completion of pattern + uint32_t DimColor(uint32_t color); + void Increment(); + void (*OnComplete)(); // Callback on completion of pattern }; diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index cea4080..db365b8 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -10,11 +10,177 @@ #define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 -#define FPS 15 +void StripComplete() { + return; +} +NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); + +HomieNode homieNode("pixel", "commands"); + + +bool onSetColor(const HomieRange& range, const String& value){ + if (!range.isRange || range.index < 0 || range.index > 1) { + return false; + } + switch(range.index) { + case 0: + strip.SetColor1(value.toInt()); + break; + case 1: + strip.SetColor2(value.toInt()); + break; + } + homieNode.setProperty("color_" + String(range.index)).send(value); +} + +bool onSetPixel(const HomieRange& range, const String& value){ + if(!range.isRange) { + strip.None(); + strip.ColorSet(value.toInt()); + homieNode.setProperty("pixel").send(value); + return true; + } + if (range.index < 0 || range.index > strip.numPixels()-1) { + return false; + } + strip.None(); + strip.setPixelColor(range.index, value.toInt()); + strip.show(); + homieNode.setProperty("pixel_" + String(range.index)).send(value); +} + +bool onSetBrightness(const HomieRange& range, const String& value){ + long brightness= value.toInt(); + if (brightness < 0 || brightness > 255) { + return false; + } + strip.setBrightness(brightness); + strip.show(); + homieNode.setProperty("brightness").send(value); +} + +bool onSetEffect(const HomieRange& range, const String& value){ + String effect = value; + effect.toLowerCase(); + if(effect == "scanner") { + strip.Scanner(strip.Color(255, 0, 0)); + } + else if(effect == "randomscanner") { + strip.Scanner(strip.Color(255, 0, 0), 40, true); + } + else if(effect == "larsonspiral") { + strip.Scanner(strip.Color(255, 0, 0), 40, true, true); + } + else if(effect == "rainbowcycle") { + strip.RainbowCycle(50); + } + else if(effect == "theaterchase") { + strip.TheaterChase(strip.Color(255, 0, 0), strip.Color(0,0,255), 100); + } + else if(effect == "fade") { + strip.Fade(strip.Color(255, 0, 0), strip.Color(0,0,255), 200, 100); + } + else if(effect == "randomfade") { + strip.RandomFade(); + } + else { + strip.None(); + } + homieNode.setProperty("effect").send(value); +} + +bool onSetClear(const HomieRange& range, const String& value){ + strip.None(); + strip.clear(); + strip.show(); + homieNode.setProperty("clear").send(value); +} + +bool onSetLength(const HomieRange& range, const String& value){ + strip.None(); + strip.clear(); + strip.show(); + int newLength = value.toInt(); + if(newLength > 0) { + strip.updateLength(newLength); + } + homieNode.setProperty("length").send(value); +} + +void loopHandler() { + strip.Update(); + +} + +void setup() { + Serial.begin(115200); + + Homie_setFirmware("pixelprojektor", "1.0.0"); + Homie.setLoopFunction(loopHandler); + + homieNode.advertiseRange("pixel", 0, NUMPIXELS-1).settable(onSetPixel); + homieNode.advertiseRange("color", 0, 1).settable(onSetColor); + homieNode.advertise("brightness").settable(onSetBrightness); + homieNode.advertise("effect").settable(onSetEffect); + homieNode.advertise("clear").settable(onSetClear); + homieNode.advertise("length").settable(onSetLength); + + strip.begin(); + strip.clear(); + strip.setBrightness(64); + strip.show(); + + Homie.setup(); + + ArduinoOTA.setHostname("pixelprojektor"); + ArduinoOTA.onStart([]() { + strip.clear(); + }); + ArduinoOTA.onEnd([]() { + strip.clear(); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + strip.setPixelColor(progress / (total / NUMPIXELS), strip.Color(100, 0, 0)); + strip.show(); + }); + ArduinoOTA.begin(); +} + +void loop() { + Homie.loop(); + ArduinoOTA.handle(); +} + +// Diese Effekte müssen nach dem Umbau wieder vorhanden sein: +/* + case EFFECT_SMOOTH: + led_movingPoint(); + led_smooth(); + break; + case EFFECT_SPIRAL: + led_spiral(); + break; + case EFFECT_RANDOMFADE: + led_randomfade(); + break; + case EFFECT_CHASE: + led_chase(); + break; + case EFFECT_RADAR: + led_radar(); + break; + case EFFECT_LARSON: + led_larson(); + break; +*/ + + + +/************ Old stuff ************/ +/* +#define FPS 15 uint8_t effect = 0; -#define EFFECT_NONE 0 -#define EFFECT_SMOOTH 1 uint8_t movingPoint_x = 3; uint8_t movingPoint_y = 3; uint8_t wheelPos = 0; @@ -22,13 +188,14 @@ uint8_t wheelPosSlow = 0; //for slower wheelPos increment than 1 int wheelSpeed = 16; //16=+1/frame int smoothing = 80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. int strength = 50; //how much pixels to apply color to +#define EFFECT_NONE 0 +#define EFFECT_SMOOTH 1 #define EFFECT_SPIRAL 2 #define EFFECT_RANDOMFADE 3 #define EFFECT_CHASE 4 #define EFFECT_RADAR 5 #define EFFECT_LARSON 6 int fadespeedmax = 5; //1 to 255 - int iconCountStart = 0; //for percentage calculation int iconCountdown = 0; //0=off uint8_t iconchar = 0; //last displayed char @@ -38,14 +205,6 @@ uint16_t Index; // current step within the pattern // int Index = 0; // Step for Effect (e.g. chase) // int state = 0; // Direction for Larson Scanner (spiral) direction Direction; // direction to run the pattern - - - - -Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); - -HomieNode homieNode("pixel", "commands"); - uint8_t pixelR[NUMPIXELS]; uint8_t pixelG[NUMPIXELS]; uint8_t pixelB[NUMPIXELS]; @@ -57,6 +216,7 @@ uint8_t pixelB_buffer[NUMPIXELS]; long lastMillis = 0; long fpsdelay = 1000 / FPS; + int xyToPos(int x, int y) { //convert x y pixel position to matrix position if (y % 2 == 0) { return (y * 8 + x); @@ -72,16 +232,17 @@ int numToPos(int num) { //convert pixel number to actual 8x8 matrix position } int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix position in a spiral - int findx = 7; + int edge = (int)sqrt(NUMPIXELS); + int findx = edge-1; // 7 int findy = 0; - int stepsize = 7; // initial value (0..7) + int stepsize = edge-1; // initial value (0..7) int stepnumber = 0; // each "step" should be used twice int count = -1; int dir = 1; // direction: 0 = incX, 1=incY, 2=decX, 3=decY - if (num < 8) { + if (num < edge) { return num; // trivial } - for (int i = 8; i <= num; i++) + for (int i = edge; i <= num; i++) { count++; if (count == stepsize) { @@ -177,24 +338,6 @@ uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) sum += array[i + 1]; count++; } - - /* - if (i>=(8+1)){ //up left - sum+=array[i-8-1]; - count++; - } - if (i<(64-8-1)){ //down left - sum+=array[i+8-1]; - count++; - } - if (i>=(8-1)){ //up right - sum+=array[i-8+1]; - count++; - } - if (i<(64-8+1)){ //down right - sum+=array[i+8+1]; - count++; - }*/ return sum / count; } @@ -414,7 +557,7 @@ void led_spiral() wheelPos++; int qp = Index % every; Index++; - if (Index >= strip.numPixels()-1) { + if (Index >= strip.numPixels() - 1) { Index = 0; } int q = Index % every; @@ -673,7 +816,7 @@ void setup() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - strip.setPixelColor(numToPos((progress / (total / strip.numPixels()))), strip.Color(255, 255, 255)); + strip.setPixelColor(numToPos((progress / (total / strip.numPixels()))), strip.Color(100, 0, 0)); strip.show(); Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); @@ -687,11 +830,6 @@ void setup() { }); ArduinoOTA.begin(); - // led_fill(strip.Color(0, 0, 0)); - - // Initialer Effekt - //effect = EFFECT_CHASE; - //effect = EFFECT_SPIRAL; effect = EFFECT_LARSON; Serial << "Setup finished" << endl; @@ -736,8 +874,4 @@ void loop() { } - - - - - +*/ From 408b9d3671b749bd4a3530c071914ef235b06798 Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 16:21:34 +0100 Subject: [PATCH 06/14] Refactor: Effect smooth now working. --- pixelprojektor/NeoPatterns.cpp | 158 ++++++++++- pixelprojektor/NeoPatterns.h | 18 +- pixelprojektor/pixelprojektor.ino | 445 +++++++++++++++--------------- 3 files changed, 389 insertions(+), 232 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index 8b834fe..4a66080 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -4,6 +4,14 @@ NeoPatterns::NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*call Adafruit_NeoPixel(pixels, pin, type) { OnComplete = callback; + // TODO: Arrays hier initialisieren mit konkreten Werten? Und in der NeoPatterns.h nur der Platzhalter? + //Allocate a zero initialized block of memory big enough to hold "pixels" uint8_t. + pixelR = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelG = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelB = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelR_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelG_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelB_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); } void NeoPatterns::Update() { @@ -30,6 +38,9 @@ void NeoPatterns::Update() { case RANDOM_FADE: RandomFadeUpdate(); break; + case SMOOTH: + SmoothUpdate(); + break; case NONE: break; default: @@ -48,7 +59,7 @@ void NeoPatterns::Increment() Index = 0; if (OnComplete != NULL) { - OnComplete(); // call the comlpetion callback + OnComplete(); // call the completion callback } } } @@ -60,7 +71,7 @@ void NeoPatterns::Increment() Index = TotalSteps - 1; if (OnComplete != NULL) { - OnComplete(); // call the comlpetion callback + OnComplete(); // call the completion callback } } } @@ -180,10 +191,10 @@ void NeoPatterns::ScannerUpdate() int finalpos; if (spiral) { finalpos = numToSpiralPos(i); - } + } else { - finalpos=i; + finalpos = i; } if (i == Index) // Scan Pixel to the right { @@ -239,6 +250,114 @@ void NeoPatterns::RandomFadeUpdate() { Increment(); } +void NeoPatterns::Smooth(uint8_t wheelSpeed, uint8_t smoothing, uint8_t strength, uint8_t interval) { + ActivePattern = SMOOTH; + Interval = interval; + TotalSteps = 1000; // Beim Smooth nicht sinnvoll? + Index = 0; + WheelSpeed = wheelSpeed; + Smoothing = smoothing; + Strength = strength; + movingPoint_x = 3; + movingPoint_y = 3; + // Clear buffer (from previous or different effects) + for (int i = 0; i < numPixels(); i++) { + pixelR_buffer[i] = 0; + pixelG_buffer[i] = 0; + pixelB_buffer[i] = 0; + } +} + +void NeoPatterns::SmoothUpdate() { + uint32_t c = Wheel(wPos); + wPosSlow += WheelSpeed; + wPos = (wPos + (wPosSlow / 10) ) % 255; + wPosSlow = wPosSlow % 16; + + uint8_t r = (uint8_t)(c >> 16); + uint8_t g = (uint8_t)(c >> 8); + uint8_t b = (uint8_t)c; + + movingPoint_x = movingPoint_x + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); + movingPoint_y = movingPoint_y + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); + if (movingPoint_x < 8) { + movingPoint_x = 8 - movingPoint_x; + } else if (movingPoint_x >= 16) { + movingPoint_x = 22 - movingPoint_x; + } else { + movingPoint_x -= 8; + } + + if (movingPoint_y < 8) { + movingPoint_y = 8 - movingPoint_y; + } else if (movingPoint_y >= 16) { + movingPoint_y = 22 - movingPoint_y; + } else { + movingPoint_y -= 8; + } + uint8_t startx = movingPoint_x; + uint8_t starty = movingPoint_y; + + for (int i = 0; i < Strength; i++) { + + movingPoint_x = startx + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); + movingPoint_y = starty + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); + + if (movingPoint_x < 8) { + movingPoint_x = 8 - movingPoint_x; + } else if (movingPoint_x >= 16) { + movingPoint_x = 22 - movingPoint_x; + } else { + movingPoint_x -= 8; + } + + if (movingPoint_y < 8) { + movingPoint_y = 8 - movingPoint_y; + } else if (movingPoint_y >= 16) { + movingPoint_y = 22 - movingPoint_y; + } else { + movingPoint_y -= 8; + } + + if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] < r) { + pixelR[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] > r) { + pixelR[xyToPos(movingPoint_x, movingPoint_y)]--; + } + if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] < g) { + pixelG[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] > g) { + pixelG[xyToPos(movingPoint_x, movingPoint_y)]--; + } + if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] < b) { + pixelB[xyToPos(movingPoint_x, movingPoint_y)]++; + } else if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] > b) { + pixelB[xyToPos(movingPoint_x, movingPoint_y)]--; + } + } + + movingPoint_x = startx; + movingPoint_y = starty; + + for (int i = 0; i < numPixels(); i++) { + pixelR_buffer[i] = (Smoothing / 100.0) * pixelR[i] + (1.0 - (Smoothing / 100.0)) * getAverage(pixelR, i, 0, 0); + pixelG_buffer[i] = (Smoothing / 100.0) * pixelG[i] + (1.0 - (Smoothing / 100.0)) * getAverage(pixelG, i, 0, 0); + pixelB_buffer[i] = (Smoothing / 100.0) * pixelB[i] + (1.0 - (Smoothing / 100.0)) * getAverage(pixelB, i, 0, 0); + + } + + for (int i = 0; i < numPixels(); i++) { + pixelR[i] = pixelR_buffer[i]; + pixelG[i] = pixelG_buffer[i]; + pixelB[i] = pixelB_buffer[i]; + setPixelColor(i, pixelR[i], pixelG[i], pixelB[i]); + } + + show(); + Increment(); + +} + /****************** Helper functions ******************/ void NeoPatterns::SetColor1(uint32_t color) { @@ -306,7 +425,7 @@ uint32_t NeoPatterns::Wheel(byte WheelPos) } // Convert x y pixel position to matrix position -uint8_t NeoPatterns::xyToPos(int x, int y) { +uint8_t NeoPatterns::xyToPos(int x, int y) { if (y % 2 == 0) { return (y * 8 + x); } else { @@ -315,11 +434,11 @@ uint8_t NeoPatterns::xyToPos(int x, int y) { } // Convert pixel number to actual 8x8 matrix position in a spiral -uint8_t NeoPatterns::numToSpiralPos(int num) { +uint8_t NeoPatterns::numToSpiralPos(int num) { int edge = (int)sqrt(numPixels()); - int findx = edge-1; // 7 + int findx = edge - 1; // 7 int findy = 0; - int stepsize = edge-1; // initial value (0..7) + int stepsize = edge - 1; // initial value (0..7) int stepnumber = 0; // each "step" should be used twice int count = -1; int dir = 1; // direction: 0 = incX, 1=incY, 2=decX, 3=decY @@ -360,4 +479,25 @@ uint8_t NeoPatterns::numToSpiralPos(int num) { return xyToPos(findx, findy); } - +uint8_t NeoPatterns::getAverage(uint8_t array[], uint8_t i, int x, int y) +{ + uint16_t sum = 0; + uint8_t count = 0; + if (i >= 8) { //up + sum += array[i - 8]; + count++; + } + if (i < (64 - 8)) { //down + sum += array[i + 8]; + count++; + } + if (i >= 1) { //left + sum += array[i - 1]; + count++; + } + if (i < (64 - 1)) { //right + sum += array[i + 1]; + count++; + } + return sum / count; +} diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index 032f217..a546cc4 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -1,7 +1,7 @@ #include // Pattern types supported: -enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE }; +enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH }; // Patern directions supported: enum direction { FORWARD, REVERSE }; @@ -26,6 +26,8 @@ class NeoPatterns : public Adafruit_NeoPixel void FadeUpdate(); void RandomFade(uint8_t interval = 100); void RandomFadeUpdate(); + void Smooth(uint8_t wheelSpeed, uint8_t smoothing, uint8_t strength, uint8_t interval); + void SmoothUpdate(); void SetColor1(uint32_t color); void SetColor2(uint32_t color); @@ -37,7 +39,7 @@ class NeoPatterns : public Adafruit_NeoPixel uint32_t Wheel(byte WheelPos); uint8_t numToSpiralPos(int num); uint8_t xyToPos(int x, int y); - + uint8_t getAverage(uint8_t array[], uint8_t i, int x, int y); private: // Member Variables: @@ -54,6 +56,18 @@ class NeoPatterns : public Adafruit_NeoPixel byte wPos; bool colorful; bool spiral; + uint8_t wPosSlow; + uint8_t WheelSpeed; + uint8_t Smoothing; + uint8_t Strength; + uint8_t movingPoint_x; + uint8_t movingPoint_y; + uint8_t *pixelR; + uint8_t *pixelG; + uint8_t *pixelB; + uint8_t *pixelR_buffer; + uint8_t *pixelG_buffer; + uint8_t *pixelB_buffer; uint32_t DimColor(uint32_t color); void Increment(); diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index db365b8..79d8c92 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -19,137 +19,140 @@ NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComp HomieNode homieNode("pixel", "commands"); -bool onSetColor(const HomieRange& range, const String& value){ - if (!range.isRange || range.index < 0 || range.index > 1) { - return false; - } - switch(range.index) { - case 0: - strip.SetColor1(value.toInt()); - break; - case 1: - strip.SetColor2(value.toInt()); - break; - } - homieNode.setProperty("color_" + String(range.index)).send(value); +bool onSetColor(const HomieRange& range, const String& value) { + if (!range.isRange || range.index < 0 || range.index > 1) { + return false; + } + switch (range.index) { + case 0: + strip.SetColor1(value.toInt()); + break; + case 1: + strip.SetColor2(value.toInt()); + break; + } + homieNode.setProperty("color_" + String(range.index)).send(value); } -bool onSetPixel(const HomieRange& range, const String& value){ - if(!range.isRange) { - strip.None(); - strip.ColorSet(value.toInt()); - homieNode.setProperty("pixel").send(value); - return true; - } - if (range.index < 0 || range.index > strip.numPixels()-1) { - return false; - } - strip.None(); - strip.setPixelColor(range.index, value.toInt()); - strip.show(); - homieNode.setProperty("pixel_" + String(range.index)).send(value); +bool onSetPixel(const HomieRange& range, const String& value) { + if (!range.isRange) { + strip.None(); + strip.ColorSet(value.toInt()); + homieNode.setProperty("pixel").send(value); + return true; + } + if (range.index < 0 || range.index > strip.numPixels() - 1) { + return false; + } + strip.None(); + strip.setPixelColor(range.index, value.toInt()); + strip.show(); + homieNode.setProperty("pixel_" + String(range.index)).send(value); } -bool onSetBrightness(const HomieRange& range, const String& value){ - long brightness= value.toInt(); - if (brightness < 0 || brightness > 255) { - return false; - } - strip.setBrightness(brightness); - strip.show(); - homieNode.setProperty("brightness").send(value); +bool onSetBrightness(const HomieRange& range, const String& value) { + long brightness = value.toInt(); + if (brightness < 0 || brightness > 255) { + return false; + } + strip.setBrightness(brightness); + strip.show(); + homieNode.setProperty("brightness").send(value); } -bool onSetEffect(const HomieRange& range, const String& value){ - String effect = value; - effect.toLowerCase(); - if(effect == "scanner") { - strip.Scanner(strip.Color(255, 0, 0)); - } - else if(effect == "randomscanner") { - strip.Scanner(strip.Color(255, 0, 0), 40, true); - } - else if(effect == "larsonspiral") { - strip.Scanner(strip.Color(255, 0, 0), 40, true, true); - } - else if(effect == "rainbowcycle") { - strip.RainbowCycle(50); - } - else if(effect == "theaterchase") { - strip.TheaterChase(strip.Color(255, 0, 0), strip.Color(0,0,255), 100); - } - else if(effect == "fade") { - strip.Fade(strip.Color(255, 0, 0), strip.Color(0,0,255), 200, 100); - } - else if(effect == "randomfade") { - strip.RandomFade(); - } - else { - strip.None(); - } - homieNode.setProperty("effect").send(value); +bool onSetEffect(const HomieRange& range, const String& value) { + String effect = value; + effect.toLowerCase(); + if (effect == "scanner") { + strip.Scanner(strip.Color(255, 0, 0)); + } + else if (effect == "randomscanner") { + strip.Scanner(strip.Color(255, 0, 0), 40, true); + } + else if (effect == "larsonspiral") { + strip.Scanner(strip.Color(255, 0, 0), 40, true, true); + } + else if (effect == "rainbowcycle") { + strip.RainbowCycle(50); + } + else if (effect == "theaterchase") { + strip.TheaterChase(strip.Color(255, 0, 0), strip.Color(0, 0, 255), 100); + } + else if (effect == "fade") { + strip.Fade(strip.Color(255, 0, 0), strip.Color(0, 0, 255), 200, 100); + } + else if (effect == "randomfade") { + strip.RandomFade(); + } + else if (effect == "smooth") { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 + strip.Smooth(16, 80, 50, 40); + } + else { + strip.None(); + } + homieNode.setProperty("effect").send(value); } -bool onSetClear(const HomieRange& range, const String& value){ - strip.None(); - strip.clear(); - strip.show(); - homieNode.setProperty("clear").send(value); +bool onSetClear(const HomieRange& range, const String& value) { + strip.None(); + strip.clear(); + strip.show(); + homieNode.setProperty("clear").send(value); } -bool onSetLength(const HomieRange& range, const String& value){ - strip.None(); - strip.clear(); - strip.show(); - int newLength = value.toInt(); - if(newLength > 0) { - strip.updateLength(newLength); - } - homieNode.setProperty("length").send(value); +bool onSetLength(const HomieRange& range, const String& value) { + strip.None(); + strip.clear(); + strip.show(); + int newLength = value.toInt(); + if (newLength > 0) { + strip.updateLength(newLength); + } + homieNode.setProperty("length").send(value); } void loopHandler() { - strip.Update(); + strip.Update(); } void setup() { - Serial.begin(115200); + Serial.begin(115200); - Homie_setFirmware("pixelprojektor", "1.0.0"); - Homie.setLoopFunction(loopHandler); + Homie_setFirmware("pixelprojektor", "1.0.0"); + Homie.setLoopFunction(loopHandler); - homieNode.advertiseRange("pixel", 0, NUMPIXELS-1).settable(onSetPixel); - homieNode.advertiseRange("color", 0, 1).settable(onSetColor); - homieNode.advertise("brightness").settable(onSetBrightness); - homieNode.advertise("effect").settable(onSetEffect); - homieNode.advertise("clear").settable(onSetClear); - homieNode.advertise("length").settable(onSetLength); + homieNode.advertiseRange("pixel", 0, NUMPIXELS - 1).settable(onSetPixel); + homieNode.advertiseRange("color", 0, 1).settable(onSetColor); + homieNode.advertise("brightness").settable(onSetBrightness); + homieNode.advertise("effect").settable(onSetEffect); + homieNode.advertise("clear").settable(onSetClear); + homieNode.advertise("length").settable(onSetLength); - strip.begin(); - strip.clear(); - strip.setBrightness(64); - strip.show(); + strip.begin(); + strip.clear(); + strip.setBrightness(64); + strip.show(); - Homie.setup(); + Homie.setup(); - ArduinoOTA.setHostname("pixelprojektor"); - ArduinoOTA.onStart([]() { - strip.clear(); - }); - ArduinoOTA.onEnd([]() { - strip.clear(); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - strip.setPixelColor(progress / (total / NUMPIXELS), strip.Color(100, 0, 0)); - strip.show(); - }); - ArduinoOTA.begin(); + ArduinoOTA.setHostname("pixelprojektor"); + ArduinoOTA.onStart([]() { + strip.clear(); + }); + ArduinoOTA.onEnd([]() { + strip.clear(); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + strip.setPixelColor(progress / (total / NUMPIXELS), strip.Color(100, 0, 0)); + strip.show(); + }); + ArduinoOTA.begin(); } void loop() { - Homie.loop(); - ArduinoOTA.handle(); + Homie.loop(); + ArduinoOTA.handle(); } // Diese Effekte müssen nach dem Umbau wieder vorhanden sein: @@ -179,59 +182,59 @@ void loop() { /************ Old stuff ************/ /* -#define FPS 15 -uint8_t effect = 0; -uint8_t movingPoint_x = 3; -uint8_t movingPoint_y = 3; -uint8_t wheelPos = 0; -uint8_t wheelPosSlow = 0; //for slower wheelPos increment than 1 -int wheelSpeed = 16; //16=+1/frame -int smoothing = 80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. -int strength = 50; //how much pixels to apply color to -#define EFFECT_NONE 0 -#define EFFECT_SMOOTH 1 -#define EFFECT_SPIRAL 2 -#define EFFECT_RANDOMFADE 3 -#define EFFECT_CHASE 4 -#define EFFECT_RADAR 5 -#define EFFECT_LARSON 6 -int fadespeedmax = 5; //1 to 255 -int iconCountStart = 0; //for percentage calculation -int iconCountdown = 0; //0=off -uint8_t iconchar = 0; //last displayed char -int32_t iconcolor = 0; //last icon color + #define FPS 15 + uint8_t effect = 0; + uint8_t movingPoint_x = 3; + uint8_t movingPoint_y = 3; + uint8_t wheelPos = 0; + uint8_t wheelPosSlow = 0; //for slower wheelPos increment than 1 + int wheelSpeed = 16; //16=+1/frame + int smoothing = 80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. + int strength = 50; //how much pixels to apply color to + #define EFFECT_NONE 0 + #define EFFECT_SMOOTH 1 + #define EFFECT_SPIRAL 2 + #define EFFECT_RANDOMFADE 3 + #define EFFECT_CHASE 4 + #define EFFECT_RADAR 5 + #define EFFECT_LARSON 6 + int fadespeedmax = 5; //1 to 255 + int iconCountStart = 0; //for percentage calculation + int iconCountdown = 0; //0=off + uint8_t iconchar = 0; //last displayed char + int32_t iconcolor = 0; //last icon color -uint16_t Index; // current step within the pattern -// int Index = 0; // Step for Effect (e.g. chase) -// int state = 0; // Direction for Larson Scanner (spiral) -direction Direction; // direction to run the pattern -uint8_t pixelR[NUMPIXELS]; -uint8_t pixelG[NUMPIXELS]; -uint8_t pixelB[NUMPIXELS]; -//write to buffer, flip with showBuffer() -uint8_t pixelR_buffer[NUMPIXELS]; -uint8_t pixelG_buffer[NUMPIXELS]; -uint8_t pixelB_buffer[NUMPIXELS]; + uint16_t Index; // current step within the pattern + // int Index = 0; // Step for Effect (e.g. chase) + // int state = 0; // Direction for Larson Scanner (spiral) + direction Direction; // direction to run the pattern + uint8_t pixelR[NUMPIXELS]; + uint8_t pixelG[NUMPIXELS]; + uint8_t pixelB[NUMPIXELS]; + //write to buffer, flip with showBuffer() + uint8_t pixelR_buffer[NUMPIXELS]; + uint8_t pixelG_buffer[NUMPIXELS]; + uint8_t pixelB_buffer[NUMPIXELS]; -long lastMillis = 0; -long fpsdelay = 1000 / FPS; + long lastMillis = 0; + long fpsdelay = 1000 / FPS; -int xyToPos(int x, int y) { //convert x y pixel position to matrix position + int xyToPos(int x, int y) { //convert x y pixel position to matrix position if (y % 2 == 0) { return (y * 8 + x); } else { return (y * 8 + (7 - x)); } -} + } -int numToPos(int num) { //convert pixel number to actual 8x8 matrix position + int numToPos(int num) { //convert pixel number to actual 8x8 matrix position int x = num % 8; int y = num / 8; return xyToPos(x, y); -} + } -int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix position in a spiral + int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix position in a spiral int edge = (int)sqrt(NUMPIXELS); int findx = edge-1; // 7 int findy = 0; @@ -274,9 +277,9 @@ int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix posit } } return xyToPos(findx, findy); -} + } -uint32_t wheel(byte WheelPos) { + uint32_t wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if (WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); @@ -287,28 +290,28 @@ uint32_t wheel(byte WheelPos) { } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); -} + } -void led_fill(uint32_t c) -{ + void led_fill(uint32_t c) + { for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); } strip.show(); -} + } -void led_random() -{ + void led_random() + { for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, wheel(random(0, 255))); } strip.show(); -} + } -void showBuffer() -{ + void showBuffer() + { for (int i = 0; i < strip.numPixels(); i++) { pixelR[i] = pixelR_buffer[i]; pixelG[i] = pixelG_buffer[i]; @@ -316,10 +319,10 @@ void showBuffer() strip.setPixelColor(i, pixelR[i], pixelG[i], pixelB[i]); } strip.show(); -} + } -uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) -{ + uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) + { uint16_t sum = 0; uint8_t count = 0; if (i >= 8) { //up @@ -339,11 +342,11 @@ uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) count++; } return sum / count; -} + } -void led_smooth() -{ + void led_smooth() + { for (int i = 0; i < strip.numPixels(); i++) { //uint8_t avgbrightness=pixelR_buffer[i]/3+pixelG_buffer[i]/3+pixelB_buffer[i]/3; pixelR_buffer[i] = (smoothing / 100.0) * pixelR[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelR, i, 0, 0); @@ -352,10 +355,10 @@ void led_smooth() } showBuffer(); -} + } -void led_movingPoint() -{ + void led_movingPoint() + { uint32_t c = wheel(wheelPos); wheelPosSlow += wheelSpeed; wheelPos = (wheelPos + (wheelPosSlow / 10) ) % 255; @@ -433,18 +436,18 @@ void led_movingPoint() movingPoint_x = startx; movingPoint_y = starty; -} -void bufferClear() -{ + } + void bufferClear() + { for (int i = 0; i < strip.numPixels(); i++) { pixelR_buffer[i] = 0; pixelG_buffer[i] = 0; pixelB_buffer[i] = 0; } -} + } -void led_chase() -{ + void led_chase() + { Index += 1; if (Index > 255) { Index = 1; @@ -462,44 +465,44 @@ void led_chase() strip.setPixelColor(i + q, 0); //turn every third pixel off } } -} + } -void led_radar() -{ + void led_radar() + { // "Sweep" in cirles... // line(0,0,950*cos(radians(iAngle)),-950*sin(radians(iAngle))); -} + } -// Calculate 50% dimmed version of a color (used by led_larson()) -uint32_t DimColor(uint32_t color) -{ + // Calculate 50% dimmed version of a color (used by led_larson()) + uint32_t DimColor(uint32_t color) + { // Shift R, G and B components one bit to the right uint32_t Dimcolor = strip.Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); return Dimcolor; -} + } -// Returns the Red component of a 32-bit color -uint8_t Red(uint32_t color) -{ + // Returns the Red component of a 32-bit color + uint8_t Red(uint32_t color) + { return (color >> 16) & 0xFF; -} + } -// Returns the Green component of a 32-bit color -uint8_t Green(uint32_t color) -{ + // Returns the Green component of a 32-bit color + uint8_t Green(uint32_t color) + { return (color >> 8) & 0xFF; -} + } -// Returns the Blue component of a 32-bit color -uint8_t Blue(uint32_t color) -{ + // Returns the Blue component of a 32-bit color + uint8_t Blue(uint32_t color) + { return color & 0xFF; -} + } -void Increment() -{ + void Increment() + { if (Direction == FORWARD) { Index++; @@ -516,11 +519,11 @@ void Increment() Index = (strip.numPixels() - 1) * 2 - 1; } } -} + } -void led_larson() -{ + void led_larson() + { int EyeSize = 5; uint32_t rgb[3] = {0}; wheelPos++; @@ -548,11 +551,11 @@ void led_larson() strip.show(); Increment(); -} + } -void led_spiral() -{ + void led_spiral() + { int every = 4; wheelPos++; int qp = Index % every; @@ -569,19 +572,19 @@ void led_spiral() } strip.show(); -} + } -void led_randomfade() -{ + void led_randomfade() + { for (int i = 0; i < strip.numPixels(); i++) { pixelR_buffer[i] += random(0, random(0, fadespeedmax + 1) + 1); //use buffer red channel for color wheel strip.setPixelColor(i, wheel(pixelR_buffer[i])); } strip.show(); -} + } -void led_icon(uint8_t fontchar, uint32_t iconcolor) -{ + void led_icon(uint8_t fontchar, uint32_t iconcolor) + { for (int i = 0; i < strip.numPixels(); i++) { uint64_t mask = 1LL << (uint64_t)i; @@ -598,20 +601,20 @@ void led_icon(uint8_t fontchar, uint32_t iconcolor) } strip.show(); -} + } -void set_randomBuffer() -{ + void set_randomBuffer() + { for (int i = 0; i < strip.numPixels(); i++) { uint32_t c = wheel(random(0, 256)); pixelR_buffer[i] = (uint8_t)(c >> 16); pixelG_buffer[i] = (uint8_t)(c >> 8); pixelB_buffer[i] = (uint8_t)c; } -} + } -uint32_t parseColor(String value) { + uint32_t parseColor(String value) { if (value.charAt(0) == '#') { //solid fill String color = value.substring(1); int number = (int) strtol( &color[0], NULL, 16); @@ -629,10 +632,10 @@ uint32_t parseColor(String value) { } return 0; -} + } -bool effectHandler(const HomieRange& range, const String& value) { + bool effectHandler(const HomieRange& range, const String& value) { Homie.getLogger() << "-> " << value << endl; int sep = value.indexOf("|"); @@ -721,9 +724,9 @@ bool effectHandler(const HomieRange& range, const String& value) { strip.show(); } return true; -} + } -bool pixelsHandler(const HomieRange& range, const String& value) { + bool pixelsHandler(const HomieRange& range, const String& value) { String remaining = value; int i = 0; @@ -748,9 +751,9 @@ bool pixelsHandler(const HomieRange& range, const String& value) { strip.show(); return true; -} + } -bool iconHandler(const HomieRange& range, const String& value) { + bool iconHandler(const HomieRange& range, const String& value) { String _iconname = value; iconcolor = strip.Color(255, 255, 255); //default color if (value[0] == '#') { //color given @@ -769,9 +772,9 @@ bool iconHandler(const HomieRange& range, const String& value) { strip.show(); return true; -} + } -void setup() { + void setup() { Serial.begin(115200); Serial << endl << endl; @@ -833,9 +836,9 @@ void setup() { effect = EFFECT_LARSON; Serial << "Setup finished" << endl; -} + } -void loop() { + void loop() { Homie.loop(); ArduinoOTA.handle(); @@ -872,6 +875,6 @@ void loop() { lastMillis = currentMillis; } -} + } */ From ce70f346e63429ecd4cdf672f1a824e164b186dc Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 17:37:20 +0100 Subject: [PATCH 07/14] Fill-Effect working --- pixelprojektor/NeoPatterns.cpp | 44 ++- pixelprojektor/NeoPatterns.h | 8 +- pixelprojektor/pixelprojektor.ino | 447 +----------------------------- 3 files changed, 54 insertions(+), 445 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index 4a66080..c68d487 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -4,14 +4,13 @@ NeoPatterns::NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*call Adafruit_NeoPixel(pixels, pin, type) { OnComplete = callback; - // TODO: Arrays hier initialisieren mit konkreten Werten? Und in der NeoPatterns.h nur der Platzhalter? //Allocate a zero initialized block of memory big enough to hold "pixels" uint8_t. - pixelR = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); - pixelG = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); - pixelB = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); - pixelR_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); - pixelG_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); - pixelB_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelR = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelG = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelB = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelR_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelG_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); + pixelB_buffer = ( uint8_t* ) calloc( pixels, sizeof( uint8_t ) ); } void NeoPatterns::Update() { @@ -253,7 +252,7 @@ void NeoPatterns::RandomFadeUpdate() { void NeoPatterns::Smooth(uint8_t wheelSpeed, uint8_t smoothing, uint8_t strength, uint8_t interval) { ActivePattern = SMOOTH; Interval = interval; - TotalSteps = 1000; // Beim Smooth nicht sinnvoll? + // TotalSteps = 1; // TODO: Beim Smooth nicht sinnvoll? Index = 0; WheelSpeed = wheelSpeed; Smoothing = smoothing; @@ -354,7 +353,7 @@ void NeoPatterns::SmoothUpdate() { } show(); - Increment(); + // Increment(); } @@ -385,6 +384,12 @@ void NeoPatterns::ColorSet(uint32_t color) show(); } +void NeoPatterns::ColorSetParameters(String parameters) +{ + None(); + ColorSet(parseColor(parameters)); +} + // Returns the Red component of a 32-bit color uint8_t NeoPatterns::Red(uint32_t color) { @@ -433,6 +438,13 @@ uint8_t NeoPatterns::xyToPos(int x, int y) { } } +//convert pixel number to actual 8x8 matrix position +uint8_t NeoPatterns::numToPos(int num) { + int x = num % 8; + int y = num / 8; + return xyToPos(x, y); +} + // Convert pixel number to actual 8x8 matrix position in a spiral uint8_t NeoPatterns::numToSpiralPos(int num) { int edge = (int)sqrt(numPixels()); @@ -481,6 +493,7 @@ uint8_t NeoPatterns::numToSpiralPos(int num) { uint8_t NeoPatterns::getAverage(uint8_t array[], uint8_t i, int x, int y) { + // TODO: This currently works only with 8x8 (64 pixel)! uint16_t sum = 0; uint8_t count = 0; if (i >= 8) { //up @@ -501,3 +514,16 @@ uint8_t NeoPatterns::getAverage(uint8_t array[], uint8_t i, int x, int y) } return sum / count; } + +uint32_t NeoPatterns::parseColor(String value) { + if (value.charAt(0) == '#') { //solid fill + String color = value.substring(1); + int number = (int) strtol( &color[0], NULL, 16); + // Split them up into r, g, b values + int r = number >> 16; + int g = number >> 8 & 0xFF; + int b = number & 0xFF; + return Color(r, g, b); + } + return 0; +} diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index a546cc4..d175364 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -26,21 +26,24 @@ class NeoPatterns : public Adafruit_NeoPixel void FadeUpdate(); void RandomFade(uint8_t interval = 100); void RandomFadeUpdate(); - void Smooth(uint8_t wheelSpeed, uint8_t smoothing, uint8_t strength, uint8_t interval); + void Smooth(uint8_t wheelSpeed = 16, uint8_t smoothing = 80, uint8_t strength = 50, uint8_t interval = 40); void SmoothUpdate(); void SetColor1(uint32_t color); void SetColor2(uint32_t color); //Utilities void ColorSet(uint32_t color); + void ColorSetParameters(String parameters); uint8_t Red(uint32_t color); uint8_t Green(uint32_t color); uint8_t Blue(uint32_t color); uint32_t Wheel(byte WheelPos); uint8_t numToSpiralPos(int num); uint8_t xyToPos(int x, int y); + uint8_t numToPos(int num); uint8_t getAverage(uint8_t array[], uint8_t i, int x, int y); - private: + uint32_t parseColor(String value); + private: // Member Variables: pattern ActivePattern; // which pattern is running @@ -52,6 +55,7 @@ class NeoPatterns : public Adafruit_NeoPixel uint32_t Color1, Color2; // What colors are in use uint16_t TotalSteps; // total number of steps in the pattern uint16_t Index; // current step within the pattern + uint8_t Every; // Turn every "Every" pixel in Color1/Color2 byte wPos; bool colorful; diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index 79d8c92..c9724cd 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -88,7 +88,16 @@ bool onSetEffect(const HomieRange& range, const String& value) { strip.Smooth(16, 80, 50, 40); } else { - strip.None(); + // Test whether command with parameters was sent + int sep = value.indexOf("|"); + String command = value.substring(0, sep); + String parameters = value.substring(sep + 1); + if (command.equals("fill")) + { + strip.ColorSetParameters(parameters); + } else { + strip.None(); + } } homieNode.setProperty("effect").send(value); } @@ -129,12 +138,14 @@ void setup() { homieNode.advertise("clear").settable(onSetClear); homieNode.advertise("length").settable(onSetLength); + + Homie.setup(); + strip.begin(); strip.clear(); strip.setBrightness(64); strip.show(); - Homie.setup(); ArduinoOTA.setHostname("pixelprojektor"); ArduinoOTA.onStart([]() { @@ -157,10 +168,6 @@ void loop() { // Diese Effekte müssen nach dem Umbau wieder vorhanden sein: /* - case EFFECT_SMOOTH: - led_movingPoint(); - led_smooth(); - break; case EFFECT_SPIRAL: led_spiral(); break; @@ -170,115 +177,22 @@ void loop() { case EFFECT_CHASE: led_chase(); break; - case EFFECT_RADAR: - led_radar(); - break; - case EFFECT_LARSON: - led_larson(); - break; */ /************ Old stuff ************/ /* - #define FPS 15 - uint8_t effect = 0; - uint8_t movingPoint_x = 3; - uint8_t movingPoint_y = 3; - uint8_t wheelPos = 0; - uint8_t wheelPosSlow = 0; //for slower wheelPos increment than 1 - int wheelSpeed = 16; //16=+1/frame - int smoothing = 80; //0 to 100. 100=no change (ultrasmooth), 0=no smoothing. - int strength = 50; //how much pixels to apply color to - #define EFFECT_NONE 0 - #define EFFECT_SMOOTH 1 - #define EFFECT_SPIRAL 2 - #define EFFECT_RANDOMFADE 3 - #define EFFECT_CHASE 4 - #define EFFECT_RADAR 5 - #define EFFECT_LARSON 6 int fadespeedmax = 5; //1 to 255 int iconCountStart = 0; //for percentage calculation int iconCountdown = 0; //0=off uint8_t iconchar = 0; //last displayed char int32_t iconcolor = 0; //last icon color - uint16_t Index; // current step within the pattern - // int Index = 0; // Step for Effect (e.g. chase) - // int state = 0; // Direction for Larson Scanner (spiral) - direction Direction; // direction to run the pattern - uint8_t pixelR[NUMPIXELS]; - uint8_t pixelG[NUMPIXELS]; - uint8_t pixelB[NUMPIXELS]; - //write to buffer, flip with showBuffer() - uint8_t pixelR_buffer[NUMPIXELS]; - uint8_t pixelG_buffer[NUMPIXELS]; - uint8_t pixelB_buffer[NUMPIXELS]; - long lastMillis = 0; long fpsdelay = 1000 / FPS; - int xyToPos(int x, int y) { //convert x y pixel position to matrix position - if (y % 2 == 0) { - return (y * 8 + x); - } else { - return (y * 8 + (7 - x)); - } - } - - int numToPos(int num) { //convert pixel number to actual 8x8 matrix position - int x = num % 8; - int y = num / 8; - return xyToPos(x, y); - } - - int numToSpiralPos(int num) { // convert pixel number to actual 8x8 matrix position in a spiral - int edge = (int)sqrt(NUMPIXELS); - int findx = edge-1; // 7 - int findy = 0; - int stepsize = edge-1; // initial value (0..7) - int stepnumber = 0; // each "step" should be used twice - int count = -1; - int dir = 1; // direction: 0 = incX, 1=incY, 2=decX, 3=decY - if (num < edge) { - return num; // trivial - } - for (int i = edge; i <= num; i++) - { - count++; - if (count == stepsize) { - count = 0; - // Change direction - dir++; - stepnumber++; - if (stepnumber == 2) { - stepsize -= 1; - stepnumber = 0; - } - if (dir == 4) { - dir = 0; - } - } - switch (dir) { - case 0: - findx++; - break; - case 1: - findy++; - break; - case 2: - findx--; - break; - case 3: - findy--; - break; - } - } - return xyToPos(findx, findy); - } - uint32_t wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if (WheelPos < 85) { @@ -293,13 +207,6 @@ void loop() { } - void led_fill(uint32_t c) - { - for (int i = 0; i < strip.numPixels(); i++) { - strip.setPixelColor(i, c); - } - strip.show(); - } void led_random() { @@ -309,219 +216,12 @@ void loop() { strip.show(); } - - void showBuffer() - { - for (int i = 0; i < strip.numPixels(); i++) { - pixelR[i] = pixelR_buffer[i]; - pixelG[i] = pixelG_buffer[i]; - pixelB[i] = pixelB_buffer[i]; - strip.setPixelColor(i, pixelR[i], pixelG[i], pixelB[i]); - } - strip.show(); - } - - uint8_t getAverage(uint8_t array[NUMPIXELS], uint8_t i, int x, int y) - { - uint16_t sum = 0; - uint8_t count = 0; - if (i >= 8) { //up - sum += array[i - 8]; - count++; - } - if (i < (64 - 8)) { //down - sum += array[i + 8]; - count++; - } - if (i >= 1) { //left - sum += array[i - 1]; - count++; - } - if (i < (64 - 1)) { //right - sum += array[i + 1]; - count++; - } - return sum / count; - } - - - void led_smooth() - { - for (int i = 0; i < strip.numPixels(); i++) { - //uint8_t avgbrightness=pixelR_buffer[i]/3+pixelG_buffer[i]/3+pixelB_buffer[i]/3; - pixelR_buffer[i] = (smoothing / 100.0) * pixelR[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelR, i, 0, 0); - pixelG_buffer[i] = (smoothing / 100.0) * pixelG[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelG, i, 0, 0); - pixelB_buffer[i] = (smoothing / 100.0) * pixelB[i] + (1.0 - (smoothing / 100.0)) * getAverage(pixelB, i, 0, 0); - - } - showBuffer(); - } - - void led_movingPoint() - { - uint32_t c = wheel(wheelPos); - wheelPosSlow += wheelSpeed; - wheelPos = (wheelPos + (wheelPosSlow / 10) ) % 255; - wheelPosSlow = wheelPosSlow % 16; - - uint8_t r = (uint8_t)(c >> 16); - uint8_t g = (uint8_t)(c >> 8); - uint8_t b = (uint8_t)c; - - movingPoint_x = movingPoint_x + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); - movingPoint_y = movingPoint_y + 8 + random(-random(0, 1 + 1), random(0, 1 + 1) + 1); - if (movingPoint_x < 8) { - movingPoint_x = 8 - movingPoint_x; - } else if (movingPoint_x >= 16) { - movingPoint_x = 22 - movingPoint_x; - } else { - movingPoint_x -= 8; - } - - if (movingPoint_y < 8) { - movingPoint_y = 8 - movingPoint_y; - } else if (movingPoint_y >= 16) { - movingPoint_y = 22 - movingPoint_y; - } else { - movingPoint_y -= 8; - } - uint8_t startx = movingPoint_x; - uint8_t starty = movingPoint_y; - - for (int i = 0; i < strength; i++) { - - movingPoint_x = startx + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); - movingPoint_y = starty + 8 + random(-random(0, 2 + 1), random(0, 2 + 1) + 1); - - if (movingPoint_x < 8) { - movingPoint_x = 8 - movingPoint_x; - } else if (movingPoint_x >= 16) { - movingPoint_x = 22 - movingPoint_x; - } else { - movingPoint_x -= 8; - } - - if (movingPoint_y < 8) { - movingPoint_y = 8 - movingPoint_y; - } else if (movingPoint_y >= 16) { - movingPoint_y = 22 - movingPoint_y; - } else { - movingPoint_y -= 8; - } - - - - if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] < r) { - pixelR[xyToPos(movingPoint_x, movingPoint_y)]++; - } else if (pixelR[xyToPos(movingPoint_x, movingPoint_y)] > r) { - pixelR[xyToPos(movingPoint_x, movingPoint_y)]--; - } - if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] < g) { - pixelG[xyToPos(movingPoint_x, movingPoint_y)]++; - } else if (pixelG[xyToPos(movingPoint_x, movingPoint_y)] > g) { - pixelG[xyToPos(movingPoint_x, movingPoint_y)]--; - } - if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] < b) { - pixelB[xyToPos(movingPoint_x, movingPoint_y)]++; - } else if (pixelB[xyToPos(movingPoint_x, movingPoint_y)] > b) { - pixelB[xyToPos(movingPoint_x, movingPoint_y)]--; - } - } - - - //pixelR[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelR[xyToPos(movingPoint_x,movingPoint_y)]+0.5*r; - //pixelG[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelG[xyToPos(movingPoint_x,movingPoint_y)]+0.5*g; - //pixelB[xyToPos(movingPoint_x,movingPoint_y)]=0.5*pixelB[xyToPos(movingPoint_x,movingPoint_y)]+0.5*b; - - movingPoint_x = startx; - movingPoint_y = starty; - - } - void bufferClear() - { - for (int i = 0; i < strip.numPixels(); i++) { - pixelR_buffer[i] = 0; - pixelG_buffer[i] = 0; - pixelB_buffer[i] = 0; - } - } - - void led_chase() - { - Index += 1; - if (Index > 255) { - Index = 1; - } - // for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel - for (int q = 0; q < 3; q++) { - for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { - strip.setPixelColor(i + q, wheel( (i + Index) % 255)); //turn every third pixel on - } - strip.show(); - - delay(49); - - for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { - strip.setPixelColor(i + q, 0); //turn every third pixel off - } - } - } - - - void led_radar() { // "Sweep" in cirles... // line(0,0,950*cos(radians(iAngle)),-950*sin(radians(iAngle))); } - // Calculate 50% dimmed version of a color (used by led_larson()) - uint32_t DimColor(uint32_t color) - { - // Shift R, G and B components one bit to the right - uint32_t Dimcolor = strip.Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1); - return Dimcolor; - } - - // Returns the Red component of a 32-bit color - uint8_t Red(uint32_t color) - { - return (color >> 16) & 0xFF; - } - - // Returns the Green component of a 32-bit color - uint8_t Green(uint32_t color) - { - return (color >> 8) & 0xFF; - } - - // Returns the Blue component of a 32-bit color - uint8_t Blue(uint32_t color) - { - return color & 0xFF; - } - - void Increment() - { - if (Direction == FORWARD) - { - Index++; - if (Index >= (strip.numPixels() - 1) * 2) - { - Index = 0; - } - } - else // Direction == REVERSE - { - --Index; - if (Index <= 0) - { - Index = (strip.numPixels() - 1) * 2 - 1; - } - } - } - - void led_larson() { int EyeSize = 5; @@ -614,25 +314,6 @@ void loop() { } - uint32_t parseColor(String value) { - if (value.charAt(0) == '#') { //solid fill - String color = value.substring(1); - int number = (int) strtol( &color[0], NULL, 16); - - - // Split them up into r, g, b values - int r = number >> 16; - int g = number >> 8 & 0xFF; - int b = number & 0xFF; - Homie.getLogger() << "r=" << r << " g=" << g << " b=" << b << endl; - //Serial.print("r=");Serial.print(r); - //Serial.print(" g=");Serial.print(g); - //Serial.print(" b=");Serial.println(b); - return strip.Color(r, g, b); - - } - return 0; - } bool effectHandler(const HomieRange& range, const String& value) { @@ -774,107 +455,5 @@ void loop() { return true; } - void setup() { - Serial.begin(115200); - Serial << endl << endl; - - Serial << "Begin strip" << endl; - strip.begin(); - strip.show(); // Initialize all pixels to 'off' - - - led_fill(strip.Color(100, 0, 0)); - //delay(500); - - - - Serial << "Homie_setFirmware" << endl; - Homie_setFirmware("pixelprojektor", "1.0.0"); - - Serial << "Homie node advertise" << endl; - homieNode.advertise("effect").settable(effectHandler); - homieNode.advertise("pixels").settable(pixelsHandler); - homieNode.advertise("icon").settable(iconHandler); - - - - led_fill(strip.Color(0, 0, 0)); - strip.setPixelColor(0, strip.Color(100, 0, 0)); - strip.show(); - - Serial << "homie setup" << endl; - Homie.setup(); - - // Hostname defaults to esp8266-[ChipID] - ArduinoOTA.setHostname("pixelprojektor"); - - // No authentication by default - // ArduinoOTA.setPassword((const char *)"ctdo2342"); - - ArduinoOTA.onStart([]() { - Serial.println("Start"); - led_fill(strip.Color(0, 0, 0)); // Clear - }); - ArduinoOTA.onEnd([]() { - Serial.println("\nEnd"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - strip.setPixelColor(numToPos((progress / (total / strip.numPixels()))), strip.Color(100, 0, 0)); - strip.show(); - Serial.printf("Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); - else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); - else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); - else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); - else if (error == OTA_END_ERROR) Serial.println("End Failed"); - }); - ArduinoOTA.begin(); - - effect = EFFECT_LARSON; - - Serial << "Setup finished" << endl; - } - - void loop() { - Homie.loop(); - ArduinoOTA.handle(); - - long currentMillis = millis(); - - - if (lastMillis + fpsdelay < currentMillis) { - if (iconCountdown > 0) { //icon effect active - iconCountdown--; - led_icon(iconchar, iconcolor); - } else { - switch (effect) { - case EFFECT_SMOOTH: - led_movingPoint(); - led_smooth(); - break; - case EFFECT_SPIRAL: - led_spiral(); - break; - case EFFECT_RANDOMFADE: - led_randomfade(); - break; - case EFFECT_CHASE: - led_chase(); - break; - case EFFECT_RADAR: - led_radar(); - break; - case EFFECT_LARSON: - led_larson(); - break; - } - } - lastMillis = currentMillis; - } - - } */ From 498a689e1ecaf48b1b377fe38650cfc047a2488e Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 21:41:27 +0100 Subject: [PATCH 08/14] Refactoring completed, New: RandomFadeSingle, Icon (with Continue of old Effect), Random, RandomFade. Set OTA-Brightness --- pixelprojektor/NeoPatterns.cpp | 100 +++++++++++++++++- pixelprojektor/NeoPatterns.h | 24 ++++- pixelprojektor/pixelprojektor.ino | 169 +++++++----------------------- 3 files changed, 158 insertions(+), 135 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index c68d487..ac7a82b 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -37,9 +37,15 @@ void NeoPatterns::Update() { case RANDOM_FADE: RandomFadeUpdate(); break; + case RANDOM_FADE_SINGLE: + RandomFadeSingleUpdate(); + break; case SMOOTH: SmoothUpdate(); break; + case ICON: + IconUpdate(); + break; case NONE: break; default: @@ -244,15 +250,52 @@ void NeoPatterns::RandomFade(uint8_t interval ) { TotalSteps = 255; Index = 0; } + void NeoPatterns::RandomFadeUpdate() { ColorSet(Wheel(Index)); Increment(); } +void NeoPatterns::RandomFadeSingle(uint8_t interval, uint8_t speed) { + ActivePattern = RANDOM_FADE_SINGLE; + Interval = interval; + TotalSteps = 255; + Index = 0; + WheelSpeed = speed; + RandomBuffer(); +} + +void NeoPatterns::RandomFadeSingleUpdate() { + for (int i = 0; i < numPixels(); i++) { + pixelR_buffer[i] += random(0, random(0, WheelSpeed + 1) + 1); //use buffer red channel for color wheel + setPixelColor(i, Wheel(pixelR_buffer[i])); + } + show(); + Increment(); +} + +void NeoPatterns::RandomBuffer() +{ + for (int i = 0; i < numPixels(); i++) { + uint32_t c = Wheel(random(0, 256)); + pixelR_buffer[i] = (uint8_t)(c >> 16); + pixelG_buffer[i] = (uint8_t)(c >> 8); + pixelB_buffer[i] = (uint8_t)c; + } +} + +void NeoPatterns::Random() +{ + None(); // Stop all other effects + for (int i = 0; i < numPixels(); i++) { + setPixelColor(i, Wheel(random(0, 256))); + } + show(); +} + void NeoPatterns::Smooth(uint8_t wheelSpeed, uint8_t smoothing, uint8_t strength, uint8_t interval) { ActivePattern = SMOOTH; Interval = interval; - // TotalSteps = 1; // TODO: Beim Smooth nicht sinnvoll? Index = 0; WheelSpeed = wheelSpeed; Smoothing = smoothing; @@ -353,8 +396,57 @@ void NeoPatterns::SmoothUpdate() { } show(); - // Increment(); +} + +/****************** Icon ******************/ + +void NeoPatterns::Icon(uint8_t fontchar, String iconcolor, uint8_t interval) +{ + // Save last effect, should be called after completion again + SavedPattern = ActivePattern; + SavedInterval = Interval; + SavedTotalSteps = TotalSteps; + SavedIndex = Index; + SavedColor1 = Color1; + SavedDirection = Direction; + ActivePattern = ICON; + Interval = interval; + TotalSteps = 80; + Index = 80; + Color1 = parseColor(iconcolor); + FontChar = fontchar; + Direction = REVERSE; +} + +void NeoPatterns::IconUpdate() +{ + for (int i = 0; i < numPixels(); i++) { + uint64_t mask = 1LL << (uint64_t)i; + + if ( (font[FontChar]&mask) == 0) { + setPixelColor(numToPos(i), Color(0, 0, 0)); //bit is 0 at pos i + } else { + float _brightness = 1.0 - ( (TotalSteps - Index) * 1.0 / TotalSteps ); + uint8_t _r = (uint8_t)(Color1 >> 16); + uint8_t _g = (uint8_t)(Color1 >> 8); + uint8_t _b = (uint8_t)Color1; + setPixelColor(numToPos(i), Color(_r * _brightness, _g * _brightness, _b * _brightness)); //bit is 1 at pos i + } + } + show(); + Increment(); +} + +void NeoPatterns::IconComplete() +{ + // Reload last effect + ActivePattern = SavedPattern; + Interval = SavedInterval; + TotalSteps = SavedTotalSteps; + Index = SavedIndex; + Color1 = SavedColor1; + Direction = SavedDirection; } /****************** Helper functions ******************/ @@ -527,3 +619,7 @@ uint32_t NeoPatterns::parseColor(String value) { } return 0; } + + + + diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index d175364..4f87547 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -1,7 +1,8 @@ #include +#include "font.h" // Pattern types supported: -enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH }; +enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH, ICON, RANDOM_FADE_SINGLE }; // Patern directions supported: enum direction { FORWARD, REVERSE }; @@ -20,14 +21,21 @@ class NeoPatterns : public Adafruit_NeoPixel void TheaterChaseUpdate(); void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD); void ColorWipeUpdate(); - void Scanner(uint32_t color1, uint8_t interval = 40, bool colorful = false, bool spiral = false); + void Scanner(uint32_t color1 = 16711680, uint8_t interval = 40, bool colorful = false, bool spiral = false); void ScannerUpdate(); void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD); void FadeUpdate(); void RandomFade(uint8_t interval = 100); void RandomFadeUpdate(); + void RandomFadeSingle(uint8_t interval = 100, uint8_t speed = 5); + void RandomFadeSingleUpdate(); + void RandomBuffer(); + void Random(); void Smooth(uint8_t wheelSpeed = 16, uint8_t smoothing = 80, uint8_t strength = 50, uint8_t interval = 40); void SmoothUpdate(); + void Icon(uint8_t fontchar, String iconcolor = "#FFFFFF", uint8_t interval = 30); + void IconUpdate(); + void IconComplete(); void SetColor1(uint32_t color); void SetColor2(uint32_t color); @@ -43,18 +51,24 @@ class NeoPatterns : public Adafruit_NeoPixel uint8_t numToPos(int num); uint8_t getAverage(uint8_t array[], uint8_t i, int x, int y); uint32_t parseColor(String value); - private: + private: // Member Variables: pattern ActivePattern; // which pattern is running + pattern SavedPattern; direction Direction; // direction to run the pattern + direction SavedDirection; unsigned long Interval; // milliseconds between updates + unsigned long SavedInterval; unsigned long lastUpdate; // last update of position uint32_t Color1, Color2; // What colors are in use + uint32_t SavedColor1; uint16_t TotalSteps; // total number of steps in the pattern + uint16_t SavedTotalSteps; uint16_t Index; // current step within the pattern + uint16_t SavedIndex; uint8_t Every; // Turn every "Every" pixel in Color1/Color2 byte wPos; @@ -71,7 +85,9 @@ class NeoPatterns : public Adafruit_NeoPixel uint8_t *pixelB; uint8_t *pixelR_buffer; uint8_t *pixelG_buffer; - uint8_t *pixelB_buffer; + uint8_t *pixelB_buffer; + + uint8_t FontChar; uint32_t DimColor(uint32_t color); void Increment(); diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index c9724cd..31c535a 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -2,7 +2,6 @@ #include #include #include "NeoPatterns.h" -#include "font.h" #ifdef __AVR__ #include #endif @@ -10,12 +9,18 @@ #define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 +NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); + +bool stopAfterCompletion; + void StripComplete() { + if (stopAfterCompletion) + { + strip.IconComplete(); + } return; } -NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); - HomieNode homieNode("pixel", "commands"); @@ -61,6 +66,7 @@ bool onSetBrightness(const HomieRange& range, const String& value) { } bool onSetEffect(const HomieRange& range, const String& value) { + stopAfterCompletion = false; String effect = value; effect.toLowerCase(); if (effect == "scanner") { @@ -75,7 +81,7 @@ bool onSetEffect(const HomieRange& range, const String& value) { else if (effect == "rainbowcycle") { strip.RainbowCycle(50); } - else if (effect == "theaterchase") { + else if (effect == "theaterchase" || effect == "chase") { strip.TheaterChase(strip.Color(255, 0, 0), strip.Color(0, 0, 255), 100); } else if (effect == "fade") { @@ -84,7 +90,9 @@ bool onSetEffect(const HomieRange& range, const String& value) { else if (effect == "randomfade") { strip.RandomFade(); } - else if (effect == "smooth") { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 + else if (effect == "random") { + strip.Random(); + } else if (effect == "smooth") { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 strip.Smooth(16, 80, 50, 40); } else { @@ -92,16 +100,36 @@ bool onSetEffect(const HomieRange& range, const String& value) { int sep = value.indexOf("|"); String command = value.substring(0, sep); String parameters = value.substring(sep + 1); - if (command.equals("fill")) - { + if (command.equals("fill")) { strip.ColorSetParameters(parameters); - } else { + } + else if (command.equals("randomfade")) { + int sepparam = parameters.indexOf("|"); + int p1 = parameters.substring(0, sepparam).toInt(); + if (p1 <= 0) { + p1 = 5; + } + strip.RandomFadeSingle(p1); + } + else { strip.None(); } } homieNode.setProperty("effect").send(value); } +bool onSetIcon(const HomieRange& range, const String& value) { + stopAfterCompletion = true; + String _iconname = value; + if (value[0] == '#') { //color given + strip.Icon(value.substring(7)[0], value.substring(0, 6)); + } + else { + strip.Icon(value[0]); + } + homieNode.setProperty("icon").send(value); +} + bool onSetClear(const HomieRange& range, const String& value) { strip.None(); strip.clear(); @@ -122,7 +150,6 @@ bool onSetLength(const HomieRange& range, const String& value) { void loopHandler() { strip.Update(); - } void setup() { @@ -137,19 +164,20 @@ void setup() { homieNode.advertise("effect").settable(onSetEffect); homieNode.advertise("clear").settable(onSetClear); homieNode.advertise("length").settable(onSetLength); - + homieNode.advertise("icon").settable(onSetIcon); Homie.setup(); - + strip.begin(); strip.clear(); strip.setBrightness(64); strip.show(); - + stopAfterCompletion = false; // Default ArduinoOTA.setHostname("pixelprojektor"); ArduinoOTA.onStart([]() { strip.clear(); + strip.setBrightness(64); }); ArduinoOTA.onEnd([]() { strip.clear(); @@ -184,29 +212,6 @@ void loop() { /************ Old stuff ************/ /* int fadespeedmax = 5; //1 to 255 - int iconCountStart = 0; //for percentage calculation - int iconCountdown = 0; //0=off - uint8_t iconchar = 0; //last displayed char - int32_t iconcolor = 0; //last icon color - - long lastMillis = 0; - long fpsdelay = 1000 / FPS; - - - uint32_t wheel(byte WheelPos) { - WheelPos = 255 - WheelPos; - if (WheelPos < 85) { - return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); - } - if (WheelPos < 170) { - WheelPos -= 85; - return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); - } - WheelPos -= 170; - return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); - } - - void led_random() { @@ -222,37 +227,6 @@ void loop() { // line(0,0,950*cos(radians(iAngle)),-950*sin(radians(iAngle))); } - void led_larson() - { - int EyeSize = 5; - uint32_t rgb[3] = {0}; - wheelPos++; - if (wheelPos >= 256) { - wheelPos = 0; - } - int Color1 = wheel(wheelPos); - - for (int i = 0; i < strip.numPixels(); i++) - { - int realpos = numToSpiralPos(i); - if (i == Index) // Scan Pixel to the right - { - strip.setPixelColor(realpos, Color1); - } - else if (i == ((strip.numPixels() - 1) * 2) - Index) // Scan Pixel to the left - { - strip.setPixelColor(realpos, Color1); - } - else // Fading tail - { - strip.setPixelColor(realpos, DimColor(strip.getPixelColor(realpos))); - } - } - - strip.show(); - Increment(); - } - void led_spiral() { @@ -274,48 +248,6 @@ void loop() { } - void led_randomfade() - { - for (int i = 0; i < strip.numPixels(); i++) { - pixelR_buffer[i] += random(0, random(0, fadespeedmax + 1) + 1); //use buffer red channel for color wheel - strip.setPixelColor(i, wheel(pixelR_buffer[i])); - } - strip.show(); - } - - void led_icon(uint8_t fontchar, uint32_t iconcolor) - { - for (int i = 0; i < strip.numPixels(); i++) { - uint64_t mask = 1LL << (uint64_t)i; - - if ( (font[fontchar]&mask) == 0) { - strip.setPixelColor(numToPos(i), strip.Color(0, 0, 0)); //bit is 0 at pos i - } else { - - float _brightness = 1.0 - ( (iconCountStart - iconCountdown) * 1.0 / iconCountStart ); - uint8_t _r = (uint8_t)(iconcolor >> 16); - uint8_t _g = (uint8_t)(iconcolor >> 8); - uint8_t _b = (uint8_t)iconcolor; - strip.setPixelColor(numToPos(i), strip.Color(_r * _brightness, _g * _brightness, _b * _brightness)); //bit is 1 at pos i - } - - } - strip.show(); - } - - void set_randomBuffer() - { - for (int i = 0; i < strip.numPixels(); i++) { - uint32_t c = wheel(random(0, 256)); - pixelR_buffer[i] = (uint8_t)(c >> 16); - pixelG_buffer[i] = (uint8_t)(c >> 8); - pixelB_buffer[i] = (uint8_t)c; - } - } - - - - bool effectHandler(const HomieRange& range, const String& value) { Homie.getLogger() << "-> " << value << endl; int sep = value.indexOf("|"); @@ -434,26 +366,5 @@ void loop() { return true; } - bool iconHandler(const HomieRange& range, const String& value) { - String _iconname = value; - iconcolor = strip.Color(255, 255, 255); //default color - if (value[0] == '#') { //color given - iconcolor = parseColor(value.substring(0, 6)); - _iconname = value.substring(7); // example: #ff00dc|A (pipe will be ignored) - } - - iconCountStart = FPS * 2; - iconCountdown = iconCountStart; - if (_iconname.length() == 1) { //only one character - iconchar = value[0]; - } else { - - } - - strip.show(); - - return true; - } - */ From b84d21ff8356d2a9fdb18c552ba1314bbb63037a Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 21:45:15 +0100 Subject: [PATCH 09/14] Removed backups. Warning: setPixel has changed, now default from Adafruit. TODO! --- pixelprojektor/pixelprojektor.ino | 146 +----------------------------- 1 file changed, 1 insertion(+), 145 deletions(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index 31c535a..d4c95a1 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -194,152 +194,10 @@ void loop() { ArduinoOTA.handle(); } -// Diese Effekte müssen nach dem Umbau wieder vorhanden sein: -/* - case EFFECT_SPIRAL: - led_spiral(); - break; - case EFFECT_RANDOMFADE: - led_randomfade(); - break; - case EFFECT_CHASE: - led_chase(); - break; -*/ - - /************ Old stuff ************/ /* - int fadespeedmax = 5; //1 to 255 - - void led_random() - { - for (int i = 0; i < strip.numPixels(); i++) { - strip.setPixelColor(i, wheel(random(0, 255))); - } - strip.show(); - } - - void led_radar() - { - // "Sweep" in cirles... - // line(0,0,950*cos(radians(iAngle)),-950*sin(radians(iAngle))); - } - - - void led_spiral() - { - int every = 4; - wheelPos++; - int qp = Index % every; - Index++; - if (Index >= strip.numPixels() - 1) { - Index = 0; - } - int q = Index % every; - for (uint16_t i = 0; i < strip.numPixels(); i = i + every) { - strip.setPixelColor(numToSpiralPos(i + q), wheel( (i + Index * 4) % 255)); //turn every "every" pixel on - } - for (uint16_t i = 0; i < strip.numPixels(); i = i + every) { - strip.setPixelColor(numToSpiralPos(i + qp), 0); //turn every "every" pixel off - } - strip.show(); - - } - - bool effectHandler(const HomieRange& range, const String& value) { - Homie.getLogger() << "-> " << value << endl; - int sep = value.indexOf("|"); - - String command = value.substring(0, sep); - String parameters = value.substring(sep + 1); - Homie.getLogger() << "command=" << command << " parameters=" << parameters << endl; - - if (command.equals("fill")) { - effect = EFFECT_NONE; - led_fill(parseColor(parameters)); - } else if (command.equals("off")) { - effect = EFFECT_NONE; - led_fill(strip.Color(0, 0, 0)); - } else if (command.equals("random")) { - effect = EFFECT_NONE; - led_random(); - } else if (command.equals("set")) { //example: set|37#ff003a - effect = EFFECT_NONE; - int x = parameters.substring(0, 1).toInt(); - int y = parameters.substring(1, 2).toInt(); - String cstr = parameters.substring(2, 9); - strip.setPixelColor(xyToPos(x, y), parseColor(cstr)); - strip.show(); - } else if (command.equals("smooth")) { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 - int sepparam = parameters.indexOf("|"); - int p1 = parameters.substring(0, sepparam).toInt(); - String parameters_part2 = parameters.substring(sepparam + 1); - sepparam = parameters_part2.indexOf("|"); - int p2 = parameters_part2.substring(0, sepparam).toInt(); - int p3 = parameters_part2.substring(sepparam + 1).toInt(); - wheelSpeed = 16; //default, speed=+1 /frame - if (p1 > 0) { - wheelSpeed = p1; - } - smoothing = 80; - if (p2 > 0) { - smoothing = p2; - } - strength = 50; - if (p3 > 0) { - strength = p3; - } - Homie.getLogger() << "-- p1=" << p1 << " p2=" << p2 << " p3=" << p3 << endl; - effect = EFFECT_SMOOTH; - bufferClear(); - showBuffer(); - strip.show(); - } else if (command.equals("spiral")) { - effect = EFFECT_SPIRAL; - Index = 0; - bufferClear(); - showBuffer(); - strip.show(); - } else if (command.equals("clearbuffer")) { - bufferClear(); - showBuffer(); - strip.show(); - } else if (command.equals("randomfade")) { //example: randomfade|5 - int sepparam = parameters.indexOf("|"); - int p1 = parameters.substring(0, sepparam).toInt(); - fadespeedmax = 5; - if (p1 > 0) { - fadespeedmax = p1; - } - effect = EFFECT_RANDOMFADE; - set_randomBuffer(); //initialize random - } else if (command.equals("randombuffer")) { - set_randomBuffer(); //set random - showBuffer(); - } else if (command.equals("chase")) { - effect = EFFECT_CHASE; - bufferClear(); - showBuffer(); - strip.show(); - } else if (command.equals("radar")) { - effect = EFFECT_RADAR; - Index = 0; - bufferClear(); - showBuffer(); - strip.show(); - } else if (command.equals("larson")) { - effect = EFFECT_LARSON; - Index = 0; - bufferClear(); - showBuffer(); - strip.show(); - } - return true; - } - - bool pixelsHandler(const HomieRange& range, const String& value) { + bool pixelsHandler(const HomieRange& range, const String& value) { String remaining = value; int i = 0; @@ -365,6 +223,4 @@ void loop() { return true; } - - */ From 755abb3317e4567bcaa95fde8e4cf5b94627d0ba Mon Sep 17 00:00:00 2001 From: starcalc Date: Wed, 1 Mar 2017 21:59:41 +0100 Subject: [PATCH 10/14] Control PIN for ctdo corrected. --- pixelprojektor/pixelprojektor.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index d4c95a1..f031f73 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -6,7 +6,7 @@ #include #endif -#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) +#define PIN 2 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); From 535281750ec9e67ca4f9e03fd47e6eb34ba3a5fb Mon Sep 17 00:00:00 2001 From: starcalc Date: Thu, 2 Mar 2017 11:06:29 +0100 Subject: [PATCH 11/14] Effect: Plasma added --- pixelprojektor/NeoPatterns.cpp | 67 +++++++++++++++++++++++++++++++ pixelprojektor/NeoPatterns.h | 15 ++++++- pixelprojektor/pixelprojektor.ino | 9 +++-- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index ac7a82b..b510538 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -46,6 +46,9 @@ void NeoPatterns::Update() { case ICON: IconUpdate(); break; + case PLASMA: + PlasmaUpdate(); + break; case NONE: break; default: @@ -449,6 +452,70 @@ void NeoPatterns::IconComplete() Direction = SavedDirection; } +// Based upon https://github.com/johncarl81/neopixelplasma +void NeoPatterns::Plasma(float phase, float phaseIncrement, float colorStretch, uint8_t interval) +{ + ActivePattern = PLASMA; + Interval = interval; + PlasmaPhase = phase; + PlasmaPhaseIncrement = phaseIncrement; + PlasmaColorStretch = colorStretch; +} + +void NeoPatterns::PlasmaUpdate() +{ + PlasmaPhase += PlasmaPhaseIncrement; + int edge = (int)sqrt(numPixels()); + // The two points move along Lissajious curves, see: http://en.wikipedia.org/wiki/Lissajous_curve + // The sin() function returns values in the range of -1.0..1.0, so scale these to our desired ranges. + // The phase value is multiplied by various constants; I chose these semi-randomly, to produce a nice motion. + Point p1 = { (sin(PlasmaPhase * 1.000) + 1.0) * (edge / 2), (sin(PlasmaPhase * 1.310) + 1.0) * (edge / 2) }; + Point p2 = { (sin(PlasmaPhase * 1.770) + 1.0) * (edge / 2), (sin(PlasmaPhase * 2.865) + 1.0) * (edge / 2) }; + Point p3 = { (sin(PlasmaPhase * 0.250) + 1.0) * (edge / 2), (sin(PlasmaPhase * 0.750) + 1.0) * (edge / 2)}; + + byte row, col; + + // For each row... + for ( row = 0; row < edge; row++ ) { + float row_f = float(row); // Optimization: Keep a floating point value of the row number, instead of recasting it repeatedly. + + // For each column... + for ( col = 0; col < edge; col++ ) { + float col_f = float(col); // Optimization. + + // Calculate the distance between this LED, and p1. + Point dist1 = { col_f - p1.x, row_f - p1.y }; // The vector from p1 to this LED. + float distance1 = sqrt( dist1.x * dist1.x + dist1.y * dist1.y ); + + // Calculate the distance between this LED, and p2. + Point dist2 = { col_f - p2.x, row_f - p2.y }; // The vector from p2 to this LED. + float distance2 = sqrt( dist2.x * dist2.x + dist2.y * dist2.y ); + + // Calculate the distance between this LED, and p3. + Point dist3 = { col_f - p3.x, row_f - p3.y }; // The vector from p3 to this LED. + float distance3 = sqrt( dist3.x * dist3.x + dist3.y * dist3.y ); + + // Warp the distance with a sin() function. As the distance value increases, the LEDs will get light,dark,light,dark,etc... + // You can use a cos() for slightly different shading, or experiment with other functions. Go crazy! + float color_1 = distance1; // range: 0.0...1.0 + float color_2 = distance2; + float color_3 = distance3; + float color_4 = (sin( distance1 * distance2 * PlasmaColorStretch )) + 2.0 * 0.5; + + // Square the color_f value to weight it towards 0. The image will be darker and have higher contrast. + color_1 *= color_1 * color_4; + color_2 *= color_2 * color_4; + color_3 *= color_3 * color_4; + color_4 *= color_4; + + // Scale the color up to 0..7 . Max brightness is 7. + //strip.setPixelColor(col + (edge * row), strip.Color(color_4, 0, 0) ); + setPixelColor(col + (edge * row), Color(color_1, color_2, color_3)); + } + } + show(); +} + /****************** Helper functions ******************/ void NeoPatterns::SetColor1(uint32_t color) { diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index 4f87547..24a196a 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -2,7 +2,7 @@ #include "font.h" // Pattern types supported: -enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH, ICON, RANDOM_FADE_SINGLE }; +enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH, ICON, RANDOM_FADE_SINGLE, PLASMA }; // Patern directions supported: enum direction { FORWARD, REVERSE }; @@ -36,6 +36,8 @@ class NeoPatterns : public Adafruit_NeoPixel void Icon(uint8_t fontchar, String iconcolor = "#FFFFFF", uint8_t interval = 30); void IconUpdate(); void IconComplete(); + void Plasma(float phase = 0, float phaseIncrement = 0.03, float colorStretch = 0.3, uint8_t interval = 60); // 0.08 and 0.11 + void PlasmaUpdate(); void SetColor1(uint32_t color); void SetColor2(uint32_t color); @@ -89,8 +91,19 @@ class NeoPatterns : public Adafruit_NeoPixel uint8_t FontChar; + float PlasmaPhase; + float PlasmaPhaseIncrement; + float PlasmaColorStretch; + uint32_t DimColor(uint32_t color); void Increment(); void (*OnComplete)(); // Callback on completion of pattern + // Convenient 2D point structure + struct Point { + float x; + float y; + }; + + }; diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index f031f73..93b849f 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -6,7 +6,7 @@ #include #endif -#define PIN 2 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) +#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); @@ -92,10 +92,13 @@ bool onSetEffect(const HomieRange& range, const String& value) { } else if (effect == "random") { strip.Random(); - } else if (effect == "smooth") { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 + } + else if (effect == "smooth") { //example: smooth|[wheelspeed]|[smoothing]|[strength] wheelspeed=1-255, smoothing=0-100, strength=1-255 strip.Smooth(16, 80, 50, 40); } - else { + else if (effect == "plasma") { + strip.Plasma(); + } else { // Test whether command with parameters was sent int sep = value.indexOf("|"); String command = value.substring(0, sep); From 519e2d6a6de6b951401763d7ef5ea9513fc0b9e7 Mon Sep 17 00:00:00 2001 From: starcalc Date: Thu, 2 Mar 2017 11:08:27 +0100 Subject: [PATCH 12/14] ctdo-PIN --- pixelprojektor/pixelprojektor.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index 93b849f..b4dd61c 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -6,7 +6,7 @@ #include #endif -#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) +#define PIN 2 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); From 9fb6b1c089e080c447d89a16a6b3ec672107fd43 Mon Sep 17 00:00:00 2001 From: starcalc Date: Fri, 3 Mar 2017 18:27:51 +0100 Subject: [PATCH 13/14] =?UTF-8?q?Effekt=20RANDOM,=20Effekt=20FILL=20sauber?= =?UTF-8?q?=20hinzugef=C3=BCgt,=20werden=20auch=20korrekt=20abgeschaltet.?= =?UTF-8?q?=20Energieverbrauch=20gesenkt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pixelprojektor/NeoPatterns.cpp | 18 +++++++++++++++++- pixelprojektor/NeoPatterns.h | 8 ++++++-- pixelprojektor/pixelprojektor.ino | 5 +++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/pixelprojektor/NeoPatterns.cpp b/pixelprojektor/NeoPatterns.cpp index b510538..de2697b 100644 --- a/pixelprojektor/NeoPatterns.cpp +++ b/pixelprojektor/NeoPatterns.cpp @@ -49,11 +49,17 @@ void NeoPatterns::Update() { case PLASMA: PlasmaUpdate(); break; + case FILL: + break; + case RANDOM: + break; case NONE: break; default: break; } + } else { + delay(1); } } @@ -98,7 +104,8 @@ void NeoPatterns::Reverse() { } } -void NeoPatterns::None() { +void NeoPatterns::None(uint8_t interval) { + Interval = interval; if (ActivePattern != NONE) { clear(); show(); @@ -290,6 +297,7 @@ void NeoPatterns::RandomBuffer() void NeoPatterns::Random() { None(); // Stop all other effects + ActivePattern = RANDOM; for (int i = 0; i < numPixels(); i++) { setPixelColor(i, Wheel(random(0, 256))); } @@ -413,6 +421,9 @@ void NeoPatterns::Icon(uint8_t fontchar, String iconcolor, uint8_t interval) SavedIndex = Index; SavedColor1 = Color1; SavedDirection = Direction; + SavedPlasmaPhase = PlasmaPhase; + SavedPlasmaPhaseIncrement = PlasmaPhaseIncrement; + SavedPlasmaColorStretch = PlasmaColorStretch; ActivePattern = ICON; Interval = interval; TotalSteps = 80; @@ -450,6 +461,9 @@ void NeoPatterns::IconComplete() Index = SavedIndex; Color1 = SavedColor1; Direction = SavedDirection; + PlasmaPhase = SavedPlasmaPhase; + PlasmaPhaseIncrement = SavedPlasmaPhaseIncrement; + PlasmaColorStretch = SavedPlasmaColorStretch; } // Based upon https://github.com/johncarl81/neopixelplasma @@ -516,6 +530,7 @@ void NeoPatterns::PlasmaUpdate() show(); } + /****************** Helper functions ******************/ void NeoPatterns::SetColor1(uint32_t color) { @@ -546,6 +561,7 @@ void NeoPatterns::ColorSet(uint32_t color) void NeoPatterns::ColorSetParameters(String parameters) { None(); + ActivePattern = FILL; ColorSet(parseColor(parameters)); } diff --git a/pixelprojektor/NeoPatterns.h b/pixelprojektor/NeoPatterns.h index 24a196a..bd02db2 100644 --- a/pixelprojektor/NeoPatterns.h +++ b/pixelprojektor/NeoPatterns.h @@ -2,7 +2,7 @@ #include "font.h" // Pattern types supported: -enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH, ICON, RANDOM_FADE_SINGLE, PLASMA }; +enum pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, RANDOM_FADE, SMOOTH, ICON, RANDOM_FADE_SINGLE, PLASMA, FILL, RANDOM }; // Patern directions supported: enum direction { FORWARD, REVERSE }; @@ -14,7 +14,7 @@ class NeoPatterns : public Adafruit_NeoPixel void Update(); void Reverse(); - void None(); + void None(uint8_t interval = 40); void RainbowCycle(uint8_t interval, direction dir = FORWARD); void RainbowCycleUpdate(); void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD); @@ -92,8 +92,12 @@ class NeoPatterns : public Adafruit_NeoPixel uint8_t FontChar; float PlasmaPhase; + float SavedPlasmaPhase; float PlasmaPhaseIncrement; + float SavedPlasmaPhaseIncrement; float PlasmaColorStretch; + float SavedPlasmaColorStretch; + uint32_t DimColor(uint32_t color); void Increment(); diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index b4dd61c..6945d90 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -6,7 +6,7 @@ #include #endif -#define PIN 2 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) +#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete); @@ -98,7 +98,8 @@ bool onSetEffect(const HomieRange& range, const String& value) { } else if (effect == "plasma") { strip.Plasma(); - } else { + } + else { // Test whether command with parameters was sent int sep = value.indexOf("|"); String command = value.substring(0, sep); From 8f8d0e7bf58548bd31d79f91209b79459ece984a Mon Sep 17 00:00:00 2001 From: starcalc Date: Fri, 3 Mar 2017 18:33:02 +0100 Subject: [PATCH 14/14] ctdo PIN --- pixelprojektor/pixelprojektor.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino index 6945d90..6079a5c 100644 --- a/pixelprojektor/pixelprojektor.ino +++ b/pixelprojektor/pixelprojektor.ino @@ -6,7 +6,7 @@ #include #endif -#define PIN D1 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) +#define PIN 2 //data pin for ws2812 (pixelprojektor @ ctdo: PIN 2) #define NUMPIXELS 64 NeoPatterns strip = NeoPatterns(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800, &StripComplete);