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

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

Сообщение 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 где К - коэффициент гармоник.
А вот что делать с этими циферками я не понял ))
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

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

Сообщение KyJek »

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

Сообщение Engineer_Keen »

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

Сообщение ARV »

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

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

Сообщение KyJek »

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

Сообщение 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
Откуда: Москва

Сообщение aam »

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

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

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