Цветомузыка на AVR

Обсуждаем контроллеры компании Atmel.
KyJek
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт апр 07, 2015 19:19:29
Откуда: г. Москва

Re: Цветомузыка на AVR

Сообщение KyJek »

Действительно получается простой вольтметр. По анализатору спектра нашел преобразование фурье.
Делаем 5 замеров ацп в переменные Y1 - Y5, вычисляемY0
Y0 = (Y1+Y5+2*(Y2+Y4))/6 ,получается среднее значение сигнала
вычисляем гармоники сигнала:
M1 = (Y1 - Y5 + Y2 - Y4) / 3
M2 = (Y1 + Y5 - 2 * Y3) / 4
M3 = (Y1 - Y5 - 2 * (Y2-Y4)) / 6
M4 = ((Y1 + Y5) - 4 * (Y2 + Y4) + 6 * Y3) / 12
Где м1 - м4 амплитуды 1й - 4й гармоник сигнала. Можно вычислить из этого и коэффициент гармоник, но АВРу будет уже сложно K=(SQR((M2в степени 2)+(m3в квадрате)+(м4 в квадрате)))/м1 где К - коэффициент гармоник.
А вот что делать с этими циферками я не понял ))
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3868
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Цветомузыка на AVR

Сообщение Engineer_Keen »

KyJek писал(а):А вот что делать с этими циферками я не понял ))

Если вы про M1-M4, то выводить их через ШИМ на светодиоды, вот и получится анализатор спектра на 4 диапазона. Формулы кстати вы нашли довольно простые, их можно будет оптимизировать так, что даже тинька без аппаратного умножения/деления справится.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
KyJek
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт апр 07, 2015 19:19:29
Откуда: г. Москва

Re: Цветомузыка на AVR

Сообщение KyJek »

Что значит простые формулы? :)) :)) :)). Формула либо верная, либо не верная. Что я теряю применяя данные формулы и что я получу если формулы будут более сложные ? И для чего нужен коэффициент гармоник ?
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3868
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Цветомузыка на AVR

Сообщение Engineer_Keen »

KyJek писал(а):Что значит простые формулы? :)) :)) :)). Формула либо верная, либо не верная.

БПФ в общем виде выглядит сложнее, а тут уже все приведено к простому алгоритму.
KyJek писал(а):И для чего нужен коэффициент гармоник ?

Для цветомузыки он точно не нужен :)
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Цветомузыка на AVR

Сообщение ARV »

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

Мой уютный бложик... заходите!
KyJek
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт апр 07, 2015 19:19:29
Откуда: г. Москва

Re: Цветомузыка на AVR

Сообщение KyJek »

Формулы я взял отсюда. http://bascom.at.ua/publ/cvetomuzyka_qu ... t/1-1-0-20
Не знаю, насколько они правильные, но если есть другие предложения, я с радостью поковыряюсь!
Формулы, думаю да могут быть сложнее, возможно не 4 гармоники а больше и количество замеров не 5. Думаю, я проиграю в точности, но пока это не будет так принципиально.
KyJek
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт апр 07, 2015 19:19:29
Откуда: г. Москва

Re: Цветомузыка на AVR

Сообщение KyJek »

Так же я нашел довольно понятный и интересный пример кода БПФ.
main
Спойлер

Код: Выделить всё

/************************************************************************
   main.c

    FFT Audio Analysis
    Copyright (C) 2011 Simon Inns

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

   Email: simon.inns@gmail.com

************************************************************************/

#ifndef MAIN_C
#define MAIN_C

// Global includes
#include <htc.h>
#include <stdio.h>

// Local includes
#include "hardware.h"
#include "fft.h"
#include "graph.h"

// PIC18F4550/PIC18F2550 fuse configuration:
// Config word 1 (Oscillator configuration)
// 20Mhz crystal input scaled to 48Mhz and configured for USB operation
__CONFIG(1, USBPLL & IESODIS & FCMDIS & HSPLL & CPUDIV1 & PLLDIV5);
// Config word 2
__CONFIG(2, VREGEN & PWRTDIS & BORDIS & BORV20 & WDTDIS & WDTPS32K);
// Config word 3
__CONFIG(3, PBDIGITAL & LPT1DIS & MCLREN);
// Config word 4
__CONFIG(4, XINSTDIS & STVREN & LVPDIS & ICPORTDIS & DEBUGDIS);
// Config word 5, 6 and 7 (protection configuration)
__CONFIG(5, UNPROTECT);
__CONFIG(6, UNPROTECT);
__CONFIG(7, UNPROTECT);

// Globals
short imaginaryNumbers[64];
short realNumbers[64];

void main(void)
{
   // PIC port set up ----------

   // Configure on-board ADC
   // Vss and Vdd as voltage references
   ADCON1 = 0b00001110;

   // Configure the ADC acquisition time according to the datasheet
   ADCON2 = 0b10110110; // Note: output is right justified

   // Configure ports as inputs (1) or outputs(0)
   //        76543210
   TRISA = 0b00000001;
   TRISB = 0b00000000;
   TRISC = 0b00000011;
   TRISD = 0b00000000;
   TRISE = 0b00000000;

   // Clear all ports
   //        76543210
   PORTA = 0b00000000;
   PORTB = 0b00000000;
   PORTC = 0b00000000;
   PORTD = 0b00000000;
   PORTE = 0b00000000;
   
   RE0 = 0;
   RE1 = 0;
   RE2 = 0;
   
   // Initialise the gLCD
   gLcdInit();
   gLcdClear();

   
   while(1)
   {
      // Perform the FFT

      // Get 64 samples at 50uS intervals
      // 50uS means our sampling rate is 20KHz which gives us
      // Nyquist limit of 10Khz
      short i = 0;
      unsigned short result;
      for (i = 0; i < 64; i++)
      {
         // Perform the ADC conversion
         // Select the desired ADC and start the conversion
         ADCON0 = 0b00000011;    // Start the ADC conversion on AN0
      
         // Wait for the ADC conversion to complete
         TESTPIN_W4 = 1; // Don't remove this... it will affect the sample timing
         while(GODONE);
         TESTPIN_W4 = 0; // Don't remove this... it will affect the sample timing
         
         // Get the 10-bit ADC result and adjust the virtual ground of 2.5V
         // back to 0Vs to make the input wave centered correctly around 0
         // (i.e. -512 to +512)
         realNumbers[i] = ((short)(ADRESH << 8) + (short)ADRESL) - 512;
         
         // Set the imaginary number to zero
         imaginaryNumbers[i] = 0;
         
         // This delay is calibrated using an oscilloscope according to the
         // output on RA1 to ensure that the sampling periods are correct
         // given the overhead of the rest of the code and the ADC sampling
         // time.
         //
         // If you change anything in this loop or use the professional
         // (optimised) version of Hi-Tech PICC18, you will need to re-
         // calibrate this to achieve an accurate sampling rate.
         __delay_us(7);
      }

      // Perform the (forward) FFT calculation

      // Note: the FFT result length is half of the input data length
      // so if we put 64 samples in we get 32 buckets out.  The first bucket
      // cannot be used so in reality our result is 31 buckets.
      //
      // The maximum frequency we can measure is half of the sampling rate
      // so if we sample at 20Khz our maximum is 10Khz (this is called the
      // Nyquist frequency).  So if we have 32 buckets divided over 10Khz,
      // each bucket represents 312.5Khz of range, so our lowest bucket is
      // (bucket 1) 312.5Hz - 625Hz and so on up to our 32nd bucket which
      // is 9687.5Hz - 10,000Hz
      
      //  1 : 312.5 - 625
      //  2 : 625 - 937.5
      //  3 : 937.5 - 1250
      //  4 : 1250 - 1562.5
      //  5 : 1562.5 - 1875
      //  6 : 1875 - 2187.5
      //  7 : 2187.5 - 2500
      //  8 : 2500 - 2812.5
      //  9 : 2812.5 - 3125
      // 10 : 3125 - 3437.5
      // 11 : 3437.5 - 3750
      // 12 : 3750 - 4062.5
      // 13 : 4062.5 - 4375
      // 14 : 4375 - 4687.5
      // 15 : 4687.5 - 5000
      // 16 : 5000 - 5312.5
      // 17 : 5312.5 - 5625
      // 18 : 5625 - 5937.5
      // 19 : 5937.5 - 6250
      // 20 : 6250 - 6562.5
      // 21 : 6562.5 - 6875
      // 22 : 6875 - 7187.5
      // 23 : 7187.5 - 7500
      // 24 : 7500 - 7812.5
      // 25 : 7812.5 - 8125
      // 26 : 8125 - 8437.5
      // 27 : 8437.5 - 8750
      // 28 : 8750 - 9062.5
      // 29 : 9062.5 - 9375
      // 30 : 9375 - 9687.5
      // 31 : 9687.5 - 10000
      
      // Note: the '6' is the size of the input data (2 to the power of 6 = 64)
      TESTPIN_W5 = 1;
      fix_fft(realNumbers, imaginaryNumbers, 6);
      
      // Take the absolute value of the FFT results
      
      // Note: The FFT routine returns 'complex' numbers which consist of
      // both a real and imaginary part.  To find the 'absolute' value
      // of the returned data we have to calculate the complex number's
      // distance from zero which requires a little pythagoras and therefore
      // a square-root calculation too.  Since the PIC has multiplication
      // hardware, only the square-root needs to be optimised.         
      long place, root;
        for (int k=0; k < 32; k++)
        {
           realNumbers[k] = (realNumbers[k] * realNumbers[k] +
                   imaginaryNumbers[k] * imaginaryNumbers[k]);
                   
            // Now we find the square root of realNumbers[k] using a very
            // fast (but compiler dependent) integer approximation:
            // (adapted from: http://www.codecodex.com/wiki/Calculate_an_integer_square_root)
            place = 0x40000000;
         root = 0;
         
         if (realNumbers[k] >= 0) // Ensure we don't have a negative number
         {
            while (place > realNumbers[k]) place = place >> 2;
            
            while (place) 
            { 
               if (realNumbers[k] >= root + place) 
               { 
                  realNumbers[k] -= root + place; 
                  root += place * 2; 
               } 
               root = root >> 1; 
               place = place >> 2; 
            }
         }
         realNumbers[k] = root;
       }
       TESTPIN_W5 = 0;
      
       // Now we have 32 buckets of audio frequency data represented as
       // linear intensity in realNumbers[]
       //
       // Since the maximum input value (in theory) to the SQRT function is
       // 32767, the peak output at this stage is SQRT(32767) = 181.
      
       // Draw a bar graph of the FFT output data
       TESTPIN_W6 = 1;
       drawFftGraph(realNumbers);
       TESTPIN_W6 = 0;
   }
}

#endif



fft
Спойлер

Код: Выделить всё

/************************************************************************
   fft.c

    FFT Audio Analysis
    Copyright (C) 2011 Simon Inns

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

   Email: simon.inns@gmail.com

************************************************************************/

#ifndef FFT_C
#define FFT_C

#include <htc.h>
#include "fft.h"

// fix_fft.c - Fixed-point in-place Fast Fourier Transform

// All data are fixed-point short integers, in which -32768
// to +32768 represent -1.0 to +1.0 respectively. Integer
// arithmetic is used for speed, instead of the more natural
// floating-point.
//
// For the forward FFT (time -> freq), fixed scaling is
// performed to prevent arithmetic overflow, and to map a 0dB
// sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq
// coefficients.
//
// Written by:  Tom Roberts  11/8/89
// Made portable:  Malcolm Slaney 12/15/94 malcolm@interval.com
// Enhanced:  Dimitrios P. Bouras  14 Jun 2006 dbouras@ieee.org
// Ported to PIC18F:  Simon Inns 20110104

/*
  fix_fft() - perform forward fast Fourier transform.
  fr[n],fi[n] are real and imaginary arrays, both INPUT AND
  RESULT (in-place FFT), with 0 <= n < 2**m
*/
void fix_fft(short fr[], short fi[], short m)
{
   long int mr = 0, nn, i, j, l, k, istep, n, shift;
   short qr, qi, tr, ti, wr, wi;

   n = 1 << m;
   nn = n - 1;

   /* max FFT size = N_WAVE */
   //if (n > N_WAVE) return -1;

   /* decimation in time - re-order data */
   for (m=1; m<=nn; ++m)
   {
      l = n;
      do
      {
         l >>= 1;
      } while (mr+l > nn);
      
      mr = (mr & (l-1)) + l;
      if (mr <= m) continue;
      
      tr = fr[m];
      fr[m] = fr[mr];
      fr[mr] = tr;
      ti = fi[m];
      fi[m] = fi[mr];
      fi[mr] = ti;
   }

   l = 1;
   k = LOG2_N_WAVE-1;
   
   while (l < n)
   {
      /*
        fixed scaling, for proper normalization --
        there will be log2(n) passes, so this results
        in an overall factor of 1/n, distributed to
        maximize arithmetic accuracy.

        It may not be obvious, but the shift will be
        performed on each data point exactly once,
        during this pass.
      */
      
      // Variables for multiplication code
      long int c;
      short b;
      
      istep = l << 1;
      for (m=0; m<l; ++m)
      {
         j = m << k;
         /* 0 <= j < N_WAVE/2 */
         wr =  Sinewave[j+N_WAVE/4];
         wi = -Sinewave[j];

         wr >>= 1;
         wi >>= 1;
         
         for (i=m; i<n; i+=istep)
         {
            j = i + l;
            
            // Here I unrolled the multiplications to prevent overhead
            // for procedural calls (we don't need to be clever about
            // the actual multiplications since the pic has an onboard
            // 8x8 multiplier in the ALU):
            
            // tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]);
            c = ((long int)wr * (long int)fr[j]);
            c = c >> 14;
            b = c & 0x01;
            tr = (c >> 1) + b;
            
            c = ((long int)wi * (long int)fi[j]);
            c = c >> 14;
            b = c & 0x01;
            tr = tr - ((c >> 1) + b);
            
            // ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
            c = ((long int)wr * (long int)fi[j]);
            c = c >> 14;
            b = c & 0x01;
            ti = (c >> 1) + b;
            
            c = ((long int)wi * (long int)fr[j]);
            c = c >> 14;
            b = c & 0x01;
            ti = ti + ((c >> 1) + b);
            
            qr = fr[i];
            qi = fi[i];
            qr >>= 1;
            qi >>= 1;

            fr[j] = qr - tr;
            fi[j] = qi - ti;
            fr[i] = qr + tr;
            fi[i] = qi + ti;
         }
      }
      
      --k;
      l = istep;
   }
}

#endif




Правда код для пик, но думаю саму вычислительную часть можно взять отсюда. не очень понимаю как получить не 32 гармоники, а 4 уменьшить количество замеров до 8?
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Цветомузыка на AVR

Сообщение aam »

Здравствуйте!
Разбираюсь с БПФ и работой ЦМУ. До этого с ЦМУ дела не имел.
Какие вообще требования предъявляются к аналоговой части нормальной ЦМУ? Кто-то говорит, что достаточно полосы частот до 8 кГц. Так ли это или лучше сделать более широкую полосу?
Нашел пример на Мега8: http://lightportal.at.ua/publ/cvetomuzy ... 1/3-1-0-18
Не могу понять, как это работает без антиалиасингового фильтра?
Звук заводить хочу через микрофон чтобы небыло никаких проводов. Какие минусы у данного решения и реально ли так сделать нормальную ЦМУ? Или может через Блютуз?

Хочу сделать ЦМУ на 4 канала (светодиоды красного, желтого, зеленого и синего цвета). Как лучше разбить по частотам?
Как лучше выделять полосы - с помощью БПФ или же цифровыми фильтрами? Много видел споров на эту тему, но так и не нашел четкого ответа. Сам пока до конца не разобрался в алгоритмических тонкостях реализации БПФ и фильтров. Что быстрее - считать БПФ сразу для всего или же считать 4 шт фильтра? Также, какая дополнительная информация из спектра используется в разных эффектах? Т. е. для 4-х канальной ЦМУ достаточно ли только 4-х частотных полос или же надо иметь дополнительные частоты?
Ответить

Вернуться в «AVR»