capturando sonido con Atmega328

Ir abajo

capturando sonido con Atmega328

Mensaje por Pikitin el Vie 2 Mar 2012 - 17:50

Esto es una prueba de captura de sonido con la plaquita Metaboard con un chip Atmega328.
Esta placa es muy sencilla y barata, inspirada en las arduino, se programa por usb sin necesidad de programador (una vez grabado el bootloader) y tiene una pequeña area de prototipado.

Para capturar sonido con una calidad mínima el tema es cofigurar el ADC para que vaya lo más rápido posible: a 8 bits y en modo "free running" el adc se dispara sólo y hace una lectura cada 13 uS (reloj a 16 Mhz) sin tener que llamarlo por software. Esto sólo vale para leer un solo canal continuamente.

el programita de abajo crea una tarea que se ejecuta cada 52 uS , lee el registro adc, le aplica algunos efectos sencillos y el resultado lo saca por PWM.

Aqui hay dos efectos:
Reverb, que consiste en una especie de "eco" muy rápido, osea mezclar la lectura actual con una anterior.
Pitch, que aplica una onda sinoidal a la señal pra lograr un efecto de más grave o agudo.

La onda sinoidal no se calcula sino que está grabada en una tabla, así que sólo hay que leer los valores consecutivamente.

Con algún control exterior tipo pulsador se podrían ir cambiando los efectos, pero eso no esta incluido en este programita (gcbasic):



' Implementar adc rapido, captura sonido y aplica reverb y pitch

' Timer2 prescalers: 1-7: 1,8,32,64,128,256,1024

' presc KHz(aprox) Fosc: 16 MHz.
' 1 : 62.5
' 8 : 8
' 32 : 2
' 64 : 0.5
' 128 : 0.125


#chip mega328p, 16 'MHz

#include "sin_tab.h"

'Multitasking __________________________________________________________________

#include <multitasking.h>

#define base_time 52 'us
#define Task1 Sample
#define Task1_us base_time
'_______________________________________________________________________________

#define pwmPin PORTB.3 'OC2A

dir portb.5 OUT
portb.5 = 1 ' TO AREF

dir PORTD.0 out
PORTD.0 = 0

dir pwmPin out
dir PORTB.4 out
PORTB.4 = 0

dir PORTC out
dir PORTC.0 in

dim tempoint as integer


' Array ________________________________________________________________________

#define size 1000
dim buffer(size)

dim write as word ' array index to write data
dim read as word ' array index to read data
dim offset as word

read = 1
offset = 900 '46800/base_time
write = read + offset
'_______________________________________________________________________________

dim pitch as word
counter = 0

initpwm
initadc

Do
Do_Task1
Loop


'Subroutines ___________________________________________________________________

Sub initpwm ' Timer 2, 1 KHz 50% fosc: 16 MHz

OCR2A = 0 ' Duty 0%
' PWM Phase Correct, duty = OCR2X
TCCR2A = b'10000001' ' bits 6:7 output-A; bits 4:5 output-B
' Prescaler = 2 => presc 8
TCCR2B = b'00000001' ' Period = 2* 256 * 8/16 = 256 uS, Frec = 1/256e-6 = 3906,25 Hz
' Prescaler = 3 => presc 32
End Sub ' Period = 2* 256 * 32/16 = 1024 uS, Frec = 1/1024e-6 = 976,5 Hz

Sub initadc
ADMUX = b'01100000' ' Channel 0, Left justified, Vref = Avcc
ADCSRA = b'11100100' ' Enabled, Auto-Trigger, presc = 16
ADCSRB = 0
End Sub

Sub Sample
write += 1
if write > size then write = 1

read += 1
if read > size then read = 1

' Read sin table
if counter = 255 then
counter = 0
sin = 0
else
if counter = 0 then
sin = 0
else
ReadTable Sin_Tab, counter, sin
end if
counter += 1
end if

' Read actual adc value
value = ADCH

' Substract dc
tempoint = [integer]value - [integer]127

' Save actual reading
buffer(write) = value

' Aply Reverb ( add actual and buffered values)
tempoint = tempoint + [integer]buffer(read) - [integer]127
tempoint = tempoint / 2

' Aply sin wave to signal (pitch)
tempoint = ([integer]sin*tempoint)/[integer]255

' Output signal to pwm
OCR2A = tempoint + 127
End Sub

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.