ARDUINO Цветомузыка на MSGEQ7 и на фильтрах

Цветомузыка на MSGEQ7 и на фильтрах
ЦМУ на MSGEQ7. Также сюда добавляю второй проект ЦМУ на фильтрах.
ссылка на плату и схему https://oshwlab.com/technotrasher/colormusic
За год была проведена большая работа.
Итак ЦМУ на MSGEQ7.
1. Двухканальная схема. стерео.
2. Ручная регулировка шумов. предустановки шумов.
3. 7 режимов цму. в которых есть под-режимы.
4. 10 вариантов световых эффектов.
5. регулировки эффектов и режимов.
6. за "спектр" отвечают микросхемы MSGEQ7. достать рабочие сложно. (Купить более менее рабочие MSGEQ7 - по поиску на алиэкспресс "Модуль анализатора звука Aispark")
7. Аудио компрессор и система контроля клипинга взята тут - kompressor_SSM2167. прочтите обязательно, кто будет собирать.
8. описание режимов в начале скетча.
9. работа возможна с 300 светодиодами!
10. регулировка параметров с пульта и возможность сброса настроек "когда, что то нажал и все поломалось"
11. режим тишины с подсветкой (можно отключить), время срабатывания так же выставляется в скетче.
12 . Использованы статьи. тут для понимания работы MSGEQ7.
13. работа от микрофона. включается с пульта! на плате есть возможность отрегулировать чувствительность и время срабатывания микрофона.
14. режимы работы отображаются светодиодами на плате. на плате возможно механическое отсоединение сигнала с микрофона либо "байпас"
компрессора.
15. регулировка уровня входного сигнала линейным стерео потенциометром.
17. кнопки с платы убраны все, кроме переключения из ждущего режима. нужно для аварийного режима. если перестал работать пульт, а нужно включить хоть что то.
никаких энкодеров и т.д. скетч в первую очередь адаптировался под большую ленту. была битва за каждый байт и даже бит. и дорабатываться будет дальше.
18. Параметры сохраняются в память при отключении ЦМУ. в том числе режимы, шумы, настройки для режимов.
19. питание ленты обособлено от питания ардуино. вы не "сожжете" ардуино, забыв подключить внешний БП и программируя её через USB.
20.

Если вы нашли ошибку или знаете, как что то доработать - напишите об этом.

Особая благодарность Евгению (Slenk) - он находил на меня пару минут на ответ и подсказку. я же подглядывал в его скетч и брал самое лучшее.
так же благодарность - Sergo_ST без его подсказок и терпеливых ответов на мои глупые вопросы скетч был бы намного "толще и тупее". и не факт, что работал бы.


Этап второй ЦМУ на фильтрах. проект делается совместно с poty
проект сложен для сборки.
что сделано - плата. бетта версия. постоянно вносятся изменения. часть отлажена и уже работает.
модуль сбора данных. частично отлажен. работа продолжается.
ЦМУ на фильтрах можно повторять. работает! плату можно заказывать. недавно были изменены некоторые номиналы конденсаторов в фильтрах.
плата доступна тут .
скетч colorMusic_v8_filter.rar
эффектов очень много. все описано вначале скетча. могу сказать, что есть эффекты от Лумазоид ЦМУ. :)
 

Вложения

Изменено:

Комментарии

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
слепить обратно сигнал. Уверены? получится правильно? Я - нет. приводить сигнал нужно. Я написал про VU метр. никто так логику и не посмотрел. что там к чему приводится. Я разберусь сам. проверю все по частотам. и проверю по сумме частот вариант. на разных композициях.
 

bort707

★★★★★★✩
21 Сен 2020
2,893
860
слепить обратно сигнал. Уверены? получится правильно? Я - нет.
не "слепить обратно сигнал", а посчитать суммарную амплитуду.
Правильно или неправильно - это Вам решать, вы же автор проекта. Если Вы хотите сделать какой-то нестандартный VU метр - то может это Вам не подойдет.
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
да понял я. только не проверив это обсуждать что либо рано. то, что теоретически должно работать оказывается не оптимальным.
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
привет! работаю дальше со скетчем. делаю 7 каналов по цвету. задача - есть лента с кол-вом светодиодов NUM_LEDS. нужно ее "разбить на" на 7 отрезков. так чтобы они менялись в зависимости от длины ленты. то-есть если лента будет из 7 светодиодов то на каждый отрезок будет по одному светодиоду. такое возможно? если 180 то - по 25. пропорционально.
 

poty

★★★★★★✩
19 Фев 2020
2,990
895
Да, можно определить отрезки на ленте и управлять ими отдельно. Если в FastLed. Но это и самостоятельно можно сделать.
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
я про алгоритм. для трех каналов было так -
C++:
for (int i = 0; i < NUM_LEDS; i++) {
if (i < NUM_LEDS / 3)          one_color_all(LOW_COLOR_0, thissat, thisBright[0]);
else if (i < NUM_LEDS * 2 / 3) one_color_all(MID_COLOR_2, thissat, thisBright[1]);
else if (i < NUM_LEDS)         one_color_all(HIGH_COLOR_5, thissat, thisBright[2]);
}
 

bort707

★★★★★★✩
21 Сен 2020
2,893
860
И для семи можно так. Но лучше положить цвета в массив
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
ага. если бы я знал как это сделать - я бы не спрашивал. я уже роюсь в учебнике геометрии за школу. но может быстрее будет если кто подскажет.
 

poty

★★★★★★✩
19 Фев 2020
2,990
895
@technotrasher, приведённый кусочек кода не имеет смысла. Функция one_color_all заливает ВСЮ ленту одним цветом, передающимся в первом аргументе, с насыщенностью, задаваемой вторым аргументом и яркостью из третьего аргумента. Поэтому цикл в первую треть будет многократно закрашивать ленту цветом HSV(LOW_COLOR_0, thissat, thisBright[0]), вторую треть - HSV(MID_COLOR_2, thissat, thisBright[1]), последнюю треть - HSV(HIGH_COLOR_5, thissat, thisBright[2]).

@bort707,предлагал "загнать" цвет в двумерный массив:
CRGB leds[7][NUM_LEDS/7]
и обращаться к нужной части по первому индексу. FastLED будет рассматривать массив как одномерный (он по другому не умеет), поэтому всё будет хорошо и на своих местах.

Но я предпочитаю старый "ассемблерный" подход - вместо вычисления индекса каждый раз при доступе к массиву можно заранее вычислить длину "строки" и использовать инкрементируемые переменные:

C++:
// где-то объявляем массив
#define NUM_LEDS 180
const byte numstrips = 7;
const byte striplength = NUM_LEDS / numstrips;
CRGB leds[numstrips*striplength];

// где-то объявляем цвета
CRGB mcolor[7] = {HUE_RED, HUE_ORANGE, HUE_YELLOW, HUE_GREEN, HUE_AQUA, HUE_BLUE, HUE_PURPLE};

{
CRGB *curcolor = leds;
byte curstrip = 0;
byte curelement = 0;
CRGB stripcolor = mcolor[curstrip];
do {
    *curcolor = stripcolor;
    curcolor++;
    if (++curelement == striplength) {
        curelement = 0;
        if (++curstrip == numstrips) break;
        else stripcolor = mcolor[curstrip];
    }
} while (1);
}
Ну, и ещё один способ - воспользоваться С# и индексируемым объектом (перечислимым типом).
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
2,893
860
@poty, по-моему вы забыли про индексацию указателя curcolor, код реально ничего не делает
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
таак.
C++:
for (int i = 0; i < NUM_LEDS; i++) {
              if (i < NUM_LEDS / 7)                  one_color_all(LOW_COLOR_0, thissat, thisBright[0]);
              else if (i < NUM_LEDS * 2 / 7)         one_color_all(LOW_COLOR_1, thissat, thisBright[1]);
              else if (i < NUM_LEDS * 3 / 7)         one_color_all(MID_COLOR_2, thissat, thisBright[2]);
              else if (i < NUM_LEDS * 4 / 7)         one_color_all(MID_COLOR_3, thissat, thisBright[3]);
              else if (i < NUM_LEDS * 5 / 7)         one_color_all(MID_COLOR_4, thissat, thisBright[4]);
              else if (i < NUM_LEDS * 6 / 7)         one_color_all(HIGH_COLOR_5, thissat, thisBright[5]);
              else if (i < NUM_LEDS)                 one_color_all(HIGH_COLOR_6, thissat, thisBright[6]);
            }
где thissat - #define thissat 255 //-Насыщенность
thisBright - "яркости" по каналам.
LOW_COLOR и т.д. это да, цвета.

но ассемблерный подход интереснее. и памяти же выиграем? буду разбираться. все постепенно.
а one_color_all
// Функция делает всю ленту выбранным цветом
void one_color_all(byte all_color = 0, byte all_sat = 0, byte all_bright = 0) {
for (int i = 0 ; i < NUM_LEDS; i++ ) leds.setHSV(all_color, all_sat, all_bright);
}
 

bort707

★★★★★★✩
21 Сен 2020
2,893
860
но ассемблерный подход интереснее. и памяти же выиграем? буду разбираться. все постепенно.
что вы в данном случае называете "ассемблерным подходом"?

что касается кода - @poty правильно сказал, он ошибный. Функция one_color_all сюда не подходит
 

poty

★★★★★★✩
19 Фев 2020
2,990
895
@technotrasher, ну так сами же написали, что ВСЮ ленту ОДНИМ цветом! Зачем столько раз-то?
Вот, допустим, у нас 7 LED. Как выполнится программа:
i=0; i< 7/7; one_color_all(LOW_COLOR_0, thissat, thisBright[0]);
i=1; i< 14/7; one_color_all(LOW_COLOR_1, thissat, thisBright[1]);
i=2; i< 21/7; one_color_all(MID_COLOR_2, thissat, thisBright[2]);
...
i=6; i< 7; one_color_all(HIGH_COLOR_6, thissat, thisBright[6]);
конец цикла
И всё это ЗА ОДИН ЦИКЛ! Увидите Вы только последний цвет!
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
да я понял. вижу ошибку.
было изначально так
for (int i = 0; i < NUM_LEDS; i++) {
if (i < NUM_LEDS / 3) leds = CHSV(LOW_COLOR_0, thissat, thisBright[0]); //R
else if (i < NUM_LEDS * 2 / 3) leds = CHSV(MID_COLOR_2, thissat, thisBright[1]); //G
else if (i < NUM_LEDS) leds = CHSV(HIGH_COLOR_5, thissat, thisBright[2]); //B
}
но хотелось бы сделать лучше.
как бы это сделать правильно
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
с PROGMEM застрял
сделал так, как в документации

C++:
extern const TProgmemPalette16 DEFINE_GRADIENT_PALETTE PROGMEM;
CRGBPalette16 myPal = DEFINE_GRADIENT_PALETTE;
// градиент-палитра от зелёного к красному
//const TProgmemRGBPalette16 DEFINE_GRADIENT_PALETTE PROGMEM =
//{
//  0,    0,    255,  0,  // green
//  100,  255,  255,  0,  // yellow
//  150,  255,  100,  0,  // orange
//  200,  255,  50,   0,  // red
//  255,  255,  0,    0   // red
//};
const TProgmemRGBPalette16 DEFINE_GRADIENT_PALETTE PROGMEM =
{
        CRGB::Green,
        CRGB::Yellow,
        CRGB::Orange,
        CRGB::OrangeRed,
        CRGB::Red
}
работает только 16 диодов теперь...
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
шкала громкости (градиент) - в этом режиме хорошо бы сделать затухание в полосках.
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
С PROGMEM разобрался сам к утру, а с затуханием помог Slenk, за что ему благодарность великая.
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
Простите, но какая связь между "тяжестью" библиотеки и "местом под светодиоды"?
Первое это флеш, второе - ОЗУ, не пересекается вообще.
100 светодиодов
Скетч использует 23528 байт (76%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1099 байт (53%) динамической памяти, оставляя 949 байт для локальных переменных. Максимум: 2048 байт.
200 светодиодов
Скетч использует 23534 байт (76%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1538 байт (75%) динамической памяти, оставляя 510 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
что забивает динамическую память? глобальные переменные это, те, что "действуют" по всей программе? можно ли что либо сделать для оптимизации?
 

technotrasher

★★★★✩✩✩
14 Ноя 2019
501
223
лишние это ключевое слово. :))))) вот только они не лишние. ко мне обращались с просьбой сделать этот скетч на 300 светодиодов. :(
ладно. я понимаю - 328P. может загрузчик убрать и через ISP. :rolleyes: но я пока посмотрю, что можно убрать или переделать.
и вот, кстати - IRLremote - память динамическую не кушает сильно?