Плавное включение светодиодов ленты WS2812 в светомузыке

AkkSergey
Offline
Зарегистрирован: 15.10.2017

Есть светомузыка с транзисторным фильтром, сигнал с которого идёт на аналоговые порты ардуины (есть частота в музыке, от её мощности открывается на определённый % транзистор, пропуская на аналоговый порт от 0 до 5 вольт). Ардуина, в зависимости от того, какой сигнал приходит с транзисторного фильтра управляет лентой WS2812. Управление лентой реализовал с помощью Adafruit_NeoPixel.h. Суть кода программы:

#include <Adafruit_NeoPixel.h>
#define PINLeft 10 //номер порта к которому подключена лента
#define count_ledLeft 30 //количество светодиодов в ленте

Adafruit_NeoPixel pixelsLeft = Adafruit_NeoPixel(count_ledLeft, PINLeft, NEO_GRB + NEO_KHZ800);

float nizkiePinLeft = A7; // указываем пины входов с транзисторного фильтра светомузыки и да, можно было в define записать, не суть
float sredniePinLeft = A5;
float visokiePinLeft = A3;

float redanalogL; //переменные для хранения считанного значения с аналогового входа
float greenanalogL;
float blueanalogL;

int redLeft; //переменные для управления цветами ленты, можно byte поставить, тоже не суть
int greenLeft;
int blueLeft;

void setup()
{
redLeft = 0; //задаём изначальное значение цвета стоек
greenLeft = 0;
blueLeft = 0;

pinMode(nizkiePinLeft, INPUT); //указываем входные пины сигналов с фильтра
pinMode(sredniePinLeft, INPUT);
pinMode(visokiePinLeft, INPUT);

brightness = 120; //устанавливаем яркость свечения ленты, 255 максимум
  
pixelsLeft.begin();
pixelsLeft.setBrightness(brightness);
pixelsLeft.show();
}
​
void loop()
{ 
//генерируется значение для красного цвета:

redanalogL = analogRead(nizkiePinLeft); //записываем значения сигнала с аналогового входа левой части фильтра
redanalogL = map(redanalogL, 0, 1023, 0, 255); //переводим значение 0-1023 в значение 0-255 для прямого управления лентой

if(redanalogL >= 94 && redanalogL <= 255) //т.к. при диапазоне 0-94 идут ложные срабатывания на частоты с фильтра, отсекаем их
        {
        redLeft = redanalogL; //задаётся значение для цвета, которое потом пошлётся на ленту
        }

//генерируется значение для зелёного цвета:

greenanalogL = analogRead(sredniePinLeft); 
greenanalogL = map(greenanalogL, 0, 1023, 0, 255); 

if(greenanalogL >= 94 && greenanalogL <= 255) 
        { 
        greenLeft = greenanalogL;
        }

//генерируется значение для синего цвета цвета:

blueanalogL = analogRead(visokiePinLeft); 
blueanalogL = map(blueanalogL, 0, 1023, 0, 255); 

if(blueanalogL >= 94 && blueanalogL <= 255) 
        { 
        blueLeft = blueanalogL;
        }

//посылаем сгенерированные цвета на ленту:

for(l=0; l < pixelsLeft.numPixels(); l++) //цикл, который перебирает все пиксели стойки, посылая на них цвета
        { 
        pixelsLeft.setPixelColor(l, pixelsLeft.Color(redLeft,greenLeft,blueLeft)); //сюда вставляются сгенерированные алгоритмами выше коды цветов 
        }
pixelsLeft.show(); //отображаем полученные цвета на стойке 
}

А теперь проблема: когда светомузыка была просто на транзисторном фильтре с "тупой" RGB лентой, достаточно было повесить на светодиоды конденстаторы емкостью эдак 220-470 мКф и всё включалось/выключалось наиплавнейше, тут же лента управляется сигналом с ардуины и кондёры не прокатят.

Пробовал:

1. Ставить delay(); в конце void loop(), но это вообще не решает проблему, лента всё-равно мельтишит при небольшой задержке или начинает залипать при большой.

2. Использовать циклы for, типа если условие верное, тогда цвет=цвет+1, если нет, тогда цвет=цвет-1. С циклами вообще не работает ничего, цвета даже не загораются.

3. Пробовал выводить уравнение, чтобы при значении с аналогового входа 94 (срабатывания условия верно) значение цвета было 0, а при 255, собственно, 255, ибо без этого начальное значение цвета было не ноль, а 94, из-за этого пиксель включался "рывком", но нет, лента всё-равно мельтишит.

И вот вопрос: как реализовать плавное включение/выключение пикселей ленты, как, например, это сделано в китайских дешманских контроллерах с пультиками и микрофоном типа такого: https://pl-1.org/public/productdetail.aspx?id=10803 ?

Уже кучу всего прошерстил, не могу найти ничего подходящего. По сути, проблема в том, что слишком быстро меняются значения на аналоговом порту и нужно как то замедлить этот процесс, но так же не потерять при этом нормальную сработку на частоты... Прошу помощи, в общем, как говорится: "одна голова хорошо..." =).

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

AkkSergey, цикл for здесь, разумеется, не подходит, все надо делать в цикле loop().

попытайтесь 

greenLeft = greenanalogL;

заменить на что-то вроде:

if (greenLeft < greenanalogL) greenLeft++;
else if (greenLeft > greenanalogL) greenLeft--;

 

AkkSergey
Offline
Зарегистрирован: 15.10.2017

Нечто похожее тоже пробовал, но решил ещё раз повторить. Результат не сильно порадовал, прибавки на 1 (++) не достаточно, слишком медленно идёт прирост/убавка яркости, в результате лента просто тупо принимает какой то оттенок из цветов, который немного туда-сюда переплывает. Попробовал увеличить прибавку, дошёл до greenLeft += 40, переплывание оттенка стало только более дёрганным...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Вы перечислили симптомы характерные для низкой (недостаточной) частоты работы loop().

Измерьте, сколько времени у Вас занимает один проход цикла и, желательно, измерить время работы отдельных его частей.

AkkSergey
Offline
Зарегистрирован: 15.10.2017

К слову, при включении буквально секунду цвета отображаются нормально, потом смешиваются в кашу полную, когда снимаю питание, опять же, на секунду цвета принимают нормальный вид и лента гаснет. В программе вроде лагать так ничего не должно, боюсь, не было бы косяков с питанием где, потому что лента начинает нормально работать при отключении транзисторного фильтра похоже, возможно есть особенности работы с аналоговым входом ардуины?

Схему установки прилагаю: 

Большая версия: http://i2.imageban.ru/out/2017/10/15/a8b53473c61ce9ee2d370c940d650e5b.jpg

Onkel
Offline
Зарегистрирован: 22.02.2016
AkkSergey
Offline
Зарегистрирован: 15.10.2017

Всем спасибо за помощь, решение проблемы больше не требуется! Решил изменить схемотехнику на другую, так что всем отбой.