Плавное включение светодиодов ленты 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
Всем спасибо за помощь, решение проблемы больше не требуется! Решил изменить схемотехнику на другую, так что всем отбой.