Дабы не томить, покажу сразу что в итоге получилось:
фотоПоказать
По проще и дешевле для дома: http://s.click.aliexpress.com/e/f6y7EmM
Пару лет назад пришлось справлять этот волшебный праздник с обычной китайской гирляндой из лампочек накаливания, которые от старости выцвели и светили стрёмным жёлтым цветом. И была найдена зависимость: какая гирлянда - такой и новый год.
Год назад (перед 2016 нг) заказал с китаю гирлянду в 100 диодов с чипами ws2811, Ехала долго, думал не успеет, но мне повезло - гирлянда приехала до нового года. По быстрому отрыл старый БП от компа ватт на 250, выдрал лишние провода и заменил вспухшие кондёры, почистил естественно и перепаял 80мм вентилятор с 12в на 5в чтоб меньше жужжал, предварительно смазав его литолом. Впихал туда ардуину, кнопочки, крутилочки... Мигает! ))
Ёлка у меня искуственная но высокая и пышная, прикинул по вышине - 25 диодов получилось в самый раз, поэтому гирлянда была распилена на 4 куска по 25 диодов. (позже я добавил ещё 4 таких куска, но об этом потом)
Всверлил в корпус БП 3 кнопки и три крутилки, одна крутилка регулирует яркость гирлянды, вторая скорость еффектов, третья будет менять скорость смены цвета в радуге, ну или ещё чего на неё повешать - не знаю.
Кнопка из 3х задействована одна. Она переключает эффекты и записывает в ЕЕПРОМ, для того, чтобы при включении показывался ранее выбраный эффект. На две другие пока думаю чего навешать. можно например ночной режим - яркость на минимум, скорость на минимум, эффект радуга. Или можно определённые, самые любимые эффекты на них повешать.
Из эффектов пока 6 штук из библтотеки FastLED и ещё несколько самопальных

Зачем запихал в такую большую коробку? Потому что старых БП от компа у меня много

А теперь как я туда чего запихивал, высверливал и протачивал...
Нашёл свободное место, подальше от высокочастотных и силовых узлов (разъём 220 не в счет

К тому же будет доступ к USB разъёму.
Для органов управления так же найдено место, подальше от всего опасного...
Сверлить тонкую жестянку, так чтобы было аккуратно - не очень получается (позже приноровился - подставляя разделочную доску)
Паяем выходы, те что пойдут на гирлянды. Для безопасности делаем это через резистор. Советуют 470 ом, но у меня были в наличии на 330, сойдёт...
Распаял кнопки и переменники. Кнопки замыкают на массу и используется внутренняя подтяжка к плюсу, поэтому лишних резисторов не ставим. Все переменники (лучше на 10к, но не особо важно, можно даже на 1к воткнуть) подключены одним концом на массу, другие концы все в кучу и через 200 ом резистор (ну вдруг там чего замкнёт) на +5в, паралельно переменникам напаял кондёр (100мкф и 0.1мкф) , чтоб сильно цифры не скакали. Ползунки переменников идут в ардуино на аналоговые входы.
Подаём питание... И поскольку очень много говорят про всякие там помехи и фильтры - поставил пару кондёров (100мкф и 0.1мкф) Не потому что я чегото там просчитал, а просто у меня есть кондёры только 100мкф и 0.1мкф

Всё паялось обычным 40вт паялом, без всякого заземления со вставленой в панель ардуиной и как ни странно, всё работает

Был написан скетч по быстрому на базе библиотеки FastLED и весело отпразднован новый год. После чего, гирлянда вместе с ёлкой были упрятаны в коробку и отправлены в дальний угол ожидать следующего нового года.
И вот "на горизонте" обозначился очередной 2017 новый год. заказана и уже доставлена ещё одна гирлянда из 100 диодов с чипами WS2811. Досталась прошлогодняя гирлянда и работы продолжились...
Было решено заменить самопальные разъёмы на нормальные типа "Джек". Был так же докуплен провод и термоусадка.
Выбрано место, куда бы эти 8 джеков влезли - единственным местом оказалось пространство над высоковольтной частью блока питания. Боимся, но делаем...
Готово! Теперь надо паять к ним провода...
В прошлом году гирлянд было 4, распаял на 6, но в задумке было 8, поэтому допаиваем недостающие 2 провода с резисторами.
И припаиваем это всё к джекам, не забывая надевать термоусадки (я на плюс забыл одеть)...
Вычитал также что надо конденсатор ближе к гирляндам поставить, под руку попался 1000мкф х 25в. Паяю его прямо к джекам.
Чтоб провода не лезли к вентелятору и высоковольтной части БП - фиксирую их бумажным скотчем и для верности - клеющим пистолетом.
Собираем корпус
Припаивал провода метра по полтора от джека до куска гирлянды, закрывая все стыки термоусадкой
Чтоб было за что вешать гирлянду на ёлку (или ещё куда нибудь) из больших канцелярских скрепок сделал крючки, а из оставшихся проводов-хвостиков сделал петельки, куда и вставил скрепки
Подошло время для скетча... Первая версия была переработана, инициализация лент была запихана в массив, вызов эффектов был переделан под использование этого массива, что дало возможность делать горизонтальные эффекты. Сделал 1-2 эффекта простых (между лентами) и после нескольких дней обдумывания изобретён эффект "снегопад". Если бы вместо гирлянд были ленты с высокой плотностью диодов, то эффект можно было назвать "капающие сосульки", а на гирлянде только "снегопад"


Библиотеку FastLED качаем здесь
Ну и сам скетч (делал всё в arduino IDE):
открой меня!Показать
Код: Выделить всё
#include <EEPROM.h>
#include "FastLED.h"
const int bright_rezistor_pin = A7; // Резистор регулировки яркости (10к)
const int rainbowspeed_rezistor_pin = A6; // Резистор регулировки скорости смены цвета в радуге (10к)
const int fps_rezistor_pin = A5; // Общая скорость эффектов (кадров в секунду) (10к)
const int btn_changeeffect_pin = 2; // Кнопка смены эффектов
const int btn_2_pin = 3; // Резерв
const int btn_3_pin = 4; // Резерв
int bright_rezistor = 400; // Стартовое значение резистора яркости
int fps_rezistor = 400; // Стартовое значение резистора скорости еффектов (fps)
int btn_changeeffect_flag = 0;
int btn_changeeffect_state = HIGH;
int last_btn_changeeffect_state = HIGH;
long last_btn_changeeffect_debounce_time = 0;
const int debounceDelay = 80;
byte current_effect = 0;
const int eeprom_addr = 4;
int pos1 = 0;
int color_x = 0;
FASTLED_USING_NAMESPACE
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define DATA_PIN_1 5 // Определяем пин для ленты #1
#define DATA_PIN_2 6 // Определяем пин для ленты #2
#define DATA_PIN_3 7 // Определяем пин для ленты #3
#define DATA_PIN_4 8 // Определяем пин для ленты #4
#define DATA_PIN_5 9 // Определяем пин для ленты #5
#define DATA_PIN_6 10 // Определяем пин для ленты #6
#define DATA_PIN_7 11 // Определяем пин для ленты #7
#define DATA_PIN_8 12 // Определяем пин для ленты #8
#define LED_TYPE WS2811
#define COLOR_ORDER RGB
#define NUM_LEDS 25
#define NUM_STRIPS 8
CRGB leds[NUM_STRIPS][NUM_LEDS];
#define BRIGHTNESS 150 // Стартовое значение яркости
#define FRAMES_PER_SECOND 1 // Стартовое значение скорости эффектов
void setup() {
Serial.begin(9600); // Для отладки
pinMode(bright_rezistor_pin, INPUT);
pinMode(rainbowspeed_rezistor_pin, INPUT);
pinMode(fps_rezistor_pin, INPUT);
pinMode(btn_changeeffect_pin, INPUT);
digitalWrite(btn_changeeffect_pin, HIGH); // Используем встроенную верхнюю подтяжку
pinMode(btn_2_pin, INPUT);
digitalWrite(btn_2_pin, HIGH); // Используем встроенную верхнюю подтяжку
pinMode(btn_3_pin, INPUT);
digitalWrite(btn_3_pin, HIGH); // Используем встроенную верхнюю подтяжку
delay(1000); // 3 second delay for recovery
// tell FastLED about the LED strip configuration
FastLED.addLeds<LED_TYPE,DATA_PIN_1,COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_2,COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_3,COLOR_ORDER>(leds[2], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_4,COLOR_ORDER>(leds[3], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_5,COLOR_ORDER>(leds[4], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_6,COLOR_ORDER>(leds[5], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_7,COLOR_ORDER>(leds[6], NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_8,COLOR_ORDER>(leds[7], NUM_LEDS).setCorrection(TypicalLEDStrip);
// set master brightness control
FastLED.setBrightness(BRIGHTNESS);
current_effect = EEPROM.read(eeprom_addr);
}
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm, horizont_2, snow_2 };
uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
void loop()
{
bright_rezistor = map(analogRead(bright_rezistor_pin), 0, 985 ,10 ,255);
fps_rezistor = map(analogRead(fps_rezistor_pin), 0, 985 ,5 ,255);
// Городим жуткую защиту от дребезга для кнопки переключения эффектов...
int btn_changeeffect_reading = digitalRead(btn_changeeffect_pin);
if(btn_changeeffect_reading != last_btn_changeeffect_state){
last_btn_changeeffect_debounce_time = millis();
}
if((millis() - last_btn_changeeffect_debounce_time) > debounceDelay) {
if(btn_changeeffect_reading != btn_changeeffect_state) {
btn_changeeffect_state = btn_changeeffect_reading;
if(btn_changeeffect_state == LOW && btn_changeeffect_flag == 0){ // Если кнопка нажата...
current_effect ++; // Увиличиваем номер эффекта
EEPROM.write(eeprom_addr, current_effect); // Записываем номер эффекта в ЭСППЗУ
btn_changeeffect_flag = 1;
if(current_effect > 9){ // Если номер эффекта превышает существующее
current_effect = 0; // то отсчет начинается с нуля
}
}
if(btn_changeeffect_state == HIGH && btn_changeeffect_flag == 1){
btn_changeeffect_flag = 0;
}
}
}
last_btn_changeeffect_state = btn_changeeffect_reading;
FastLED.setBrightness(bright_rezistor);
//Serial.println(current_effect);
//delay(1);
if(current_effect == 0){
EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
gPatterns[gCurrentPatternNumber]();
}
if(current_effect == 1){
rainbow();
}
if(current_effect == 2){
rainbowWithGlitter();
}
if(current_effect == 3){
confetti();
}
if(current_effect == 4){
sinelon();
}
if(current_effect == 5){
juggle();
}
if(current_effect == 6){
bpm();
}
if(current_effect == 7){
horizont_2();
}
if(current_effect == 8){
snow_1();
}
if(current_effect == 9){
snow_2();
}
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/fps_rezistor);
// do some periodic updates
EVERY_N_MILLISECONDS( 1 ) { gHue++; } // slowly cycle the "base color" through the rainbow
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
// add one to the current pattern number, and wrap around at the end
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void rainbow(){
// FastLED's built-in rainbow generator
for(int i=0; i < NUM_STRIPS; i++){
fill_rainbow( leds[i], NUM_LEDS, gHue, 7);
}
}
void rainbowWithGlitter(){
// built-in FastLED rainbow, plus some random sparkly glitter
rainbow();
addGlitter(80);
}
void addGlitter( fract8 chanceOfGlitter){
if( random8() < chanceOfGlitter) {
for(int i=0; i < NUM_STRIPS; i++){
leds[i][ random16(NUM_LEDS) ] += CRGB::White;
}
}
}
void confetti(){
// random colored speckles that blink in and fade smoothly
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 10);
}
int pos = random16(NUM_LEDS);
for(int i=0; i < NUM_STRIPS; i++){
leds[i][pos] += CHSV( gHue + random8(64), 200, 255);
}
}
void sinelon(){
// a colored dot sweeping back and forth, with fading trails
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 20);
}
int pos = beatsin16(13,0,NUM_LEDS);
for(int i=0; i < NUM_STRIPS; i++){
leds[i][pos] += CHSV( gHue, 255, 192);
}
}
void bpm(){
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int ii = 0; ii < NUM_LEDS; ii++) { //9948
for(int i=0; i < NUM_STRIPS; i++){
leds[i][ii] = ColorFromPalette(palette, gHue+(ii*2), beat-gHue+(ii*10));
}
}
}
void juggle(){
// eight colored dots, weaving in and out of sync with each other
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 20);
}
byte dothue = 0;
for( int ii = 0; ii < 8; ii++) {
for(int i=0; i < NUM_STRIPS; i++){
leds[i][beatsin16(ii+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
}
dothue += 32;
}
}
void horizont_2(){
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 100);
}
if(pos1 > NUM_STRIPS-1) {pos1 = 0; color_x = color_x+1;}
if(color_x > 3) color_x = 0;
CRGB color[] = {CRGB(255, 0, 0), CRGB(0, 255, 0), CRGB(0, 0, 255), CRGB(255, 255, 255),
CRGB(255, 0, 255), CRGB(0, 255, 255), CRGB(255, 255, 0), CRGB(255, 150, 150)};
for (int i=0; i <= NUM_LEDS-1; i++){
leds[pos1][i] = color[color_x];
}
pos1 = pos1+1;
}
void horizont_3(){
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 100);
}
if(pos1 > NUM_STRIPS-1) pos1 = 0;
for (int i=0; i <= NUM_LEDS-1; i++){
leds[pos1][i] = CHSV( gHue, 255, 192);
}
pos1 = pos1+1;
}
void snow_1(){
if(pos1 > NUM_LEDS*2-1) pos1 = 0;
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 50);
}
for(int i=0; i < NUM_STRIPS; i++){
leds[i][NUM_LEDS-pos1/2-1] = CRGB(255, 255, 255);
}
pos1 = pos1+1;
}
struct snow_line{ // объявляем структуру для ленты снега
byte pos;
long end_time;
int start_delay;
} type;
snow_line snow_2_vars[NUM_STRIPS];
void snow_2(){
for(int i=0; i < NUM_STRIPS; i++){
fadeToBlackBy( leds[i], NUM_LEDS, 40);
}
for(byte i=0; i < NUM_STRIPS; i++){
if(snow_2_vars[i].pos > NUM_LEDS*2-1){ // Если дошли до конца ленты то...
snow_2_vars[i].pos = 0; // Сбрасываем позицию на ноль
snow_2_vars[i].end_time = millis(); // Записываем время окончания эффекта
}
if(snow_2_vars[i].pos == 0){ // Если задана нулевая позиция - значит начало, то...
snow_2_vars[i].start_delay = random(10, 3000); // Генерируем врменную задержку запуска эффекта (до 3х секунд)
}
if(millis() > snow_2_vars[i].end_time+snow_2_vars[i].start_delay){ // Если вышла задержка перед запуском эффекта, запускаем...
leds[i][NUM_LEDS-snow_2_vars[i].pos/2-1] = CRGB(255, 255, 200);
snow_2_vars[i].pos++;
}
}
}
Празднуйте новый год весело!
