//simle rotozoomer procedure
//fast led rgb matrix 16x16 demo
//Yaroslaw Turbin, 03.11.2020
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//how it's look in emulator: https://wokwi.com/arduino/projects/281176629596652040
// https://editor.soulmatelights.com/gallery/457
#include "FastLED.h"
// Matrix size
#define NUM_ROWS 30
#define NUM_COLS 13
#define NUM_LEDS NUM_ROWS * NUM_COLS
struct pos_f{ float x; float y;};
struct pos_8{ uint8_t x; uint8_t y;};
//const uint8_t vHeight = NUM_COLS;
//const uint8_t vWidth = NUM_ROWS;
uint8_t vWidth = NUM_COLS;
uint8_t vHeight = NUM_ROWS;
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];
uint16_t ledPixelPos[NUM_LEDS][2];
DEFINE_GRADIENT_PALETTE( temperature_gp ) {
0, 1, 27,105,
14, 1, 40,127,
28, 1, 70,168,
42, 1, 92,197,
56, 1,119,221,
70, 3,130,151,
84, 23,156,149,
99, 67,182,112,
113, 121,201, 52,
127, 142,203, 11,
141, 224,223, 1,
155, 252,187, 2,
170, 247,147, 1,
184, 237, 87, 1,
212, 229, 43, 1,
226, 220, 15, 1,
240, 171, 2, 2,
// 255, 80, 3, 3};
255, 1, 27, 105};
CRGBPalette16 myPal;
pos_f nextCenter = {6.0,15.0};
pos_f moveCenter = {0.0,0.0};
pos_f waveCenter = {6.0,15.0};
float hueSpeed = 40; // update hue delay
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
Serial.begin(115200);
setLedPxPos();
myPal = temperature_gp;
}
void loop() {
EVERY_N_MILLIS(10){
// plasma();
// movingWave();
rotozum ();
// rotationRainbow();
showOnlyCenter();
FastLED.show();
}
EVERY_N_MILLIS(400){
Serial.print(nextCenter.x);Serial.print('\t');Serial.print(nextCenter.y);;Serial.print('\t');
Serial.print(moveCenter.x);Serial.print('\t');Serial.print(moveCenter.y);Serial.print('\t');
Serial.print(waveCenter.x);Serial.print('\t');Serial.print(waveCenter.y);
//Serial.print();Serial.print('\t');
Serial.println();
}
}
void plasma(){
uint8_t zoom = 30; // zoom 20 to 80
float speed = 0.1;
uint16_t ms = speed*millis();
for( int i = 0; i< NUM_LEDS; i++){
uint8_t x = ledPixelPos[i][0];
uint8_t y = ledPixelPos[i][1];
byte noises = inoise8 (y * zoom, x * zoom, ms);
leds[XY(x,y)] = ColorFromPalette (myPal, noises, BRIGHTNESS );
}
}
uint16_t XY (uint8_t x, uint8_t y) { return (y * NUM_COLS + x);} //simple function to find led number in led matrix,
//change this to your routine
//or generate XY function for your matrix there:
//https://macetech.github.io/FastLED-XY-Map-Generator/
void setLedPxPos(){
for (int i = 0; i < NUM_LEDS; i++){
ledPixelPos[i][0] = i % NUM_COLS;
ledPixelPos[i][1] = i / NUM_COLS;
}
}
void showOnlyCenter(){
for( int x = 0; x < vWidth ; x++){
for( int y = 0; y < vHeight ; y++){
if(x != 6) leds[XY(x,y)] = nblend(leds[XY(x,y)],CRGB::Black,127);
//if(x != 6) leds[XY(x,y)] = CRGB::Black;
}
}
}
pos_f getRandomPoint(){ return {random( 0, vWidth), random( 0, vHeight)};}
//pos_f getStep(pos_f posCurrent, pos_f posTarget){ return {(posTarget.x - posCurrent.x) / 50 , (posTarget.y - posCurrent.y) / 50 };}
pos_f getStep(pos_f posCurrent, pos_f posTarget){
pos_f deltaPos = {(posTarget.x - posCurrent.x) , (posTarget.y - posCurrent.y) };
float dist = sqrt(sq(deltaPos.x)+sq(deltaPos.y)) / sqrt(sq(vWidth)+sq(vHeight)); // normalized distance
return {deltaPos.x * dist / 30 , deltaPos.y * dist / 30 };
}
void movingWave(){
static uint16_t hueOffset = 0; // counter for radial color wave motion
static int plasVector = 0;// 0; // counter for orbiting plasma center
static float zoom = 6; //0.7; // 0.5 is close and 10 is zoomed out
static uint8_t yDelta = 128;
static uint8_t yDeltaMax = NUM_LEDS/2 + 2;
float xOffA = -waveCenter.x;
float yOffA = -waveCenter.y;
float xOffB = -nextCenter.x;
float yOffB = -nextCenter.y;
for( int i = 0; i < (NUM_LEDS); i++ ){
int x = ledPixelPos[i][0];
int y = ledPixelPos[i][1];
byte color;
float waveCenterDistA = sqrt(sq(((float)x + xOffA)*zoom) + sq(((float)y + yOffA )* zoom)) ;
color = sin8(waveCenterDistA + hueOffset) ;
leds[i] = ColorFromPalette(myPal, color, 255, LINEARBLEND);
}
EVERY_N_MILLIS(40){
hueOffset-= 3;
if((int)waveCenter.x != (int)nextCenter.x && (int)waveCenter.y != (int)nextCenter.y){
waveCenter.x += moveCenter.x;
waveCenter.y += moveCenter.y;
}
else if(waveCenter.x < 0 || waveCenter.y < 0 || waveCenter.x > vWidth || waveCenter.y > vHeight);}
else{
nextCenter = getRandomPoint();
moveCenter = getStep(waveCenter,nextCenter);
}
}
//}
void rotationRainbow() // ---- palettemix
{
float zoom = 10;
uint32_t ms = millis();
//int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / vWidth));
//int32_t xHueDelta32 = ((int32_t)sin16( ms * (39/1) ) * (310 / vHeight));
int32_t yHueDelta32 = ((int32_t)cos16( (ms * (17.0/1.0)) + vWidth/2) * (35*zoom / vWidth));
int32_t xHueDelta32 = ((int32_t)cos16( (ms * (29.0/1.0)) + vHeight/2) * (31*zoom / vHeight));
DrawOneFrame( ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768 + 3*zoom);
}
void DrawOneFrame( byte startHue8, int8_t yHueDelta8, int8_t xHueDelta8){
Serial.print(startHue8 );Serial.print('\t');Serial.print(yHueDelta8);Serial.print('\t');Serial.println(xHueDelta8);
for( int i = 0; i< NUM_LEDS; i++){
uint8_t x = i % NUM_COLS;
uint8_t y = i / NUM_COLS;
byte pixelHue = (startHue8 + (yHueDelta8 * (y+1))) + (xHueDelta8 * (x+1));
leds[XY(x, y)] = CHSV( pixelHue, 255, 255);
}
}
uno:SCL
uno:SDA
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:14
uno:15
uno:16
uno:17
uno:18
uno:19
uno:20
uno:21
uno:5V.1
uno:5V.2
uno:22
uno:23
uno:24
uno:25
uno:26
uno:27
uno:28
uno:29
uno:30
uno:31
uno:32
uno:33
uno:34
uno:35
uno:36
uno:37
uno:38
uno:39
uno:40
uno:41
uno:42
uno:43
uno:44
uno:45
uno:46
uno:47
uno:48
uno:49
uno:50
uno:51
uno:52
uno:53
uno:GND.4
uno:GND.5
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
uno:A6
uno:A7
uno:A8
uno:A9
uno:A10
uno:A11
uno:A12
uno:A13
uno:A14
uno:A15
neopixels:DOUT
neopixels:VDD
neopixels:VSS
neopixels:DIN