// // By Serge Skorodinsky, 11/15/2019 // #define FASTLED_ESP8266_RAW_PIN_ORDER #include #include "XYMatrix.h" #include "RGBGradientCalc.h" FASTLED_USING_NAMESPACE #include SSVTimer Tmr_effects; SSVTimer Tmr_effectChange; #define LED_PIN D8 //15 //ESP8266 Lolin ESP-12E module #define COLOR_ORDER GRB #define CHIPSET WS2811 #define BRIGHTNESS 64 // Params for width and height const uint8_t MatrixWidth = 16; const uint8_t MatrixHeight = 16; #define NUM_LEDS (MatrixWidth * MatrixHeight) CRGB leds[NUM_LEDS]; XYMatrix matrix(leds, MatrixWidth, MatrixHeight, true); timer_callback effect_functions[] = {TimerEffect1Func, TimerEffect2Func, TimerEffect3Func, TimerEffect4Func, TimerEffect5Func, TimerEffect6Func, TimerEffect7Func, TimerEffect8Func}; uint8_t effectnum=0; void WaitForSerial(char *serial_message) { Serial.println(serial_message); /* Serial.println("\r Press in serial terminal...\n"); while (Serial.available()) {Serial.read();} //to clear incoming buffer while (! (Serial.available() ) ) {}; //wait for any char while (Serial.available()) {Serial.read();} //to clear incoming buffer */ delay(5000); } void Tmr_EffectChange() { uint8_t arrsize = (sizeof(effect_functions))/(sizeof(effect_functions[0])); effectnum++; if (effectnum >= arrsize) effectnum=0; Tmr_effects.SetOnTimer(effect_functions[effectnum]); Serial.print("Change effect to #"); Serial.println(effectnum+1); } void setup() { Serial.begin(115200); Tmr_effects.SetInterval(20); Tmr_effects.SetOnTimer(effect_functions[0]); Tmr_effects.SetEnabled(true); Tmr_effectChange.SetOnTimer(Tmr_EffectChange); Tmr_effectChange.SetInterval(60000); //change once in a minute Tmr_effectChange.SetEnabled(false); FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalSMD5050); FastLED.setBrightness( BRIGHTNESS ); FastLED.clear (); FastLED.show(); delay(100); //for stability Serial.println();Serial.println(); //Demo started here //Dots matrix.setPixelColor(0,0, CRGB::Red); matrix.setPixelColor(1,0, CRGB::Red); matrix.setPixelColor(0,15, CRGB::Blue); matrix.setPixelColor(15,0, CRGB::Blue); matrix.setPixelColor(15,15, CRGB::Green); matrix.setPixelColor(Point(5,5), CRGB::White); matrix.setPixelColor(Point(5,10), CRGB::White); matrix.setPixelColor(Point(10,5), CRGB::White); matrix.setPixelColor(Point(10,10), CRGB::White); matrix.setPixelColor(100,100, CRGB::White); //ERROR, out of bounds, will be ignored FastLED.show(); WaitForSerial("Dots..."); //Lines FastLED.clear (); //matrix.draw_line (Point(0,7), Point(0,15), CRGB::Red); matrix.draw_line (Point(0,15), Point(2,7), CRGB::Blue); matrix.draw_line (Point(2,7), Point(6,15), CRGB::Green); matrix.draw_line (Point(6,15), Point(6,7), CRGB::Yellow); matrix.draw_line (Point(6,7), Point(14,15), CRGB::Magenta); matrix.draw_line (Point(14,15), Point(9,15), CRGB::Red, false); matrix.draw_line (Point(8,13), Point(12,9), CRGB::Pink); matrix.draw_line (Point(0,0), Point(3,3), CRGB::Gold); matrix.draw_line (Point(3,3), Point(6,0), CRGB::Gold); matrix.draw_line (Point(6,0), Point(9,3), CRGB::Gold); matrix.draw_line (Point(9,3), Point(12,0), CRGB::Gold); matrix.draw_line (Point(12,0), Point(15,3), CRGB::Gold); matrix.draw_line (Point(0,1), Point(3,4), CRGB::White); matrix.draw_line (Point(3,4), Point(6,1), CRGB::White); matrix.draw_line (Point(6,1), Point(9,4), CRGB::White); matrix.draw_line (Point(9,4), Point(12,1), CRGB::White); matrix.draw_line (Point(12,1), Point(15,4), CRGB::White); matrix.draw_line (Point(0,2), Point(3,5), CRGB::Red); matrix.draw_line (Point(3,5), Point(6,2), CRGB::Red); matrix.draw_line (Point(6,2), Point(9,5), CRGB::Red); matrix.draw_line (Point(9,5), Point(12,2), CRGB::Red); matrix.draw_line (Point(12,2), Point(15,5), CRGB::Red); matrix.draw_line (Point(0,3), Point(3,6), CRGB::DarkSalmon); matrix.draw_line (Point(3,6), Point(6,3), CRGB::DarkSalmon); matrix.draw_line (Point(6,3), Point(9,6), CRGB::DarkSalmon); matrix.draw_line (Point(9,6), Point(12,3), CRGB::DarkSalmon); matrix.draw_line (Point(12,3), Point(15,6), CRGB::DarkSalmon); FastLED.show(); WaitForSerial("Lines..."); //Rectangles using Lines FastLED.clear (); matrix.draw_line (0,0, 15,0, CRGB::Red, false); matrix.draw_line (15,0, 15,15, CRGB::Green, false); matrix.draw_line (15,15, 0,15, CRGB::Blue, false); matrix.draw_line (0,15, 0,0, CRGB::Yellow, false); // matrix.draw_line (2,2, 13,2, CRGB::White, false); matrix.draw_line (13,2, 13,13, CRGB::White, false); matrix.draw_line (13,13, 2,13, CRGB::White, false); matrix.draw_line (2,13, 2,2, CRGB::White, false); FastLED.show(); WaitForSerial("Rectangles using Lines..."); //Rectangles using draw_rect() FastLED.clear (); matrix.draw_rect(4,4, 0,0, CRGB::Red); matrix.draw_rect(Point(5,5), Point(10,10), CRGB::Brown); matrix.draw_rect(RectangleWH(Point(11,11), 4,4) , CRGB::Salmon); matrix.draw_rect(RectangleWH(Point(0, 11), 4,4), CRGB::DarkSalmon); matrix.draw_rect(Point(11,4), Point(15,0), CRGB::LightPink); matrix.draw_rect(Rectangle(Point(1,6), Point(3,9)), CRGB::Red); matrix.draw_rect(Rectangle(Point(12,9), Point(14,6)), CRGB::Green); matrix.draw_rect(Rectangle(Point(9,14), Point(6, 12)), CRGB::Blue); matrix.draw_rect(Rectangle(Point(9,1), Point(6, 3)), CRGB::White); FastLED.show(); WaitForSerial("Rectangles using draw_rect()..."); //Filled Rectangles FastLED.clear (); matrix.draw_fillrect(RectangleWH(Point(15,15), 0,0), CRGB::Blue); matrix.draw_fillrect(14,14, 13,13, CRGB::Blue); matrix.draw_fillrect(Point(12,12), Point(10,10), CRGB::Blue); matrix.draw_fillrect(RectangleWH(Point(6,6), 3,3), CRGB::Blue); matrix.draw_fillrect(RectangleWH(Point(1,1), 4,4), CRGB::Blue); matrix.draw_fillrect(Rectangle(Point(0,15), Point(2,13)), CRGB::White); matrix.draw_fillrect(Rectangle(Point(3,12), Point(5,10)), CRGB::White); matrix.draw_fillrect(Rectangle(Point(15,0), Point(14,1)), CRGB::Red); matrix.draw_fillrect(Rectangle(Point(13,2), Point(12,3)), CRGB::Red); matrix.draw_fillrect(Rectangle(Point(11,4), Point(10,5)), CRGB::Red); FastLED.show(); WaitForSerial("Filled Rectangles..."); //Quarter-Circles FastLED.clear (); matrix.draw_quarterCircle(7, 7, 8, 0x02+0x04+0x08, CRGB::Magenta, true); matrix.draw_quarterCircle(7, 7, 7, 0x01+0x04+0x08, CRGB::Red, true); matrix.draw_quarterCircle(7, 7, 6, 0x01+0x02+0x04, CRGB::Blue, false); matrix.draw_quarterCircle(7, 7, 5, 0x01+0x04+0x08, CRGB::Green, false); matrix.draw_quarterCircle(7, 7, 4, 0x01+0x02+0x04, CRGB::Yellow, false); matrix.draw_quarterCircle(7, 7, 2, 0x01+0x04, CRGB::Crimson, true); FastLED.show(); WaitForSerial("Quarter-Circles..."); //Quarter-FilledCircles FastLED.clear (); matrix.draw_quarterFillCircle(7, 7, 8, 0x02+0x04+0x08, CRGB::Magenta, true); matrix.draw_quarterFillCircle(7, 7, 7, 0x01+0x04+0x08, CRGB::Red, true); matrix.draw_quarterFillCircle(7, 7, 6, 0x01+0x02+0x04, CRGB::Blue, false); matrix.draw_quarterFillCircle(7, 7, 5, 0x01+0x04+0x08, CRGB::Green, false); matrix.draw_quarterFillCircle(7, 7, 4, 0x01+0x02+0x04, CRGB::Yellow, false); matrix.draw_quarterFillCircle(7, 7, 2, 0x01+0x04, CRGB::Crimson, true); FastLED.show(); WaitForSerial("Quarter-FilledCircles..."); //Circles FastLED.clear (); matrix.draw_circle(7, 7, 8, CRGB::Yellow); matrix.draw_circle(7, 7, 7, CRGB::Red); matrix.draw_circle(7, 7, 6, CRGB::Green); matrix.draw_circle(7, 7, 5, CRGB::Blue); matrix.draw_circle(7, 7, 4, CRGB::FireBrick); matrix.draw_circle(7, 7, 3, CRGB::Pink); matrix.draw_circle(7, 7, 2, CRGB::Blue); matrix.draw_circle(7, 7, 1, CRGB::Magenta); matrix.draw_circle(7, 7, 0, CRGB::White); FastLED.show(); WaitForSerial("Circles..."); //Filled Circles FastLED.clear (); matrix.draw_fillCircle(7, 7, 8, CRGB::Yellow); matrix.draw_fillCircle(7, 7, 7, CRGB::Red); matrix.draw_fillCircle(7, 7, 6, CRGB::Green); matrix.draw_fillCircle(7, 7, 5, CRGB::Blue); matrix.draw_fillCircle(7, 7, 4, CRGB::FireBrick); matrix.draw_fillCircle(7, 7, 3, CRGB::Pink); matrix.draw_fillCircle(7, 7, 2, CRGB::Blue); matrix.draw_fillCircle(7, 7, 1, CRGB::Magenta); matrix.draw_fillCircle(7, 7, 0, CRGB::White); FastLED.show(); WaitForSerial("Filled Circles..."); //2D Rainbow, full size matrix.draw_2DRainbow( 0, Point(7,7), 4, 32); FastLED.show(); WaitForSerial("2D Rainbow, full matrix..."); //2D Rainbow, four frames FastLED.clear (); RectangleWH R1 = {Point(0,0), 7, 7}; matrix.draw_2DRainbow(R1, 0, Point(0,0), 4, 32); RectangleWH R2 = {Point(8,0), 7, 7}; matrix.draw_2DRainbow(R2, 64, Point(8,0), 16, 16); RectangleWH R3 = {Point(0,8), 7, 7}; matrix.draw_2DRainbow(R3, 128, Point(0,8), 4, 4); RectangleWH R4 = {Point(8,8), 7, 7}; matrix.draw_2DRainbow(R4, 192, Point(8,8), 32, 4); FastLED.show(); WaitForSerial("2D Rainbow, four frames..."); FastLED.clear (); //2D gradient FastLED.clear (); RectangleWH RG1 = {Point(0,7), 4, 4}; RectangleWH RG2 = {Point(7,0), 4, 4}; RectangleWH RG3 = {Point(9,9), 4, 4}; CRGB c1 = CRGB::Red; CRGB c2 = CRGB::Green; CRGB c3 = CRGB::Blue; CRGB c4 = CRGB::Yellow; matrix.draw_2DGradient(RG1, c1, c2, c3, c4); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) matrix.draw_2DGradient(RG2, c1, c2, c3, c4); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) matrix.draw_2DGradient(RG3, c1, c2, c3, c4); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) FastLED.show(); WaitForSerial("2D Gradient..."); FastLED.clear (); //done, prepare to start main loop Tmr_effectChange.SetEnabled(true); Serial.println("Effect #1"); } void TimerEffect1Func() { //FastLED.clear (); //not needed, all matrix updated anyway uint32_t ms = millis(); int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / MatrixWidth)); int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / MatrixHeight)); RectangleWH R1 = {Point(0,0), 7, 7}; matrix.draw_2DRainbow(R1, ms/65536*1000, Point(3,3), yHueDelta32/32768, xHueDelta32/32768); RectangleWH R2 = {Point(8,0), 7, 7}; matrix.draw_2DRainbow(R2, ms/65536*100, Point(11,3), xHueDelta32/32768*2, yHueDelta32/32768*2); RectangleWH R3 = {Point(0,8), 7, 7}; matrix.draw_2DRainbow(R3, ms/65536*500, Point(3,11), yHueDelta32/32768*2, xHueDelta32/32768*2); RectangleWH R4 = {Point(8,8), 7, 7}; matrix.draw_2DRainbow(R4, ms/65536*2000, Point(11,11), xHueDelta32/32768, yHueDelta32/32768); FastLED.show(); } void TimerEffect2Func() { //FastLED.clear (); //not needed, all matrix updated anyway uint32_t ms = millis(); int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / MatrixWidth)); int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / MatrixHeight)); RectangleWH R1 = {Point(0,0), 15, 15}; matrix.draw_2DRainbow(R1, ms/65536*1000, Point(3,3), yHueDelta32/32768, xHueDelta32/32768); FastLED.show(); } void TimerEffect3Func() { fadeToBlackBy( leds, NUM_LEDS, 10); uint8_t posX = triwave8(beat8(41)) /16; uint8_t posY = triwave8(beat8(20)) /16; uint8_t hue = beat8(5); matrix.setPixelColor(posX,posY, CHSV( hue, 255, 255) ); FastLED.show(); } void TimerEffect4Func() { /* colors layout: 3 6 9 2 5 8 1 4 7 */ CRGB cCorners = CHSV( triwave8(beat8(6)), 255, triwave8(beat8(7))); CRGB cMidSides = CHSV( triwave8(beat8(5)), 255, triwave8(beat8(3))); CRGB cCenter = CHSV( triwave8(beat8(4)), 255, triwave8(beat8(2))); CRGB c1 = cCorners; CRGB c3 = cCorners; CRGB c7 = cCorners; CRGB c9 = cCorners; CRGB c2 = cMidSides; CRGB c4 = cMidSides; CRGB c6 = cMidSides; CRGB c8 = cMidSides; CRGB c5 = cCenter; RectangleWH R1 = {Point(0,0), 7, 7}; RectangleWH R2 = {Point(8,0), 7, 7}; RectangleWH R3 = {Point(0,8), 7, 7}; RectangleWH R4 = {Point(8,8), 7, 7}; matrix.draw_2DGradient(R1, c1, c2, c4, c5); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) matrix.draw_2DGradient(R2, c4, c5, c7, c8); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) matrix.draw_2DGradient(R3, c2, c3, c5, c6); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) matrix.draw_2DGradient(R4, c5, c6, c8, c9); // LeftBottomColor, LeftTopColor, RightBottomColor, RightTopColor) FastLED.show(); } void TimerEffect5Func() { fadeToBlackBy( leds, NUM_LEDS, 10); long how_often=250; //mS if ((Tmr_effects.GetCounter() % ( how_often / Tmr_effects.GetInterval() ) ) == 0) //every how_often mS { uint8_t s=random(3,10); //square size RectangleWH R = {Point(random(15-s), random(15-s)), s, s}; if (random(255) > 128) matrix.draw_rect(R, CHSV( random(255), 255, 255)); else matrix.draw_fillrect(R, CHSV( random(255), 255, 255)); } FastLED.show(); } void TimerEffect6Func() { fadeToBlackBy( leds, NUM_LEDS, 10); long how_often=250; //mS if ((Tmr_effects.GetCounter() % ( how_often / Tmr_effects.GetInterval() ) ) == 0) //every how_often mS { uint8_t r=random(2,6); //radius uint8_t cx = random (r, MatrixWidth-r); uint8_t cy = random (r, MatrixHeight-r); if (random(255) > 128) matrix.draw_circle(cx, cy, r, CHSV( random(255), 255, 255)); else matrix.draw_fillCircle(cx, cy, r, CHSV( random(255), 255, 255)); } FastLED.show(); } void TimerEffect7Func() { fadeToBlackBy( leds, NUM_LEDS, 10); long how_often=250; //mS if ((Tmr_effects.GetCounter() % ( how_often / Tmr_effects.GetInterval() ) ) == 0) //every how_often mS { uint8_t x1 = random (MatrixWidth-1); uint8_t y1 = random (MatrixHeight-1); uint8_t x2 = random (MatrixWidth-1); uint8_t y2 = random (MatrixHeight-1); matrix.draw_line(x1, y1, x2, y2, CHSV( random(255), 255, 255)); } FastLED.show(); } void TimerEffect8Func() { fadeToBlackBy( leds, NUM_LEDS, 10); int16_t r = 2; uint8_t posCX = beatsin8(20, r, MatrixWidth-r, 0, 0 ); uint8_t posCY = beatsin8(20, r, MatrixHeight-r, 0, 64 ); //90 deg phase shift uint8_t hue = beat8(5); matrix.draw_circle(posCX, posCY, r, CHSV(hue, 255, 255) ); FastLED.show(); } void loop() { Tmr_effects.RefreshIt(); Tmr_effectChange.RefreshIt(); }