Зарегистрироваться

Красивая гирлянда из того что есть или запускаем скетч (с библиотекой Adafruit_NeoPixel.h) на ленте WS2801

Всем доброго времени суток. Хочу Вам рассказать, как сделать себе праздник (новогоднее настроение) из того что есть под рукой. А в частности: arduion nano, диодная лента WS2801 и красивые скетчи «гирлянды» работающие при помощи библиотеки Adafruit_NeoPixel.h. Может мои «открытия» для опытных ардуинщиков будут несерьезными. Но мне это пригодилось и я решил поделиться с остальными.

И так в преддверии нового года захотелось мне сделать новогоднюю гирлянду. Из имеющегося дома была диодная «лента» WS2801 на 50 диодов (на фото). Можно было бы заказать WS2811 или WS2812, но что-то мне подсказывало, что до нового года не успела бы лента приехать.

Сначала сделал для гирлянды что бы цвета шли по кругу переливами оттенков.
Скетч с переливами цвета
#include «FastLED.h»

#define LEDS1_NUM 50
#define LEDS1_PIN 11

#define LEDS_SATURATION 255
#define LEDS_BRIGHTNESS 255

CRGB leds[LEDS1_NUM];
byte hueCurrent = 0;
byte hueDestination = 0;
char hueStep = 5;

#define UPDATE_DELAY 50

void setup() {
FastLED.addLeds<WS2801, LEDS1_PIN, 13, RGB>(leds, 0, LEDS1_NUM);
// Adjust data rate if you have issues: 0-fast, 7-slow
//FastLED.setDataRate(3);
for (int ii=0; ii< (LEDS1_NUM); ii++) {
leds[ii] = CHSV(hueCurrent, LEDS_SATURATION, LEDS_BRIGHTNESS);
}
randomSeed(analogRead(0));
}

void loop() {
if (abs(hueCurrent — hueDestination) < hueStep) {
hueDestination = random(255);
hueStep = ((hueCurrent < hueDestination) && (hueStep < 0))? hueStep: -hueStep;
}
hueCurrent += hueStep;
pushLed(hueCurrent);
FastLED.show();
delay(UPDATE_DELAY);
}

void pushLed(byte hueValue) {
for (int ii=0; ii<(LEDS1_NUM — 1); ii++) {
leds[ii] = leds[ii+1];
}
leds[LEDS1_NUM — 1].setHSV(hueValue, LEDS_SATURATION, LEDS_BRIGHTNESS);
}


И вроде все красиво. Но как то это не по-новогоднему. Нужно что бы моргало и переливалось.
Нашел набор скетчей (много разных и красивых) yadi.sk/d/k4phCXlZ3Qg2uo
Но была проблема. Все они сделаны по отдельности, а хотелось что бы было разнообразие в одном флаконе.

Расстроенный я продолжил искать на просторах интернета скетчи для гирлянды.
И мне повезло. Нашел скетч в котором было реализовано более 10 режимов. Все это на 200 диодов и с возможностью указания координат расположения диод на на елки (для создания симметричных эффектов)
Оригинальный скетч для гирлянды
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN 6
#define LED_COUNT 200
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ400);

//MAX_X and MAX_Y represent the largest X and Y value from the table of Positions
//This is used to derive where the middle of the tree is in the X and Y direction.
//For example if MAX_X = 20, then LEDs at a position of 10 would be the middle of
//the tree.
#define MAX_X 18
#define MAX_Y 30

//Define the X,Y positions of each pixel. The first array element is the X
//coordinate of the first LED in the string, the second array element is the
//Y coordinate of the first LED. The third array element is the X position of
//the second LED, etc…
byte Positions[LED_COUNT*2] =
{
7, 6, 7, 7, 6, 7, 5, 8, 4, 6, 3, 7, 3, 6, 2, 6, 3, 6, 1, 7, // 0 — 9
1, 8, 2, 9, 2,10, 2,11, 2,12, 4,12, 4,12, 4,13, 4,12, 5,12, //10 — 19
5,10, 6, 9, 7,10, 8,12, 8,11, 8,13, 8,13, 8,15, 7,14, 6,13, //20 — 29
6,15, 5,14, 3,15, 3,14, 3,14, 4,17, 5,16, 4,16, 5,16, 7,17, //30 — 39
7,17, 9,16, 9,16, 10,18, 9,19, 8,20, 8,19, 7,18, 6,20, 6,18, //40 — 49
5,17, 4,17, 4,17, 6,18, 4,18, 4,18, 6,20, 6,22, 6,22, 7,20, //50 — 59
6,20, 8,21, 8,22, 8,22, 10,22, 10,23, 10,24, 9,24, 7,24, 8,23, //60 — 69
6,23, 7,23, 6,23, 5,23, 6,22, 5,21, 7,24, 6,22, 6,24, 7,25, //70 — 79
6,25, 7,26, 7,27, 7,27, 7,26, 9,26, 9,27, 9,28, 9,28, 8,28, //80 — 89
8,28, 8,27, 7,26, 7,26, 6,26, 8,28, 8,28, 9,30, 9,30, 9,30, //90 — 99
12,30, 12,29, 12,28, 13,28, 13,28, 13,27, 12,26, 11,27, 10,26, 12,25, //100-109
11,24, 12,24, 14,24, 14,25, 14,24, 14,23, 14,23, 15,22, 15,22, 13,22, //110-119
13,23, 13,22, 12,22, 13,22, 11,22, 11,22, 10,21, 11,21, 11,22, 12,21, //120-129
14,21, 13,20, 14,21, 14,21, 15,22, 16,21, 17,21, 18,19, 18,18, 16,17, //130-139
16,16, 16,16, 16,18, 16,18, 14,18, 15,19, 14,18, 12,19, 11,18, 11,18, //140-149
11,15, 10,15, 10,16, 12,15, 12,14, 13,15, 13,15, 14,15, 15,15, 16,15, //150-159
16,15, 17,16, 17,14, 17,14, 16,14, 18,13, 17,12, 18,11, 18,11, 15,11, //160-169
15,10, 14,10, 14,11, 13,11, 13,12, 11,11, 11, 9, 9, 9, 9, 8, 7, 9, //170-179
7, 7, 8, 6, 9, 8, 11, 6, 12, 6, 13, 7, 14, 7, 16, 8, 16, 8, 16,10, //180-189
16,10, 18, 9, 17, 8, 19,12, 20, 9, 19, 7, 19, 7, 18, 7, 18, 6, 17, 5 //190-199
};

/******************************************************/
void setup() {
Serial.begin(9600);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
/******************************************************/
void loop() {
solid(strip.Color(0,0,0));
while (true)
{
/* UnComment the following block if you are going to calculate
LED Positions. Extend and add calls as necessary to match
your LED count.
Serial.println(«GetLocation»);
getLocation(0); //LEDs 0-9
getLocation(1); //LEDs 10-19
getLocation(2); //LEDs 20-29
getLocation(3); //LEDs 30-39
getLocation(4); //LEDs 40-49
delay(3000);
*/

Serial.println(«Solid»);
solid(strip.Color(255,0,0));
delay(3000);
Serial.println(«Solid2»);
two_solid(strip.Color(0,255,0),strip.Color(0,0,255));
delay(3000);
Serial.println(«Dissolve»);
dissolve(strip.Color(255,0,0),strip.Color(0,255,0),5000);
delay(3000);
Serial.println(«Fade»);
fade(strip.Color(0,0,0),strip.Color(255,255,0),5000);
delay(3000);
Serial.println(«HorizWipe»);
horizWipe(false,strip.Color(0,255,255),strip.Color(0,0,255),5000);
delay(3000);
Serial.println(«centerHorizWipe»);
centerHorizWipe(strip.Color(0,255,0),strip.Color(255,0,0),5000);
delay(3000);
Serial.println(«vertWipe»);
vertWipe(false,strip.Color(255,0,0),strip.Color(0,0,255),5000);
delay(3000);
Serial.println(«vertLine»);
vertLine(false,strip.Color(0,255,0),strip.Color(255,0,0),5000);
delay(3000);
Serial.println(«vertWave»);
vertWave(strip.Color(0,255,0),strip.Color(255,0,0),150,5000);
delay(3000);
Serial.println(«vertCenterWave»);
vertCenterWave(strip.Color(255,255,0),strip.Color(0,255,255),150,5000);
delay(3000);
Serial.println(«transition»);
transition(strip.Color(255,0,0),strip.Color(0,255,0));
delay(3000);
Serial.println(«setBlock»);
setBlock(3,strip.Color(255,255,255));
delay(3000);
Serial.println(«Shimmer»);
shimmer(strip.Color(255,0,0),strip.Color(0,255,0),20000,25);
}
}
/*******************************************************/
uint32_t colorSlope(uint32_t c1, uint32_t c2, float percent)
{
uint32_t temp_color, temp_c1_component, temp_c2_component;
temp_color = 0;
temp_c1_component = (c1 & 0x00ff0000) >> 16;
temp_c2_component = (c2 & 0x00ff0000) >> 16;
temp_color = uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
temp_color = temp_color << 8;

temp_c1_component = (c1 & 0x0000ff00) >> 8;
temp_c2_component = (c2 & 0x0000ff00) >> 8;
temp_color += uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
temp_color = temp_color << 8;
temp_c1_component = (c1 & 0x000000ff);
temp_c2_component = (c2 & 0x000000ff);
temp_color += uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
return temp_color;
}
/*******************************************************/
void solid(uint32_t color)
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,color); }
strip.show();
}
/*******************************************************/
void two_solid(uint32_t color_1, uint32_t color_2)
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (i % 2 == 0)
{strip.setPixelColor(i,color_1);}
else
{strip.setPixelColor(i,color_2);}
}
strip.show();
}
/*******************************************************/
void dissolve(uint32_t c_from, uint32_t c_to, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t tick = duration/(strip.numPixels()+50);
bool temp[strip.numPixels()];
int rand;
for(uint16_t j=0; j<strip.numPixels(); j++)
{ temp[j] = false;
strip.setPixelColor(j,c_from);
}
while (elapsed_time < duration)
{
rand = random(strip.numPixels());
if (temp[rand])
{ rand = random(strip.numPixels());
if (temp[rand])
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (!temp[i]) {rand=i; i = 999;} }
}
}
temp[rand] = true;
strip.setPixelColor(rand,c_to);
strip.show();
delay(tick);
elapsed_time += tick+5;
}
for(uint16_t j=0; j<strip.numPixels(); j++)
{ strip.setPixelColor(j,c_to);}
strip.show();
} //dissolve
/*******************************************************/
// Transition all lights from color c_from to color c_to
void fade(uint32_t c_from, uint32_t c_to, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t temp_color;
while (elapsed_time < duration)
{
temp_color = colorSlope(c_from,c_to,float(elapsed_time)/float(duration));

for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,temp_color); }
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_to); }
strip.show();
} //fade
/***********************************************************/
// Transition of colors
void transition(uint32_t c_top, uint32_t c_bottom)
{
uint32_t elapsed_time = 0;
uint32_t temp_color;
for(uint16_t i=0; i<strip.numPixels(); i++)
{ temp_color = colorSlope(c_top,c_bottom,float(Positions[i*2+1])/float(MAX_Y));
strip.setPixelColor(i,temp_color); }
strip.show();
delay(50);
} //Transition of colors
/***********************************************************/
// Horiz Wipe from color c_from to color c_to
void horizWipe(boolean left_to_right, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t X_temp;
while (elapsed_time < duration)
{
//Locate the wipe X
X_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_X));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (left_to_right)
{if (Positions[i*2] < X_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2] > MAX_X — X_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //horizWipe
/***********************************************************/
// Horiz Wipe from color c_from to color c_to
void centerHorizWipe(uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t X_Lower,X_Upper;
while (elapsed_time < duration)
{
//Locate the wipe X
X_Lower = (uint32_t)(float(MAX_X/2) — float(elapsed_time)/float(duration)*float(MAX_X)/2);
X_Upper = (uint32_t)(float(MAX_X/2) + float(elapsed_time)/float(duration)*float(MAX_X)/2);
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (Positions[i*2] >= X_Lower && Positions[i*2] <= X_Upper )
{strip.setPixelColor(i,c_wipe); }
else
{strip.setPixelColor(i,c_orig); }
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //horizWipe
/***********************************************************/
// Vert Wipe from color c_from to color c_to
void vertWipe(boolean bottom_to_top, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t Y_temp;
while (elapsed_time < duration)
{
//Locate the wipe Y
Y_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_Y));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (bottom_to_top)
{if (Positions[i*2+1] < Y_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2+1] > MAX_Y — Y_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //vertWipe
/*******************************************************/
// Vert Line across from color c_from to color c_to
void vertLine(boolean bottom_to_top, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t Y_temp;
while (elapsed_time < duration)
{
//Locate the wipe Y
Y_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_Y));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (bottom_to_top)
{if (Positions[i*2+1] == Y_temp | Positions[i*2+1] == Y_temp+1) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2+1] == MAX_Y — Y_temp | Positions[i*2+1] == MAX_Y — Y_temp+1 ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
} //vertWipe
/*******************************************************/
// Lights up each light in the strip one-by-one, used to
// define pixel positions
void getLocation(uint32_t loc) {
uint32_t signal = loc;
for(uint16_t i=0; i<strip.numPixels();i++) {
strip.setPixelColor(i,strip.Color(0,0,0));
}
while(signal > 0)
{
if (signal >= 10)
{ for(uint16_t i=0; i< 10; i++)
{strip.setPixelColor(loc*10+i,strip.Color(255,0,0));}
signal -= 10;
}
else
{ for(uint16_t i=0; i< 10; i++)
{strip.setPixelColor(loc*10+i,strip.Color(255,255,255));}
signal -= 1;
}
strip.show();
delay(500);
for(uint16_t i=0; i<strip.numPixels();i++) {
strip.setPixelColor(i,strip.Color(0,0,0));
}
strip.show();
delay(500);
} //while on signal
for(uint16_t i=0; i < 10; i++)
{
strip.setPixelColor(loc*10+i,strip.Color(255,255,255));
strip.show();
delay(1000);
strip.setPixelColor(loc*10+i,strip.Color(0,0,0));
}
} //setupWipe()
/********************************************************/
void vertWave(uint32_t c1, uint32_t c2, uint32_t tick, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t ticker = 0;
while (elapsed_time < duration)
{
for(uint16_t i=0; i < LED_COUNT; i++)
{
if ((Positions[i*2+1] / 4) % 4 == ticker % 4)
{strip.setPixelColor(i, c1);}
else
{strip.setPixelColor(i, c2);}
}
strip.show();
delay(tick);
ticker++;
elapsed_time += tick + 5;
}
}
/********************************************************/
void vertCenterWave(uint32_t c1, uint32_t c2, uint32_t tick, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t ticker = 0;
while (elapsed_time < duration)
{
for(uint16_t i=0; i < LED_COUNT; i++)
{
if (((abs(MAX_Y/2 — Positions[i*2+1]) / 3) % 3 == ticker % 3))
{strip.setPixelColor(i, c1);}
else
{strip.setPixelColor(i, c2);}
}
strip.show();
delay(tick);
ticker++;
elapsed_time += tick + 5;
}
}
/********************************************************/
void setBlock(uint32_t block, uint32_t c)
{
uint32_t y_pos;
for(uint16_t i=0; i<strip.numPixels();i++) {
y_pos = Positions[i*2+1];
if (y_pos/(MAX_Y/6) == block)
{ strip.setPixelColor(i,c); }
}
strip.show();
}
/********************************************************/
void shimmer(uint32_t c_base, uint32_t c_shimmer, uint32_t duration, uint32_t amount)
{
uint32_t shimmer_pixel_num[amount];
float shimmer_pixel_percent[amount];
uint32_t elapsed_time = 0;

for(uint16_t i=0; i < amount; i++)
{ shimmer_pixel_num[i] = 0; }

for(uint16_t i=0; i < strip.numPixels(); i++)
{ strip.setPixelColor(i,c_base); }
while (elapsed_time < duration)
{
// See if we should start a shimmer
for(uint16_t i=0; i < amount; i++)
{
if (shimmer_pixel_num[i] == 0 & random(10) > 8)
{ shimmer_pixel_num[i] = random(199) + 1;
shimmer_pixel_percent[i] = 0.0;
}
if (shimmer_pixel_num[i] > 0)
{
if (i% 2 == 0)
{ shimmer_pixel_percent[i] += 0.02; }
else
{ shimmer_pixel_percent[i] += 0.04; }
if (shimmer_pixel_percent[i] >= 2.0)
{
strip.setPixelColor(shimmer_pixel_num[i],c_base);
shimmer_pixel_num[i] = 0;
}
else
{
strip.setPixelColor(shimmer_pixel_num[i],colorSlope(c_shimmer,c_base,abs(1.0 — shimmer_pixel_percent[i])));
}
}
}
strip.show();
delay(50);
elapsed_time += 50 + 5;
}
for(uint16_t i=0; i < strip.numPixels(); i++)
{ strip.setPixelColor(i,c_base); }
strip.show();

}


Но вот тут случилась проблема. Скетч использует библиотеку Adafruit_NeoPixel.h, а она категорически не хочет работать с диодами WS2801.
Похожая библиотека для WS2801 называется Adafruit_WS2801_Library.
Но если поменять в скетче библиотеку и немного поправив скетч (в части указания типа диодов и дополнительного контакта clock), то ничего не произойдет, так как скетч не будет компилироваться.
Опять проблемы, но мы же не будем сдаваться.
На просторах интернета была найдена похожая проблема и даже её решение (в далеком 2015).
Для того что бы скетч написанный для библиотеки Adafruit_NeoPixel.h скомпилировался с библиотекой Adafruit_WS2801_Library, нужно модифицировать эту самую библиотеку. Но для простоты работы вот вам ссылка на уже модифицированную библиотеку yadi.sk/d/M2kXhRLe3Qg4R6
Соответственно после замены файлов в библиотеке. Нужно в скетче добавить

#include <Adafruit_WS2801.h>
#define CLOCK_PIN 13

Adafruit_WS2801 strip = Adafruit_WS2801(LED_COUNT, PIN, CLOCK_PIN);


Вот уже правленый скетч (на 50 диодов)
#include <Adafruit_WS2801.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN 11
#define CLOCK_PIN 13
#define LED_COUNT 50
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_WS2801 strip = Adafruit_WS2801(LED_COUNT, PIN, CLOCK_PIN);

//MAX_X and MAX_Y represent the largest X and Y value from the table of Positions
//This is used to derive where the middle of the tree is in the X and Y direction.
//For example if MAX_X = 20, then LEDs at a position of 10 would be the middle of
//the tree.
#define MAX_X 40
#define MAX_Y 40

//Define the X,Y positions of each pixel. The first array element is the X
//coordinate of the first LED in the string, the second array element is the
//Y coordinate of the first LED. The third array element is the X position of
//the second LED, etc…
byte Positions[LED_COUNT*2] =
{
7, 6, 7, 7, 6, 7, 5, 8, 4, 6, 3, 7, 3, 6, 2, 6, 3, 6, 1, 7, // 0 — 9
1, 8, 2, 9, 2,10, 2,11, 2,12, 4,12, 4,12, 4,13, 4,12, 5,12, //10 — 19
5,10, 6, 9, 7,10, 8,12, 8,11, 8,13, 8,13, 8,15, 7,14, 6,13, //20 — 29
6,15, 5,14, 3,15, 3,14, 3,14, 4,17, 5,16, 4,16, 5,16, 7,17, //30 — 39
7,17, 9,16, 9,16, 10,18, 9,19, 8,20, 8,19, 7,18, 6,20, 6,18, //40 — 49
};

/******************************************************/
void setup() {
Serial.begin(9600);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
/******************************************************/
void loop() {
solid(strip.Color(0,0,0));
while (true)
{
/* UnComment the following block if you are going to calculate
LED Positions. Extend and add calls as necessary to match
your LED count.
Serial.println(«GetLocation»);
getLocation(0); //LEDs 0-9
getLocation(1); //LEDs 10-19
getLocation(2); //LEDs 20-29
getLocation(3); //LEDs 30-39
getLocation(4); //LEDs 40-49
delay(3000);
*/

Serial.println(«Solid»);
solid(strip.Color(255,0,0));
delay(3000);
Serial.println(«Solid2»);
two_solid(strip.Color(0,255,0),strip.Color(0,0,255));
delay(3000);
Serial.println(«Dissolve»);
dissolve(strip.Color(255,0,0),strip.Color(0,255,0),5000);
delay(3000);
Serial.println(«Fade»);
fade(strip.Color(0,0,0),strip.Color(255,255,0),5000);
delay(3000);
Serial.println(«HorizWipe»);
horizWipe(false,strip.Color(0,255,255),strip.Color(0,0,255),5000);
delay(3000);
Serial.println(«centerHorizWipe»);
centerHorizWipe(strip.Color(0,255,0),strip.Color(255,0,0),5000);
delay(3000);
Serial.println(«vertWipe»);
vertWipe(false,strip.Color(255,0,0),strip.Color(0,0,255),5000);
delay(3000);
Serial.println(«vertLine»);
vertLine(false,strip.Color(0,255,0),strip.Color(255,0,0),5000);
delay(3000);
Serial.println(«vertWave»);
vertWave(strip.Color(0,255,0),strip.Color(255,0,0),150,5000);
delay(3000);
Serial.println(«vertCenterWave»);
vertCenterWave(strip.Color(255,255,0),strip.Color(0,255,255),150,5000);
delay(3000);
Serial.println(«transition»);
transition(strip.Color(255,0,0),strip.Color(0,255,0));
delay(3000);
Serial.println(«setBlock»);
setBlock(3,strip.Color(255,255,255));
delay(3000);
Serial.println(«Shimmer»);
shimmer(strip.Color(255,0,0),strip.Color(0,255,0),20000,25);
}
}
/*******************************************************/
uint32_t colorSlope(uint32_t c1, uint32_t c2, float percent)
{
uint32_t temp_color, temp_c1_component, temp_c2_component;
temp_color = 0;
temp_c1_component = (c1 & 0x00ff0000) >> 16;
temp_c2_component = (c2 & 0x00ff0000) >> 16;
temp_color = uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
temp_color = temp_color << 8;

temp_c1_component = (c1 & 0x0000ff00) >> 8;
temp_c2_component = (c2 & 0x0000ff00) >> 8;
temp_color += uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
temp_color = temp_color << 8;
temp_c1_component = (c1 & 0x000000ff);
temp_c2_component = (c2 & 0x000000ff);
temp_color += uint32_t(temp_c1_component + (float(temp_c2_component) — float(temp_c1_component)) * percent);
return temp_color;
}
/*******************************************************/
void solid(uint32_t color)
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,color); }
strip.show();
}
/*******************************************************/
void two_solid(uint32_t color_1, uint32_t color_2)
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (i % 2 == 0)
{strip.setPixelColor(i,color_1);}
else
{strip.setPixelColor(i,color_2);}
}
strip.show();
}
/*******************************************************/
void dissolve(uint32_t c_from, uint32_t c_to, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t tick = duration/(strip.numPixels()+50);
bool temp[strip.numPixels()];
int rand;
for(uint16_t j=0; j<strip.numPixels(); j++)
{ temp[j] = false;
strip.setPixelColor(j,c_from);
}
while (elapsed_time < duration)
{
rand = random(strip.numPixels());
if (temp[rand])
{ rand = random(strip.numPixels());
if (temp[rand])
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (!temp[i]) {rand=i; i = 999;} }
}
}
temp[rand] = true;
strip.setPixelColor(rand,c_to);
strip.show();
delay(tick);
elapsed_time += tick+5;
}
for(uint16_t j=0; j<strip.numPixels(); j++)
{ strip.setPixelColor(j,c_to);}
strip.show();
} //dissolve
/*******************************************************/
// Transition all lights from color c_from to color c_to
void fade(uint32_t c_from, uint32_t c_to, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t temp_color;
while (elapsed_time < duration)
{
temp_color = colorSlope(c_from,c_to,float(elapsed_time)/float(duration));

for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,temp_color); }
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_to); }
strip.show();
} //fade
/***********************************************************/
// Transition of colors
void transition(uint32_t c_top, uint32_t c_bottom)
{
uint32_t elapsed_time = 0;
uint32_t temp_color;
for(uint16_t i=0; i<strip.numPixels(); i++)
{ temp_color = colorSlope(c_top,c_bottom,float(Positions[i*2+1])/float(MAX_Y));
strip.setPixelColor(i,temp_color); }
strip.show();
delay(50);
} //Transition of colors
/***********************************************************/
// Horiz Wipe from color c_from to color c_to
void horizWipe(boolean left_to_right, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t X_temp;
while (elapsed_time < duration)
{
//Locate the wipe X
X_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_X));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (left_to_right)
{if (Positions[i*2] < X_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2] > MAX_X — X_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //horizWipe
/***********************************************************/
// Horiz Wipe from color c_from to color c_to
void centerHorizWipe(uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t X_Lower,X_Upper;
while (elapsed_time < duration)
{
//Locate the wipe X
X_Lower = (uint32_t)(float(MAX_X/2) — float(elapsed_time)/float(duration)*float(MAX_X)/2);
X_Upper = (uint32_t)(float(MAX_X/2) + float(elapsed_time)/float(duration)*float(MAX_X)/2);
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (Positions[i*2] >= X_Lower && Positions[i*2] <= X_Upper )
{strip.setPixelColor(i,c_wipe); }
else
{strip.setPixelColor(i,c_orig); }
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //horizWipe
/***********************************************************/
// Vert Wipe from color c_from to color c_to
void vertWipe(boolean bottom_to_top, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t Y_temp;
while (elapsed_time < duration)
{
//Locate the wipe Y
Y_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_Y));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (bottom_to_top)
{if (Positions[i*2+1] < Y_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2+1] > MAX_Y — Y_temp ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
for(uint16_t i=0; i<strip.numPixels(); i++)
{ strip.setPixelColor(i,c_wipe); }
strip.show();
} //vertWipe
/*******************************************************/
// Vert Line across from color c_from to color c_to
void vertLine(boolean bottom_to_top, uint32_t c_wipe, uint32_t c_orig, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t Y_temp;
while (elapsed_time < duration)
{
//Locate the wipe Y
Y_temp = (uint32_t)(float(elapsed_time)/float(duration)*float(MAX_Y));
for(uint16_t i=0; i<strip.numPixels(); i++)
{ if (bottom_to_top)
{if (Positions[i*2+1] == Y_temp | Positions[i*2+1] == Y_temp+1) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
else
{if (Positions[i*2+1] == MAX_Y — Y_temp | Positions[i*2+1] == MAX_Y — Y_temp+1 ) {strip.setPixelColor(i,c_wipe); } else {strip.setPixelColor(i,c_orig); }}
}
strip.show();
delay(50);
elapsed_time += 55;
}
} //vertWipe
/*******************************************************/
// Lights up each light in the strip one-by-one, used to
// define pixel positions
void getLocation(uint32_t loc) {
uint32_t signal = loc;
for(uint16_t i=0; i<strip.numPixels();i++) {
strip.setPixelColor(i,strip.Color(0,0,0));
}
while(signal > 0)
{
if (signal >= 10)
{ for(uint16_t i=0; i< 10; i++)
{strip.setPixelColor(loc*10+i,strip.Color(255,0,0));}
signal -= 10;
}
else
{ for(uint16_t i=0; i< 10; i++)
{strip.setPixelColor(loc*10+i,strip.Color(255,255,255));}
signal -= 1;
}
strip.show();
delay(500);
for(uint16_t i=0; i<strip.numPixels();i++) {
strip.setPixelColor(i,strip.Color(0,0,0));
}
strip.show();
delay(500);
} //while on signal
for(uint16_t i=0; i < 10; i++)
{
strip.setPixelColor(loc*10+i,strip.Color(255,255,255));
strip.show();
delay(1000);
strip.setPixelColor(loc*10+i,strip.Color(0,0,0));
}
} //setupWipe()
/********************************************************/
void vertWave(uint32_t c1, uint32_t c2, uint32_t tick, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t ticker = 0;
while (elapsed_time < duration)
{
for(uint16_t i=0; i < LED_COUNT; i++)
{
if ((Positions[i*2+1] / 4) % 4 == ticker % 4)
{strip.setPixelColor(i, c1);}
else
{strip.setPixelColor(i, c2);}
}
strip.show();
delay(tick);
ticker++;
elapsed_time += tick + 5;
}
}
/********************************************************/
void vertCenterWave(uint32_t c1, uint32_t c2, uint32_t tick, uint32_t duration)
{
uint32_t elapsed_time = 0;
uint32_t ticker = 0;
while (elapsed_time < duration)
{
for(uint16_t i=0; i < LED_COUNT; i++)
{
if (((abs(MAX_Y/2 — Positions[i*2+1]) / 3) % 3 == ticker % 3))
{strip.setPixelColor(i, c1);}
else
{strip.setPixelColor(i, c2);}
}
strip.show();
delay(tick);
ticker++;
elapsed_time += tick + 5;
}
}
/********************************************************/
void setBlock(uint32_t block, uint32_t c)
{
uint32_t y_pos;
for(uint16_t i=0; i<strip.numPixels();i++) {
y_pos = Positions[i*2+1];
if (y_pos/(MAX_Y/6) == block)
{ strip.setPixelColor(i,c); }
}
strip.show();
}
/********************************************************/
void shimmer(uint32_t c_base, uint32_t c_shimmer, uint32_t duration, uint32_t amount)
{
uint32_t shimmer_pixel_num[amount];
float shimmer_pixel_percent[amount];
uint32_t elapsed_time = 0;

for(uint16_t i=0; i < amount; i++)
{ shimmer_pixel_num[i] = 0; }

for(uint16_t i=0; i < strip.numPixels(); i++)
{ strip.setPixelColor(i,c_base); }
while (elapsed_time < duration)
{
// See if we should start a shimmer
for(uint16_t i=0; i < amount; i++)
{
if (shimmer_pixel_num[i] == 0 & random(10) > 8)
{ shimmer_pixel_num[i] = random(199) + 1;
shimmer_pixel_percent[i] = 0.0;
}
if (shimmer_pixel_num[i] > 0)
{
if (i% 2 == 0)
{ shimmer_pixel_percent[i] += 0.02; }
else
{ shimmer_pixel_percent[i] += 0.04; }
if (shimmer_pixel_percent[i] >= 2.0)
{
strip.setPixelColor(shimmer_pixel_num[i],c_base);
shimmer_pixel_num[i] = 0;
}
else
{
strip.setPixelColor(shimmer_pixel_num[i],colorSlope(c_shimmer,c_base,abs(1.0 — shimmer_pixel_percent[i])));
}
}
}
strip.show();
delay(50);
elapsed_time += 50 + 5;
}
for(uint16_t i=0; i < strip.numPixels(); i++)
{ strip.setPixelColor(i,c_base); }
strip.show();

}



Такой фокус работает не всегда. Бывает и так, что в коде используются данные которых просто нет в библиотеке Adafruit_WS2801_Library. Тут уже нужно править код.

P.S. Такой же метод я попробовал для цветомузыки mySKU.pro/blog/diy/58060.html
Правда пришлось удалить одну строчку кода, но и без нее все работает хорошо. Теперь можно не покупать новую ленту, а использовать старую WS2801 для гирлянды или цветомузыки.



Ну и какое сообщение без котиков

Добавить в избранное +14 +41
+
avatar
  • 4NeoN4
  • 16 декабря 2017, 20:18
0
где-то должен был быть «cut» :)
+
avatar
+1
Забыл. Поправил.
+
avatar
  • chaloc
  • 16 декабря 2017, 20:19
0
черновик?
+
avatar
+1
нет.
Наверное просто коряво оформлено.
+
avatar
+5
Где красивая гирлянда?
+
avatar
-1
Где красивая гирлянда?
void loop() {
if (abs(hueCurrent — hueDestination) < hueStep) {
hueDestination = random(255);
hueStep = ((hueCurrent < hueDestination) && (hueStep < 0))? hueStep: -hueStep;
}
hueCurrent += hueStep;
pushLed(hueCurrent);
FastLED.show();
delay(UPDATE_DELAY);
}
+
avatar
-3
Будет после того как ее соберут.
+
avatar
  • ABATAPA
  • 16 декабря 2017, 22:00
+3
Вот:
github.com/evilgeniuslabs/tree-v2

А это так…
+
avatar
0
Проблема в том, что нет кода гирлянды с эффектами для голой ардуины. Все авторы начинают прикручивать и СинийЗуб, и ИК и еще какие то извращения. Сам сижу и подыскиваю код для трехметрового куска.
Неужели кто-то реально сидит возле елки и переключает режимы?
+
avatar
-1
В ваших обзорах, видимо.
+
avatar
  • nochkin
  • 17 декабря 2017, 04:28
0
Есть ведь такие обзоры тут на сайте. Вроде нет сложности сравнить и улучшить.
+
avatar
  • asdfgh
  • 16 декабря 2017, 21:15
+3
Схема электрическая принципиальная будет?
+
avatar
0
Смысл темы был в том, что бы рассказать как можно использовать скетчи с библиотекой Adafruit_NeoPixel.h на диодах WS2801.
Тут вся схема. _5 Вольт, земля и подключить диоды к 11 и 13 контактам ардуины. На сайте таких поделок достаточно.
+
avatar
  • sir0ta
  • 16 декабря 2017, 21:59
+1
Смысл темы был в том, что бы рассказать как можно использовать скетчи с библиотекой Adafruit_NeoPixel.h на диодах WS2801
А что муська вдруг превратилась в научно-познавательный сайт? Без линков на товары и прочего… такое себе.
+
avatar
+4
Да, представь себе, специальный блог даже для этого создали DIY, даже без линков на товары.
+
avatar
  • vdm
  • 18 декабря 2017, 11:34
0
Не забыть конденсатор на питание ленты и резистор 470 кОм на сигнальный провод.
+
avatar
  • Kostja
  • 16 декабря 2017, 21:16
0
А где видео работы гирлянды?
+
avatar
0
Добавил видео работы оригинального скетча. Так как у меня всего 50 диодов. Работает не так красиво как задумывал автор.
+
avatar
  • rocket1
  • 17 декабря 2017, 19:17
0
А сколько диодов на видео?
+
avatar
  • Kartus
  • 16 декабря 2017, 21:22
+6
А где же ссылка на гирлянду или ардуину?
+
avatar
0
0_0 ТАк я же ничего не обозреваю. Какие тут могут быть ссылки на товары.
А так все необходимое легко на али находится.
P.S. Тема носит информационный характер.
+
avatar
  • Kartus
  • 16 декабря 2017, 21:29
+1
P.S. Тема носит информационный характер.
Ну типа да. Сайт носит провокационный характер — хочется уже купить чего нибудь проверенного)))
+
avatar
+1
Типа тут даже отдельный блог создали чисто для DIY. «А мужики-то и не знают». Вот каждый день комментировать и не быть в курсе — это как?
+
avatar
  • Kartus
  • 16 декабря 2017, 22:47
-3
это как
Практически никак))) То что я в курсе, не означает что мне это нравится. Вот как то так)))
+
avatar
+4
Из имеющегося дома была диодная «лента» WS2801 на 50 диодов (на фото).
На каком, млин?! Нет никакого фото!
+
avatar
  • Loatan
  • 16 декабря 2017, 21:42
0
Мне вот эта тема понравилась github.com/scottlawsonbc/audio-reactive-led-strip, сейчас собрал для wemos d1 mini, работает прикольно, но ещё множество работ по доработке авторского кода предстоит.
+
avatar
  • ABATAPA
  • 16 декабря 2017, 22:03
0
Посмотрите на это.

P.S.: Синдром парных случаев. Или новогодний синдром? Как раз вокруг меня ленты, модули, ESP8266, Arduino…
+
avatar
  • Besik
  • 16 декабря 2017, 22:33
0
Посмотрите на это.
По сравнению с китайскими пстрыкалками нереально красивая штука. Хачу!
Но мозг говорит, что руки под дилдо заточены, чтобы хотеть.
+
avatar
  • kalobyte
  • 17 декабря 2017, 00:10
+1
+
avatar
  • Cucumber
  • 16 декабря 2017, 22:19
+13
Дмитрий, тебе серьезно понравились эффекты в приведенном видео?
Вот уже второй год у меня будет трудится на елке библиотека эффектов WS2812 FX.
Но вот это видео покорило и я жду от автора скетча для арудино
+
avatar
  • nochkin
  • 16 декабря 2017, 22:29
0
Можно по видео написать код если так сильно покорило. Тогда не надо ждать.
+
avatar
  • ABATAPA
  • 16 декабря 2017, 22:36
0
А что ждать-то?! Даже в названии написано, что это для контроллера T-1000S. Автор обещал переписать под Arduino?
+
avatar
  • Cucumber
  • 16 декабря 2017, 22:57
0
Да, обещал
+
avatar
  • nochkin
  • 16 декабря 2017, 23:05
0
Какой именно их эффектов? Это же сделать несложно.
+
avatar
  • Bird1833
  • 16 декабря 2017, 23:17
+3
Если получите, скиньте пожалуйста ссылочку в личку
+
avatar
  • Olegkad
  • 17 декабря 2017, 11:20
0
То же присоединюсь. Скиньте пожалуйста ссылочку в личку если будет.
+
avatar
  • Sindar
  • 17 декабря 2017, 13:13
0
Встану в очередь :)
+
avatar
  • Fover
  • 17 декабря 2017, 16:57
0
Мне тоже в личку, пожалуйста)
+
avatar
0
Можете не ждать. Кина не будет. За год он не сделал, значит уже не сделает. А что до Т-1000, так там по сути видеофайл проигрывается покадрово. Маловероятно, что эти эффекты можно ужать в ардуину.
+
avatar
0
А в ардуину с картридером?
+
avatar
  • MaxGerb
  • 16 декабря 2017, 23:49
0
К сожалению, мои руки на такое не способны. Но был бы такой готовый продукт — купил бы.
По мне так, отличная визуализация.
+
avatar
  • vdm
  • 18 декабря 2017, 11:39
0
Так он же давал исходники:
stephenculley.blogspot.ru/2016/10/christmas-tree-led-pixel-ws2811-t-1000s.html

Только беда в том, что исходники для T1000S Controller.

Для ардуины обещает…
+
avatar
  • MAXXL
  • 16 декабря 2017, 22:45
0
А для ESP32 есть что-нибудь? А то ничего больше под руками нет, те примеры что нашел — не компилятся или библиотеки не работают с ESP32
+
avatar
  • nochkin
  • 16 декабря 2017, 23:07
0
github.com/MartyMacGyver/ESP32-digital-RGB-LED-drivers
Там есть драйвер и демка. Если демка не нравится, то этот драйвер можно использовать для своих эффектов.
+
avatar
  • MAXXL
  • 17 декабря 2017, 00:48
0
Пробовал его уже. Загрузил демку в плату — лента ничего не выдала. Что-то упускаю по -видимому
+
avatar
  • nochkin
  • 17 декабря 2017, 04:23
0
Может, тип светодиодов не так выставлен? Там время задержки различается немного.
github.com/MartyMacGyver/ESP32-Digital-RGB-LED-Drivers/blob/master/arduino-esp32/demo1/esp32_digital_led_lib.h#L100
+
avatar
  • MAXXL
  • 17 декабря 2017, 11:48
0
а как узнать тип светодиода? покупал уже давно, не помню что там было в лоте.
+
avatar
  • nochkin
  • 17 декабря 2017, 23:42
0
Можно по косвенным признакам. Например, корпуса WS2812 с 6 выводами, а WS2812B — 4. И т.п.
Но можно просто перепробовать все по очереди (если нет белого канала, то RGBW можно пропустить, конечно).
+
avatar
+3
ws2812fx. дико просто и удобно. никакой толком настройки, все +- работает из коробки.
+
avatar
  • kalobyte
  • 17 декабря 2017, 00:11
0
себе запилю


эффекты гиморно рисовать
+
avatar
  • Com4com
  • 17 декабря 2017, 00:55
0
Я купил случайно 10-ти метровую многоцветную гирлянду. Всем хороша, но не нравятся режимы работы. Возникла мысль — а может можно где-то купить готовую гирлянду такую, чтобы можно было заменить контроллер на ардуино и залить хорошие скетчи? Может, кот-то подскажет.
+
avatar
  • nochkin
  • 17 декабря 2017, 01:20
0
Если можно из этой 10-метровой сделать, то почему бы не посмотреть на это? Если есть какой-то МК, то возможно не надо ничего покупать даже.
+
avatar
  • dansar
  • 17 декабря 2017, 20:17
0
Можно посмотреть вот такой вариант. Правда, у автора странная любовь к «тинькам» (attiny2313), а исходный код в Algorithm Builder'е, так что бы портировать его на какую-нибудь обычную мегу328, придется поработать головой.
+
avatar
  • slon1977
  • 17 декабря 2017, 03:50
0
К сожалению не видно на видео: на ёлке накручена простая диодная лента или всё-таки она имеет вид гирлянды?
+
avatar
  • nochkin
  • 17 декабря 2017, 04:24
+1
Автор взял чужое видео, там немного другой проект. Не знаю почему автор поленился своё видео запилить.
+
avatar
  • vanya4na
  • 17 декабря 2017, 15:28
+4
А для кого этот обзор? Людям, мало-мальски умеющим программировать и разбирающимся в ардуино, будет не интересно, т.к. и так всё понятно. Людям, ничего в этом не понимающим, будет ничего не понятно. Обзора нет, фоток нет, конечной реализации нет…
+
avatar
  • DSUHCB
  • 19 декабря 2017, 02:34
0
Соглашусь, хотелось бы видеть более развернутую инструкцию для новичков.