Цветомузыка + ИК пульт

Эт, каэшна, наша недоработка! Сорян!

Фсё патамушта еще не пятница. Погоди чутка. Нужно с мыслЯми собраццо.

А что же тогда в первом посте?

ага… только не работает.

На АВР любой IR приемник конфликтует с адресной лентой. Пока лента обновляется, ничего приниматся не будет.
Для более конкретного ответа нужно видеть полный код, причём не тот что по ссылке, а ваш - с добавленным ИК приемником.

1 лайк

Вечером выложу, но код большой пожалуй строк 400. Подскажите как сделать спойлер.

выделить текст и нажать шестерёнку

Это очень маленький

Большой код - это когда 400 файлов по 400 строк в каждом, а не 400 строк всего.

 При использование кода указание авторства обязательно
****************************************************************/

[details="Спойлер"]
#include "Adafruit_NeoPixel.h"
#include <EEPROM.h>
#include "ffft.h"
//#include <avr/pgmspace.h>
//#include <math.h>
#include <NecDecoder.h>
NecDecoder ir;

typedef struct 
{
  uint8_t baseColor;
  uint8_t age;
  uint8_t magnitude;
  uint8_t rnd;
} peak_t;

#define DEBUG false //false //режим отладки true
#define N_BANDS    8 //число светодиодов для индикации в режиме настройки яркости
#define N_FRAMES   5
#define N_PEAKS   25
#define N_MODES   18//9 //19 общее количество режимов!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define N_MODES_LS 9 // количество режимов цветомузыки
//---------------Световые алгоритмические схемы ---------------------
#define PATTERN_DANCE_PARTY            0
#define PATTERN_SINGLE_DIR_DANCE_PARTY 1
#define PATTERN_PULSE                  2
#define PATTERN_LIGHT_BAR              3
#define PATTERN_COLOR_BARS             4
#define PATTERN_COLOR_BARS2            5
#define PATTERN_FLASHBULBS             6
#define PATTERN_FIREFLIES              7
#define PATTERN_RANDOM                 8
//---------------Режимы эффектов бегущих огрней----------------------
#define PATTERN_RAINBOW        9
#define PATTERN_SPARKLE       10
#define PATTERN_COL_RANDOM    11 
#define PATTERN_CYLON         12
#define PATTERN_STROBE        13
#define PATTERN_POLICE        14
#define PATTERN_BRIGHT        15
#define PATTERN_LAMP          16
#define PATTERN_FLAME         17
#define PATTERN_MATRIX        18
#define PATTERN_BALLS         19
#define PATTERN_FIRE          20
//---------------цветовые схемы---------------------
#define N_COLOR_MODES 3 //число режимов 
#define COLOR_RANDOM  0 //Случайная двухцветная схема: выбраны два случайных цвета
#define COLOR_CYCLE   1 //меняется как радуга с течением времени
#define COLOR_BAND    2 //Цветные частоты. Самая низкая красного цвета, и т.д. вверх красный,оранжевый,желтый,зеленый,голубой,синий,фиолетовый,белый
//-----------------выбор конфигурации ленты--------------------------------
#define LEDCONFIG_60  0
#define LEDCONFIG_94  1//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define LEDCONFIG_120 2
//-------------------------------------------------
#define MAX_COLOR_BARS 22
#define MAXCOLORINDEX 256
#define EEPROM_MAGIC_NUMBER 0xbad1 //магическое число, для индетификации первого запуска

#define UNUSED   255

//Описание кнопок ИК пульта 
#define IR_1     0xA2
#define IR_2     0x62
#define IR_3     0xE2
#define IR_4     0x22
#define IR_5     0x2
#define IR_6     0xC2
#define IR_7     0xE0
#define IR_8     0xA8
#define IR_9     0x90
#define IR_STAR  0x68
#define IR_0     0x98
#define IR_HASH  0xB0
#define IR_UP    0x18
#define IR_LEFT  0x10
#define IR_OK    0x38
#define IR_RIGHT 0x5A
#define IR_DOWN  0x4A

#define ADC_CHANNEL  0 // аналоговый вход, для аудио
#define PARM_POT     1 // аналоговый вход для потенциометрам PARAM
#define BACKGROUND ((uint32_t) 0x000006) // фоновая подсветка при тишине
#define Treshold_pot 9

#define PATTERN_BUTTON_PIN 4 // 2 Кнопка PATERN
#define COLOR_BUTTON_PIN   3 //кнопка COLOR
#define LED_PIN           13 //системный светодиод, нужно использовать выводы только с ШИМ
#define LED_STRIP_PIN      6 // пин подключения к LED ленте
#define N_LED_LAMP        50 // какое количество светодиодов использовать в светильнике
#define NUM_LED           94 //120 количество светодиодов в ленте по умолчанию !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
uint8_t N_LEDS = NUM_LED;       
uint8_t MAX_AGE =          0;


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LED, LED_STRIP_PIN, NEO_GRB + NEO_KHZ800);

peak_t peaks[N_PEAKS];
uint8_t peakIndex = 0;
uint8_t newPeakFlags = 0;
uint8_t mode = 0;
uint8_t pattern = 0;
uint8_t cutoffFreqBand = 7;
uint8_t colorMode = COLOR_BAND; //COLOR_CYCLE; //цветовая схема по умолчанию
uint8_t colorIndexIncFreq = 100;
uint8_t colorIndex = 0;
uint8_t randColor[] = {0, 0};
uint8_t randColorCount[] = {0, 0};
uint8_t randColorChangeParm = 10;
uint8_t ledConfig = LEDCONFIG_94;//120; //число светодиодов по умолчанию!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
uint16_t parm;
uint16_t lastParm;
uint8_t colorBars[MAX_COLOR_BARS];
uint16_t loopCounter = 0;
uint16_t loopCounterMax = 500;
boolean randomized = false;
uint8_t recentPatterns[3];
uint8_t recentPatternIndex = 0;
uint8_t transitionWaitTime = 0;

// FFT_N = 128
int16_t       capture[FFT_N];    // Audio буфер захвата
complex_t     bfly_buff[FFT_N];  // FFT "butterfly" buffer
uint16_t      spectrum[FFT_N / 2]; // Spectrum output buffer

volatile uint8_t  smp; //порог срабатывания, уровень шума NoiseThreshold=0,
volatile uint8_t samplePos = 0;     // Начальнаячя позиция в буфере
uint8_t maxBrightness = 255;       //  яркость максимальная
float brightnessScale = 1.0;    // коэффициент яркости

byte
bandPeakLevel[8],      // Peak level of each band
  bandPeakCounter = 0, // Frame counter for delaying the fall of the band peak
  bandPeakDecay = 6, // peak decreases by 1 every bandPeakDecay frames. Larger value is slower decay
  bandCount = 0;      // Frame counter for storing past band data

int
band[8][N_FRAMES],   // band levels for the prior N_FRAMES frames
     minLvlAvg[8], // For dynamic adjustment of low & high ends of graph,
     maxLvlAvg[8], // pseudo rolling averages for the prior few frames.
     bandDiv[8];    // Used when filtering FFT output to 8 bands

// declare all control variables here so we can more easily measure memory consumption
uint8_t j, noiseThreshold, *data, nBins, binNum, c;
uint16_t minLvl, maxLvl;
int16_t level, sum;

const uint8_t PROGMEM noiseFloor[64] = {8, 6, 6, 5, 3, 4, 4, 4, 3, 4, 4, 3, 2, 3, 3, 4, 2, 1, 2, 1, 3, 2, 3, 2, 1, 2, 3, 1, 2, 3, 4, 4, 3, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4};
const uint8_t PROGMEM eq[64] = {255, 175, 218, 225, 220, 198, 147, 99, 68, 47, 33, 22, 14, 8, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const uint8_t PROGMEM bandBinCounts[] = {2, 4, 5, 8, 11, 17, 25, 37};
const uint8_t PROGMEM bandBinStarts[] = {1, 1, 2, 3, 5, 7, 11, 16};
const uint8_t PROGMEM band0weights[] = {181, 40};
const uint8_t PROGMEM band1weights[] = {19, 186, 38, 2};
const uint8_t PROGMEM band2weights[] = {11, 176, 118, 16, 1};
const uint8_t PROGMEM band3weights[] = {5, 55, 165, 164, 71, 18, 4, 1};
const uint8_t PROGMEM band4weights[] = {3, 24, 89, 139, 148, 118, 54, 20, 6, 2, 1};
const uint8_t PROGMEM band5weights[] = {2, 9, 29, 70, 125, 172, 185, 162, 118, 74, 41, 21, 10, 5, 2, 1, 1};
const uint8_t PROGMEM band6weights[] = {1, 4, 11, 25, 49, 83, 121, 156, 180, 185, 174, 149, 118, 87, 60, 40, 25, 16, 10, 6, 4, 2, 1, 1, 1};
const uint8_t PROGMEM band7weights[] = {1, 2, 5, 10, 18, 30, 46, 67, 92, 118, 143, 164, 179, 185, 184, 174, 158, 139, 118, 97, 77, 60, 45, 34, 25, 18, 13, 9, 7, 5, 3, 2, 2, 1, 1, 1, 1};
const uint8_t PROGMEM * const bandWeights[] = {band0weights, band1weights, band2weights, band3weights, band4weights, band5weights, band6weights, band7weights};

//*******************************************************************************************************
void setup() {
 {   Serial.begin(9600);
attachInterrupt(0, irIsr, FALLING);}// подключил на D2, прерывание 0
  strip.setBrightness(maxBrightness);
  randomSeed(analogRead(2)); // получаем стартовое случайное значение 
  memset(bandPeakLevel, 0, sizeof(bandPeakLevel)); //создать буфер в RAM
  memset(band, 0, sizeof(band));//создать буфер в RAM
  for (uint8_t i = 0; i < N_BANDS; i++)
  {
    binNum = pgm_read_byte(&bandBinStarts[i]);
    nBins = pgm_read_byte(&bandBinCounts[i]);
    minLvlAvg[i] = 0;
    maxLvlAvg[i] = 512;
    data = (uint8_t *)pgm_read_word(&bandWeights[i]);
    for (bandDiv[i] = 0, j = 0; j < nBins; j++) 
    {
      bandDiv[i] += pgm_read_byte(&data[j]);
    }
  }
  for (uint8_t i = 0; i < N_PEAKS; i++) 
  {
    peaks[i].age = 0;
    peaks[i].magnitude = 0;
  }
  for (uint8_t i = 0; i < MAX_COLOR_BARS; i++) 
  {
    colorBars[i] = UNUSED;
  }
  for (uint8_t i = 0; i < 3; i++) 
  {
    recentPatterns[i] = UNUSED;
  }

  lastParm = 0;
  parm = map(analogRead(PARM_POT), 0, 1023, 0, 255); //прочитать положение потенциометра PARAM
  
  setADCFreeRunning(); //запустить прерывание от АЦП
  DIDR0  = 1 << ADC_CHANNEL; // Отключение цифрового входа для указанного вывода АЦП

  pinMode(PATTERN_BUTTON_PIN, INPUT_PULLUP); //кнопка PATTERN
  pinMode(COLOR_BUTTON_PIN, INPUT_PULLUP);  //кнопка COLOR
 /* pinMode(LED_PIN, OUTPUT);                 //системный светодиод
  for (i = 0; i < 5; i++) //мигнуть 5 раз системным светодиодом
  {
    digitalWrite(LED_PIN, HIGH);//включить системный светодиод
    delay(50);
    digitalWrite(LED_PIN, LOW); //выключить системный светодиод
    delay(50);
  }*/

  sei(); // разрешить все прерывания

  strip.begin();
  strip.show(); 

  // проверяем, есть ли сохраненные настройки EEPROM?
  // если да, то считываем их
  if (EEPROMValid()) //проверяем на первое включение контролера
  {
    ledConfig = EEPROM.read(2); //конфигурация светодиодной ленты
    if (ledConfig > LEDCONFIG_94) ledConfig = LEDCONFIG_94; // EEPROM.write(2, ledConfig);}//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    mode = EEPROM.read(3); //последний выбраный режим световой схемы
    if (mode > N_MODES)  mode = 0;  // EEPROM.write(3, mode);}
 
    pattern = mode;
      if (pattern == PATTERN_RANDOM) 
       {
         randomized = true;
          pattern = chooseRandomPattern();
          loopCounter = 0;
        } else { randomized = false;  }
    
    maxBrightness = EEPROM.read(4);     //последние сохраненные настройки яркости ленты
    brightnessScale = maxBrightness / 255.0;
    colorMode = EEPROM.read(5);         //режим цветовой схемы
    if (colorMode > COLOR_BAND) {colorMode = COLOR_BAND;  EEPROM.write(5, colorMode);}
    cutoffFreqBand = EEPROM.read(6);    //настройки частоты среза
    if (cutoffFreqBand > 7) {cutoffFreqBand = 7;  EEPROM.write(6, cutoffFreqBand);}
    //NoiseThreshold = EEPROM.read(7);
  }
  else {
          test(); // запуск диагностики при первом включении питания
          ledConfig = LEDCONFIG_94;//120;  // если EEPROM не записана, то по умолчанию 120 LEDs,!!!!!!!!!!!! 
          mode = 0;                  // первый режим
          maxBrightness = 255;       //яркость максимальная
          colorMode = COLOR_BAND;    //цветовая схема COLOR_BAND
          cutoffFreqBand = 8;        //частотный срез все 8 частот
         // NoiseThreshold = 4;      //уровень срабатывания АЦП
          saveConfig();
         }

  configure(); 
  setConfig();
  setParameters();
  TIMSK0 = 0;                // Выключить Timer0

/*#if DEBUG //для отладки
  Serial.begin(115200);
  Serial.println(getMemory());
 // Serial.println(NoiseThreshold);
#endif*/
}
//************************************Главный цикл программы*******************************************
void loop() 
{
  //Пока прерывание АЦП включено, ждем завершения    
  // Обработчик прерывания собирает аудио семплы в буфер захвата.
  while (ADCSRA & _BV(ADIE));

  strip.show(); //отправляем последние сформированые данные на светодиодную ленту.

  fft_input(capture, bfly_buff);// Выполнить алгоритм FFT для преобразования выборок в сложные числа.

  // Чтобы получить показания потенциометра, переводим АЦП в стандартный режим
 // setADCDefault();    //переводим АЦП в стандартный режим
//  lastParm = parm;
//  parm = analogRead(PARM_POT); //прочитать состояние  потенциометра
//  if (parm != lastParm) // меняем настройки если положение потенциометра было изменено
//  {
//    setParameters();
//  }

  if ((colorMode == COLOR_CYCLE) && ((loopCounter % colorIndexIncFreq) == 0)) 
  {
    colorIndex++;
  }
  
  loopCounter++;
  if ((randomized) && (loopCounter > loopCounterMax)) 
  {
    loopCounter = 0;
    loopCounterMax = random(500, 1000);
    transitionWaitTime = determineWaitTime();
  }

  if (transitionWaitTime > 0) 
  {
    transitionWaitTime--;
    if (transitionWaitTime == 0) 
    {
      pattern = chooseRandomPattern();
      setParameters();
      reset();
    }
  }

  setADCDefault();    //переводим АЦП в стандартный режим
  button_pattern(); //проверяем нажатие кнопки PATTERN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  strip.setBrightness(255);  
//              if (ir.available()) {button_pattern(); }
    digitalWrite(LED_PIN, HIGH);//включить системный светодиод
//    delay(50);

    if (ir.available()) {
    // вывести команду (8 бит)
    Serial.print("0x");
    Serial.println(ir.readCommand(), HEX);
  }              
    digitalWrite(LED_PIN, LOW); //выключить системный светодиод
//    delay(50);

  // проверяем нажатие кнопки COLOR
  if ((digitalRead(COLOR_BUTTON_PIN) == LOW) && (digitalRead(PATTERN_BUTTON_PIN) == HIGH)) 
  {
    //digitalWrite(LED_PIN, HIGH);//включить системный светодиод
    setColorMode();
  }

  // Если кнопки COLOR и pattern нажаты, то меняем частотные срезы
  if ((digitalRead(COLOR_BUTTON_PIN) == LOW) && (digitalRead(PATTERN_BUTTON_PIN) == LOW)) 
  {
    // Both buttons held. Set cutoff frequency band.
    //digitalWrite(LED_PIN, HIGH);//включить системный светодиод
    setCutoffFreqBand();
  }

  setADCFreeRunning();             // снова настраиваем АЦП на работу по прерыванию

  // The rest of the FFT computation:
  fft_execute(bfly_buff);          // Process complex data
  fft_output(bfly_buff, spectrum); // Complex -> spectrum

  // Now call this to analyze the audio. See comments in this function for details.
  analyzeAudioSamples();


  if (transitionWaitTime == 0)  // only do this if not waiting to transition to new mode
  {

    // The peak values for each of the 8 bands has been computed. A bit in the 8-bit
    // value newPeakFlags indicates whether the analysis found a *new* peak in the band.
    for (uint8_t i = 0; i <= cutoffFreqBand; i++) 
    {

      // If a new peak was found in band i...
      if (newPeakFlags & (1 << i)) {
        // Map the peak value to a magnitude in range [0,255]. We pass in the band
        // number because the mapping is different for different bands.
        uint8_t magnitude = getMagnitude(i, bandPeakLevel[i]);

        // A nonzero magnitude means that the peak value is large enough to do
        // something visually with it. We ignore small peaks.
        if (magnitude > 0) 
        {
          // We want to store the information about the peak in a peak_t structure.
          // When we actually draw a visualization, the peak_t structures in peaks[]
          // represent the "visually active" band peaks.
          if (pattern != PATTERN_PULSE) 
          {
            // Look through the list of peak structures 'peaks' for an unused one.
            for (j = 0; j < N_PEAKS; j++) 
            {
              if (peaks[j].magnitude == 0) 
              {
                // unused peak found
                peakIndex = j;
                break;
              }
            }
          } else {
                    peakIndex = i; // для импульсного режима, просто используеся пик для каждой полосы частот
                  }
            // Если не найден, мы используем последний используемый (peakIndex).     
          // Инициализация структуры
          peaks[peakIndex].age = 0;
          peaks[peakIndex].rnd = random(255); //случайное значение для визуализации
          if (colorMode == COLOR_BAND) 
          {
            peaks[peakIndex].baseColor = i * 32;
          }
          if (colorMode == COLOR_RANDOM) 
          {
            peaks[peakIndex].baseColor = getRandomBaseColor(peaks[peakIndex].rnd);
          }
          if (colorMode == COLOR_CYCLE) 
          {
            peaks[peakIndex].baseColor = colorIndex;
          }
          peaks[peakIndex].magnitude = magnitude;
        }
      }
    }
  }

  if (pattern != PATTERN_LIGHT_BAR) 
  {
    strip.clear();   // выключаем все светодиоды в ленте
  }

  doVisualization(); // визуализация
}
//***********************************************************************************
void irIsr() {  ir.tick();}  // в прерывании вызываем tick()
//************************проверяем нажатие кнопки PATTERN**************************
void button_pattern()
{
  parm = analogRead(PARM_POT); //прочитать состояние  потенциометра
  parm = map(parm, 0, 1023, 0, 255);//уменьшить разрядность parm
  if(abs(parm - lastParm) < Treshold_pot) parm=lastParm; //фильтр шумов
  if (lastParm != parm) // если положение потенциометра было изменено
  {
   lastParm = parm;
    strip.setBrightness(parm); //изменяем яркость
  }
  
//  if (ir.available()) {
//    switch (ir.readCommand()) {
//      case IR_LEFT:  setMode(); break;
//      case IR_RIGHT: setMode(); break;
//    }
//  } 
  
  if ((digitalRead(PATTERN_BUTTON_PIN) == LOW) && (digitalRead(COLOR_BUTTON_PIN) == HIGH))  // Если кнопка pattern нажата
  {
    //digitalWrite(LED_PIN, HIGH);
    setMode();
  }
 }  

[/details]

9.10.167.168.319-322.418. Строки которые я вставил.


1 канал- вход от ИК датчика, 2- выход обработанного кода кнопки, 3- выход на адр.ленту.

скока же амбиций)

я авторства не нашел, если меня стукнет молния и придется использовать ваш код, так и укажу
“Автор - НеЯ

1 лайк

Возникает догадка, что неопиксель или ffft отключают прерывания. Кто нить знает так оно или нет. Обновление ленты идет чаще 50Гц. Думаю без видимых проблем можно снизить скорость кадров вдвое, а то и до 10Гц. тогда команда будет помещаться между кадрами. Подскажите в какой строке указывается частота кадров.
Второй вариант. При появлении прерывания происходит переход на обработку сигнала. а потом возврат. На скриншоте видно, что команда попала между посылками в ленту, Даже если они совпадут, то посылка гораздо длиннее и все должно получиться.

Это не мой код, писал с самого начала, читай внимательнее, и авторов указал.

Э! У меня в фамилии бува Ё. Уважайте еЁ.

Серёгин чтоле?

Вот здесь о конфликте новых версий ик библиотеки - итог откат к старой.
https://mysku.club/blog/aliexpress/68990.html

Не угадал.Нанаец я.

bёzzon или bizzёn?

Я ж намекнул. Нанаец. Группа так называлась, Их начальник ещё шёлочь туалетную выпил.

Это квест.

Нанаёц?

1 лайк

Лёвкин.