//#include <Adafruit_GFX.h>
//#include <Adafruit_NeoPixel.h>
//#include <Adafruit_NeoMatrix.h>
#include "FastLED.h"
#define PIN 6
#define MATRIX_HEIGHT 32
#define MATRIX_WIDTH 32
#define NUM_LEDS MATRIX_WIDTH * MATRIX_HEIGHT
#define SPARKLES 1 // вылетающие угольки вкл выкл
#define HUE_ADD 20 // добавка цвета в огонь (от 0 до 230) - меняет весь цвет пламени
#define BRIGHTNESS 200
#define THRESHOLD 20
CRGB leds[NUM_LEDS];
/*Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
MATRIX_WIDTH, MATRIX_HEIGHT,
PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
NEO_GRB + NEO_KHZ800
);*/
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
//these values are substracted from the generated values to give a shape to the animation
const unsigned char valueMask[MATRIX_HEIGHT][MATRIX_WIDTH] PROGMEM={
{64, 32, 16, 0, 0, 0, 0, 16, 48, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, 32},
{80, 48, 32, 0, 0, 0, 0, 32, 64, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, 32, 48},
{96, 64, 48, 16, 0, 0, 16, 48, 80, 64, 48, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 48, 48, 16, 0, 0, 0, 0, 0, 16, 48, 64},
{112, 80, 64, 32, 0, 0, 32, 64, 96, 80, 64, 32, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 64, 32, 0, 0, 0, 0, 0, 32, 64, 80},
{128, 96, 80, 48, 16, 16, 48, 80, 112, 96, 80, 48, 16, 0, 0, 0, 0, 0, 0, 16, 48, 80, 80, 48, 16, 0, 0, 0, 0, 48, 80, 96},
{144, 112, 96, 64, 32, 32, 64, 96, 128, 112, 96, 64, 32, 0, 0, 0, 0, 0, 0, 32, 64, 96, 96, 64, 32, 0, 0, 0, 0, 64, 96, 112},
{160, 128, 112, 80, 48, 48, 80, 112, 144, 128, 112, 80, 48, 0, 0, 0, 0, 0, 0, 48, 80, 112, 112, 80, 48, 0, 0, 0, 0, 80, 112, 128},
{176, 144, 128, 96, 64, 64, 96, 128, 160, 144, 128, 96, 64, 16, 0, 0, 0, 0, 16, 64, 96, 128, 128, 96, 64, 16, 0, 0, 16, 96, 128, 144},
{192, 160, 144, 112, 80, 80, 112, 144, 176, 160, 144, 112, 80, 32, 0, 0, 0, 0, 32, 80, 112, 144, 144, 112, 80, 32, 0, 0, 32, 112, 144, 160},
{208, 176, 160, 128, 96, 96, 128, 160, 192, 176, 160, 128, 96, 48, 0, 0, 0, 0, 48, 96, 128, 160, 160, 128, 96, 48, 0, 0, 48, 128, 160, 176},
{224, 192, 176, 144, 112, 112, 144, 176, 208, 192, 176, 144, 112, 64, 16, 16, 16, 16, 64, 112, 144, 176, 176, 144, 112, 64, 16, 16, 64, 144, 176, 192},
{240, 208, 192, 160, 128, 128, 160, 192, 224, 208, 192, 160, 128, 80, 32, 32, 32, 32, 80, 128, 160, 192, 192, 160, 128, 80, 32, 32, 80, 160, 192, 208},
{255, 224, 208, 176, 144, 144, 176, 208, 240, 224, 208, 176, 144, 96, 48, 48, 48, 48, 96, 144, 176, 208, 208, 176, 144, 96, 48, 48, 96, 176, 208, 224},
{255, 240, 224, 192, 160, 160, 192, 224, 255, 240, 224, 192, 160, 112, 64, 64, 64, 64, 112, 160, 192, 224, 224, 192, 160, 112, 64, 64, 112, 192, 224, 240},
{255, 255, 240, 208, 176, 176, 208, 240, 255, 255, 240, 208, 176, 128, 80, 80, 80, 80, 128, 176, 208, 240, 240, 208, 176, 128, 80, 80, 128, 208, 240, 255},
{255, 255, 255, 224, 192, 192, 224, 255, 255, 255, 255, 224, 192, 144, 96, 96, 96, 96, 144, 192, 224, 255, 255, 224, 192, 144, 96, 96, 144, 224, 255, 255},
{255, 255, 255, 240, 208, 208, 240, 255, 255, 255, 255, 240, 208, 160, 112, 112, 112, 112, 160, 208, 240, 255, 255, 240, 208, 160, 112, 112, 160, 240, 255, 255},
{255, 255, 255, 240, 224, 224, 240, 255, 255, 255, 255, 255, 224, 176, 128, 128, 128, 128, 176, 224, 255, 255, 255, 240, 224, 176, 128, 128, 176, 240, 255, 255},
{255, 255, 255, 240, 224, 224, 240, 255, 255, 255, 255, 255, 240, 192, 144, 144, 144, 144, 192, 240, 255, 255, 255, 240, 224, 192, 144, 144, 192, 240, 255, 255},
{255, 255, 255, 240, 224, 224, 240, 255, 255, 255, 255, 255, 255, 208, 192, 160, 160, 192, 208, 255, 255, 255, 255, 240, 224, 208, 160, 160, 208, 240, 255, 255},
};
//these are the hues for the fire,
//should be between 0 (red) to about 25 (yellow)
const unsigned char hueMask[MATRIX_HEIGHT][MATRIX_WIDTH] PROGMEM={
{5, 10, 20, 30, 40, 40, 30, 20, 10, 5, 15, 25, 35, 45, 45, 45, 45, 45, 40, 25, 15, 5, 5, 10, 25, 40, 45, 45, 40, 25, 10, 5},
{0, 5, 10, 20, 30, 30, 20, 10, 5, 0, 10, 20, 25, 40, 43, 43, 43, 40, 35, 20, 10, 0, 0, 0, 20, 35, 40, 40, 35, 20, 5, 0},
{0, 0, 5, 10, 20, 20, 10, 5, 0, 0, 5, 15, 20, 35, 40, 40, 40, 35, 15, 15, 5, 0, 0, 0, 15, 30, 35, 35, 30, 15, 0, 0},
{0, 0, 0, 5, 10, 10, 5, 0, 0, 0, 0, 10, 15, 20, 35, 35, 30, 20, 10, 10, 0, 0, 0, 0, 10, 25, 30, 30, 25, 10, 0, 0},
{0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 10, 15, 30, 30, 20, 15, 5, 5, 0, 0, 0, 0, 5, 20, 25, 25, 20, 5, 0, 0},
{0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 5, 10, 25, 25, 15, 10, 0, 0, 0, 0, 0, 0, 0, 15, 20, 20, 15, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 20, 20, 10, 0, 0, 0, 0, 0, 0, 0, 0, 10, 15, 15, 10, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 5, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
unsigned char matrixValue[MATRIX_HEIGHT][MATRIX_WIDTH];
unsigned char line[MATRIX_WIDTH];
int pcnt = 0;
void setup() {
FastLED.addLeds<WS2812, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
generateLine();
//init all pixels to zero
memset(matrixValue, 0, sizeof(matrixValue));
}
void loop() {
if (pcnt >= 100) {
shiftUp();
generateLine();
pcnt = 0;
}
drawFrame(pcnt);
FastLED.show();
pcnt+=30;
}
/*//Converts an HSV color to RGB color
uint16_t HSVtoRGB(uint8_t ih, uint8_t is, uint8_t iv) {
float r, g, b, h, s, v; //this function works with floats between 0 and 1
float f, p, q, t;
int i;
h = (float)(ih / 256.0);
s = (float)(is / 256.0);
v = (float)(iv / 256.0);
//if saturation is 0, the color is a shade of grey
if(s == 0.0) {
b = v;
g = b;
r = g;
}
//if saturation > 0, more complex calculations are needed
else
{
h *= 6.0; //to bring hue to a number between 0 and 6, better for the calculations
i = (int)(floor(h)); //e.g. 2.7 becomes 2 and 3.01 becomes 3 or 4.9999 becomes 4
f = h - i;//the fractional part of h
p = (float)(v * (1.0 - s));
q = (float)(v * (1.0 - (s * f)));
t = (float)(v * (1.0 - (s * (1.0 - f))));
switch(i)
{
case 0: r=v; g=t; b=p; break;
case 1: r=q; g=v; b=p; break;
case 2: r=p; g=v; b=t; break;
case 3: r=p; g=q; b=v; break;
case 4: r=t; g=p; b=v; break;
case 5: r=v; g=p; b=q; break;
default: r = g = b = 0; break;
}
}
return matrix.Color(r * 255.0, g * 255.0, b * 255.0);
}*/
/**
* Randomly generate the next line (matrix row)
*/
void generateLine(){
for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
line[x] = random(64, 255);
}
}
/**
* shift all values in the matrix up one row
*/
void shiftUp() {
for (uint8_t y=MATRIX_HEIGHT-1; y>0; y--) {
for (uint8_t x=0; x<MATRIX_WIDTH; x++) {
matrixValue[y][x] = matrixValue[y-1][x];
}
}
for (uint8_t x=0; x<MATRIX_WIDTH; x++) {
matrixValue[0][x] = line[x];
}
}
/**
* draw a frame, interpolating between 2 "key frames"
* @param pcnt percentage of interpolation
*/
void drawFrame(int pcnt) {
int nextv;
//each row interpolates with the one before it
for (unsigned char y = MATRIX_HEIGHT - 1; y > 0; y--) {
for (unsigned char x = 0; x < MATRIX_WIDTH; x++) {
//uint8_t newX = x;
//if (x > 15) newX = x - 15;
if (y < THRESHOLD) {
nextv =
(((100.0 - pcnt) * matrixValue[y][x]
+ pcnt * matrixValue[y - 1][x]) / 100.0)
- pgm_read_byte(&(valueMask[y][x]));
CRGB color = CHSV(
HUE_ADD + pgm_read_byte(&(hueMask[y][x])), // H
255, // S
(uint8_t)max(0, nextv) // V
);
leds[getPixelNumber(x, y)] = color;
} else if (y == 8 && SPARKLES) {
if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) drawPixelXY(x, y, getPixColorXY(x, y - 1));
else drawPixelXY(x, y, 0);
} else if (SPARKLES) {
// старая версия для яркости
if (getPixColorXY(x, y - 1) > 0)
drawPixelXY(x, y, getPixColorXY(x, y - 1));
else drawPixelXY(x, y, 0);
}
}
}
//first row interpolates with the "next" line
for(unsigned char x=0; x<MATRIX_WIDTH; x++) {
CRGB color = CHSV(
HUE_ADD + pgm_read_byte(&(hueMask[0][x])), // H
255, // S
(uint8_t)(((100.0 - pcnt) * matrixValue[0][x] + pcnt * line[x]) / 100.0) // V
);
leds[getPixelNumber(x, 0)] = color;
}
}
// функция отрисовки точки по координатам X Y
void drawPixelXY(int8_t x, int8_t y, CRGB color) {
if (x < 0 || x > MATRIX_WIDTH - 1 || y < 0 || y > MATRIX_HEIGHT - 1) return;
int thisPixel = getPixelNumber(x, y);
leds[thisPixel] = color;
}
// функция получения цвета пикселя по его номеру
uint32_t getPixColor(int thisSegm) {
int thisPixel = thisSegm;
if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0;
return (((uint32_t)leds[thisPixel].r << 16) | ((long)leds[thisPixel].g << 8 ) | (long)leds[thisPixel].b);
}
// функция получения цвета пикселя в матрице по его координатам
uint32_t getPixColorXY(int8_t x, int8_t y) {
return getPixColor(getPixelNumber(x, y));
}
////перевод матричногоэлемента в линейный////
uint16_t getPixelNumber (int8_t x_stripe, int8_t y_stripe){
//int stripe_n;
if (y_stripe < 16){
//if (x_stripe%2 == 0) stripe_n=16*(x_stripe+1)-(y_stripe+1);
//else stripe_n=16*(x_stripe+1)+(y_stripe+1)-17;
return 16*(x_stripe+1)+(y_stripe+1)-17;
}
else{
//if (x_stripe%2 == 0) stripe_n=-16*(x_stripe+1)-(y_stripe+1)+1056;
//else stripe_n=-16*x_stripe+y_stripe+992;
return -16*(x_stripe+1)-(y_stripe+1)+1056;
}
//return stripe_n;
}