Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "fix_fft.h"
- #define MUESTRAS 128 // Numero de muestras para el cálculo de la FFT
- #define LOGM 7 // Logaritmo en base 2 del número de muestras
- #define BAJOS_MEDIOS 7 // Nº de banda para el corte entre Bajos y Medios
- #define MEDIOS_AGUDOS 35 // Nº de banda para el corte entre Medios y Agudos
- #define BPIN 2 // Pin de salida Bajos
- #define MPIN 3 // Pin de salida Medios
- #define APIN 4 // Pin de salida Agudos
- #define MAX_PASADAS 10 // Nº de pasadas para el cálculo de los límites
- char data[MUESTRAS]; // Array con los valores muestreados (parte real)
- char im[MUESTRAS]; // Array con los valores muestreados (parte imaginaria)
- unsigned char salida[MUESTRAS/2]; // Valores obtenidos de la FFT (espectro de 64 bandas)
- unsigned char bajos,medios,agudos; // Valores calculados para cada canal
- byte pasada, // nº de pasada para el cáculo de los límites
- acumBajos,acumMedios,acumAgudos, // acumuladores de veces que se supera el límite
- limBajos,limMedios,limAgudos; // límites calculados para cada canal
- const int boton1 = 5;
- const int boton2 = 6;
- const int boton3 = 7;
- const int interruptor = 8;
- const int ledInterruptor = 9;
- const int tiempoAntirebote = 10;
- int estadoBoton1;
- int estadoBoton2;
- int estadoBoton3;
- int estadoInterruptor;
- int estadoBotonAnterior1;
- int estadoBotonAnterior2;
- int estadoBotonAnterior3;
- /*
- * Funcion que aplica una ventana de Hann a los datos muestreados para reducir el
- * efecto de las discontinuidades en los extremos
- */
- void aplicaVentana (char *vData) {
- double muestrasMenosUno = (double(MUESTRAS) - 1.0);
- // Como la ventana es simétrica , se calcula para la mitad y se aplica el factor por los dos extremos
- for (uint8_t i = 0; i < MUESTRAS/2 ; i++) {
- double indiceMenosUno = double(i);
- double ratio = (indiceMenosUno / muestrasMenosUno);
- double factorPeso = 0.5 * (1.0 - cos(6.28 * ratio));
- vData[i] *= factorPeso;
- vData[MUESTRAS - (i + 1)] *= factorPeso;
- }
- }
- boolean antirebote(int pin){ //funcion que se usa para el correcto funcionamiento de los botones
- int contador = 0;
- boolean estado;
- boolean estadoAnterior;
- do{
- estado = digitalRead(pin);
- if(estado!=estadoAnterior){
- contador = 0;
- estadoAnterior = estado;
- }else{
- contador++;
- }
- delay(1);
- }while (contador<tiempoAntirebote);
- return estado;
- }
- void envioSenal(int boton, int botFrec,int estadoBotonAux,int estadoBotonAnteriorAux){ //funcion que comunica los botones con los canales
- if (estadoBotonAux!=estadoBotonAnteriorAux){
- if (antirebote(boton)){
- digitalWrite(botFrec,HIGH);
- }else{
- digitalWrite(botFrec,LOW);
- }
- }else{
- digitalWrite(botFrec,LOW);
- }
- estadoBotonAnteriorAux = estadoBotonAux;
- }
- void setup() {
- // Configuramos el prescaler a 32 -> 16Mhz/32 = 500 KHz
- // como cada conversion son 13 ciclos 500/13 ~ 38.4KHz
- // Es decir podemos medir en teoria hasta unos 19KHz,
- // que para este proyecto sobra.
- bitWrite(ADCSRA,ADPS2,1);
- bitWrite(ADCSRA,ADPS1,0);
- bitWrite(ADCSRA,ADPS0,1);
- // Como la señal es muy baja,utilizamos la referencia interna
- // de 1.1 V en vez de la de defecto de 5 V.
- analogReference(INTERNAL);
- // Salidas para los canales de Bajos,Medios y Agudos
- pinMode(BPIN,OUTPUT);
- pinMode(MPIN,OUTPUT);
- pinMode(APIN,OUTPUT);
- // Variables para el cálculo de los límites
- pasada = 0;
- acumBajos = acumMedios = acumAgudos = 0;
- limBajos = limMedios = limAgudos = 50;
- //entradas de los botones
- pinMode(boton1,INPUT);
- pinMode(boton2,INPUT);
- pinMode(boton3,INPUT);
- pinMode(interruptor,INPUT);
- pinMode(ledInterruptor,OUTPUT);
- }
- void loop() {
- estadoInterruptor = digitalRead(interruptor);
- if (estadoInterruptor){
- digitalWrite(ledInterruptor,HIGH);
- // Realizamos el muestreo
- for( int i=0; i < MUESTRAS; i++) {
- data[i] = analogRead(0)/4 -128; //Convertimos de 0..1024 a -128..127
- im[i] = 0; // parte imaginaria = 0
- }
- // Aplicamos la ventana de Hann
- aplicaVentana (data);
- // Calculamos la FFT
- fix_fft(data,im,LOGM,0);
- // Sólo nos interesan los valores absolutos, no las fases, asi que
- // calculamos el módulos de los vectores re*re + im*im.
- // Dado que los valores son pequeños utilizamos el cuadrado
- for (int i=0; i < MUESTRAS/2; i++){
- salida[i] = data[i] * data[i] + im[i] * im[i];
- }
- // Ahora repartimos las bandas entre las 3 salidas
- // En vez de sacar la media, utilizo sólo el valor máximo de
- // una banda
- bajos = 0;
- for (int i=2; i < BAJOS_MEDIOS; i++){
- bajos += salida[i];
- }
- bajos = bajos/2;
- medios = 0;
- for (int i=BAJOS_MEDIOS ; i < MEDIOS_AGUDOS; i++){
- medios += salida[i];
- }
- medios = medios/2;
- agudos = 0;
- for (int i=MEDIOS_AGUDOS; i < MUESTRAS/2; i++){
- agudos += salida[i];
- }
- agudos = agudos/2;
- // Calculamos si el canal correspondiente
- // supera le límite para encenderlo
- int siBajos = bajos > limBajos;
- int siMedios = medios > limMedios;
- int siAgudos = agudos > limAgudos;
- digitalWrite(BPIN,siBajos ? HIGH : LOW);
- digitalWrite(MPIN,siMedios? HIGH : LOW);
- digitalWrite(APIN,siAgudos? HIGH : LOW);
- // Utilizamos las veces que se supera para
- // recalcular el límite y evitar que con los
- // cambios de volumen los canales se saturen
- // o no funcionen.
- acumBajos += siBajos;
- acumMedios += siMedios;
- acumAgudos += siAgudos;
- if ( ++pasada > MAX_PASADAS ) {
- pasada = 0;
- limBajos = 20 + acumBajos*5;
- limMedios = 20 + acumMedios*5;
- limAgudos = 20 + acumAgudos*5;
- acumBajos = 0;
- acumMedios = 0;
- acumAgudos = 0;
- }
- }
- else{
- digitalWrite(ledInterruptor,LOW);
- estadoBoton1 = digitalRead(boton1);
- estadoBoton2 = digitalRead(boton2);
- estadoBoton3 = digitalRead(boton3);
- envioSenal(boton1,BPIN,estadoBoton1,estadoBotonAnterior1);
- envioSenal(boton2,MPIN,estadoBoton2,estadoBotonAnterior2);
- envioSenal(boton3,APIN,estadoBoton3,estadoBotonAnterior3);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement