Плавное включение светодиодов ленты WS2812 в светомузыке
- Войдите на сайт для отправки комментариев
Есть светомузыка с транзисторным фильтром, сигнал с которого идёт на аналоговые порты ардуины (есть частота в музыке, от её мощности открывается на определённый % транзистор, пропуская на аналоговый порт от 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 ?
Уже кучу всего прошерстил, не могу найти ничего подходящего. По сути, проблема в том, что слишком быстро меняются значения на аналоговом порту и нужно как то замедлить этот процесс, но так же не потерять при этом нормальную сработку на частоты... Прошу помощи, в общем, как говорится: "одна голова хорошо..." =).
AkkSergey, цикл for здесь, разумеется, не подходит, все надо делать в цикле loop().
попытайтесь
заменить на что-то вроде:
Нечто похожее тоже пробовал, но решил ещё раз повторить. Результат не сильно порадовал, прибавки на 1 (++) не достаточно, слишком медленно идёт прирост/убавка яркости, в результате лента просто тупо принимает какой то оттенок из цветов, который немного туда-сюда переплывает. Попробовал увеличить прибавку, дошёл до greenLeft += 40, переплывание оттенка стало только более дёрганным...
Вы перечислили симптомы характерные для низкой (недостаточной) частоты работы loop().
Измерьте, сколько времени у Вас занимает один проход цикла и, желательно, измерить время работы отдельных его частей.
К слову, при включении буквально секунду цвета отображаются нормально, потом смешиваются в кашу полную, когда снимаю питание, опять же, на секунду цвета принимают нормальный вид и лента гаснет. В программе вроде лагать так ничего не должно, боюсь, не было бы косяков с питанием где, потому что лента начинает нормально работать при отключении транзисторного фильтра похоже, возможно есть особенности работы с аналоговым входом ардуины?
Схему установки прилагаю:
https://www.youtube.com/watch?v=o4UVhx9f-Wc
Всем спасибо за помощь, решение проблемы больше не требуется! Решил изменить схемотехнику на другую, так что всем отбой.