sábado, 29 de agosto de 2015

Construcción de un Vúmetro en AVR



DEFINICIÓN

El vúmetro es un dispositivo indicador en equipos de audio para mostrar el nivel de señal en unidades de volumen, también es llamado indicador del volumen.




DESCRIPCIÓN DEL PROYECTO

Tal como se ha dicho en la definición, un vúmetro es un indicador de nivel de señal de audio, por lo que se decidió  realizar el proceso de indicador de unidades de volúmenes en cintas LED RGB armadas en placas de acrílico controladas por un micro-controlador AVR (ATmega164P) y por un Controlador RGB.

El diagrama  del proyecto realizado es totalmente diferente a la versión original tal como se describe en el siguiente imagen.

Según el diagrama, lo primero lo que se observa es la forma en como se encuentran conectadas las 10 cintas LEG RGB, donde cada terminal R, G y B se encuentran conectadas entre si mismas a un solo punto del Controlador RGB. 

El controlador RGB se encarga de realizar el control de intensidad de luz, tonalidades de colores, modos de efectos, velocidad de transición, etc, para todas las filas en conjunto.

Cada cinta es controlada independientemente a través sus terminales positivos (+12V), que se encuentran conectadas a la tarjeta de control. Esta tarjeta realiza la tarea del vúmetro que define el nivel del audio de entrada.

FUNCIONAMIENTO DEL ALGORITMO

El algoritmo de funcionamiento es muy sencillo. Se usa un canal analógico para el nivel de audio de entrada. Si el nivel de audio de entrada es cero, los puertos de salida para cada cinta LED serán cero "niveles de voltaje 0V", caso contrario encenderá cada nivel dependiendo del nivel de señal de entrada acondicionada "niveles  de voltaje 12V".

FUSIONES  Y DESCRIPCIONES DEL uC ATMEGA164P

El uC se encarga de la lectura de datos de la señal de audio de entrada en el canal analógico ADC0 con una resolución por defecto de 10bits, 

Para la visualización de los niveles de audio se usa 10 pines del uC, todos los pines del puerto D (PD0,...,PD7) y 2 pines menos significativos del puerto C (PC0, PC1).

PD0  -> Nivel 1
PD1  -> Nivel 2
PD2  -> Nivel 3
PD3  -> Nivel 4
PD4  -> Nivel 5
PD5  -> Nivel 6
PD6  -> Nivel 7
PD7  -> Nivel 8
PC0  -> Nivel 9
PC1  -> Nivel 10

CIRCUITO

Según el circuito, para la señal de audio se usa un diodo protector "Diodo Zener" para evitar sobre voltajes y quemar el uC.

Se usa dos dispositivos para conectar la señal de audio al circuito dependiendo del caso, uno para un conector RCA y otro para un conector estereo de 3,5mm.

Cada fila tiene una configuración de transistores independientemente, con el propósito de proporcionar +12V exactos a las cintas con puntos de referencia externas a los circuitos, y para poder conectar cintas de mayor corriente.



DISEÑO PCB




PROGRAMACIÓN

El programa fue desarrollado en CodeVIsionAVR.
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : Vumetro
Version : 1.0
Date    : 03/07/2015
Author  : Byron Ganazhapa
Company : ANOM.
Comments: 


Chip type               : ATmega164P
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/

#include <mega164.h>
#include <delay.h>

int led[10] = {0,1,2,3,4,5,6,7,8,9}; // Pines de salida para los leds.

// Declare your global variables here


// Voltage Reference: AVCC pin
#define ADC_VREF_TYPE ((0<<REFS1) | (1<<REFS0) | (0<<ADLAR))

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}

int analog_voltage(int analog_channel)
{
    int adc_data = read_adc(analog_channel);    
    return adc_data;
}

void Digital_ports(int ports, int logic){
 switch (ports) {
    case 0:
        PORTD.0 = logic;
    break;
    
    case 1:
        PORTD.1 = logic;
    break;
    
    case 2:
        PORTD.2 = logic;
    break;
    
    case 3:
        PORTD.3 = logic;
    break;
    
    case 4:
        PORTD.4 = logic;
    break;
    
    case 5:
        PORTD.5 = logic;
    break;
    
    case 6:
        PORTD.6 = logic;
    break;
    
    case 7:
        PORTD.7 = logic;
    break;
    
    case 8:
        PORTC.0 = logic;
    break;
    
    case 9:
        PORTC.1 = logic;
    break;
       
    default:
    };

}

void main(void)
{
// Declare your local variables here

int signal;
float vumeter_level;
int cont;

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (1<<DDC1) | (1<<DDC0);
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);



// ADC initialization
// ADC Clock frequency: 1000,000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: Off, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On, ADC6: On, ADC7: On
DIDR0=(0<<ADC7D) | (0<<ADC6D) | (0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (1<<ADC0D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

while (1)
      {
        signal =  analog_voltage(0);
        vumeter_level = signal/5;  // acondionamiento de la señal de entrada.
        
        if (vumeter_level == 0){
            for (cont = 0; cont < 10; cont++){
                Digital_ports(led[cont],0);
            };
        }
        else{
            for (cont = 0; cont < vumeter_level; cont++){
                Digital_ports(led[cont],1);
            }
            for (cont = 0; cont < 10; cont++){
                Digital_ports(led[cont],0);
            }
        }
      }
}

PROYECTO CONCLUIDO

Las siguientes imágenes es el armado del proyecto, pero si necesitas como construir la estructura en acrílico respecto a la versión original del proyecto, puedes visitar el siguiente enlace.










REFERENCIAS
  1. Armando tiras led RGB y acrílicos para vúmetro, [Online]. Disponible en: https://www.youtube.com/watch?v=ASECWHQGvpk
  2. vu-Tower vu meter, Version Orginal, [Online]. Disponible en: https://www.youtube.com/watch?v=dsyPOGqy9to

DESCARGAS

Codigo y HEX. del proyecto en CodeVisionAVR:

Esquema electrónico y Diseño PCB en Proteus.