AVR(ADC)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
saddox
Inlägg: 132
Blev medlem: 2 januari 2005, 09:46:11
Ort: Karlstad
Kontakt:

AVR(ADC)

Inlägg av saddox »

Jag håller på och leker med en Mega8 och ADC-biten.
Eftersom jag är intresserad av musik, och då främst elektronisk sådan, så har jag slängt ihop en enkel krets för att få inkommande signal mellan 0-5V och centrerad runt 2.5 V. Aref ligger på 5 V. En stycken DAC0830 sitter på en port, dac:n är konfigurerad för "flow-through". 8bitar kör jag med.
Så allt det ska fungera.. och det gör det. Får snuskigt skitigt ljud ut. Det kan ju vara trevligt ibland.
Egentligen en rätt meningslös krets/effekt men den ger ju lite mer crunch/8bitars-känsla i ljudet. Blir mer vettig när man blandar orginalljudet med det "destruerade" ljudet.


Men så började man fundera....

Hur ska man egentligen göra för att få bästa möjliga kvalité ur denna uppkoppling?
Kan man göra interna inställningar i AVR:en mer än sleep-funktionerna(stänga av CPU under konverteringen) och matcha in skalningen så samplingsfrekvensen blir lämplig osv?

Min ingångkrets består egentligen bara av en spänningsdelning, sedan två lika motstånd som lyfter signalen till mitten av matningspänningen. Efter den två dioder som skyddar för negativa och för höga spänningar. En OPamp(spänningsföljare) ska kopplas in också..

Tacksam för alla svar.
Användarvisningsbild
JimmyAndersson
Inlägg: 26579
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Vad kör du med för hastighet till DAC'en? (samplingshastighet.)
saddox
Inlägg: 132
Blev medlem: 2 januari 2005, 09:46:11
Ort: Karlstad
Kontakt:

Inlägg av saddox »

Väldigt bra fråga faktiskt.. har suttit och lekt lite väl mycket med koden men 4 MHz på CPUn och skalning 32(101) borde väl ge 125 kHz till ADCn?
ADLAR = 1 också.
saddox
Inlägg: 132
Blev medlem: 2 januari 2005, 09:46:11
Ort: Karlstad
Kontakt:

Inlägg av saddox »

Ajdå.. läsa ska man.. DACn.. samma som ADCns hastighet.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Jag har också försökt mig på något liknande men jag hamnade i annat göra, så det blev inte så mycket av det... Jag han dock få igång sampling i 8kHz, skicka ut det via uart, ta in det igen och "spela upp" det med PWM. Jag han dock inte testa med riktigt ljud utan bara en trimpot och det verkar i alla fall fungera... Tyvärr så orkar jag ju bara "vrida fram" ett par Hz på trimpotten, så frågan är hur det fungerar i höga frekvenser.

Skalning 32 borde ju vara det optimala eftersom det ger en frekvens på 125kHz och varje omvanling tar ca 13 cykler (tror jag). 125kHz/13=9615 omvandlingar per sekund, vilket är strax över 8kHz.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Om jag fattat dig rätt så kör du alltså "så fort det bara går" med prescaler 32? Det borde bli ca 9,6kHz samplingshastighet. Den kod jag använder utnyttjar en timer för att sampla med 8kHz, den använder även PWM för att skicka ut signalen.. dessutom så tar den omvägen via UART:en, så rx och tx måste byglas om du vill testa exemplet:

Kod: Markera allt

/*********************************************
* Chip type           : ATmega8
* Clock frequency     : 4,000000 MHz
*********************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

#define TRUE			1
#define FALSE			0	

volatile unsigned char sendflag = 0;	
volatile unsigned char ch = 'a';

void usart_putc(unsigned char c) {
	while(!(UCSRA & (1 << UDRE)));	//Wait for empty buffer
	UDR = c;    					// send character
}

void init_port(void){
	DDRB	= 0x01 | _BV(PB3);	//1=out, 0=in
	DDRC 	= 0xFE;	//Debug Ut
	DDRD	|= _BV(PD7);
	PORTC 	= 0xFE;	//Debug Släck
}

void init_timer(void) {
	TCCR1B |= _BV(CS10) | _BV(WGM12); 			//Start timer with prescaler 1, CTC
	OCR1A = 0x01F4;
	TIMSK|=(1<<OCIE1A); 	//timer 1 interrupt source
}

void init_UART(void) {
	UBRRH = 0;	//Set baudrate
	UBRRL = 1;
	UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE); 		//Enable Rx, Tx and Rx interrupt
}

void init_ADC(void){
	ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS0);	//Enable AD
	ADMUX |= _BV(ADLAR);
}

void init_PWM(void){
	TCCR2 = _BV(COM21) | _BV(WGM20) | _BV(CS20);	//Enable AD
	OCR2 = 0x80;
}

// Handles Output Compare and turns off Ultrasonic 
// waveform after five periods, about 0.125ms
SIGNAL (SIG_OUTPUT_COMPARE1A) 
{
	sendflag = 1;
}

// Handles incomming bytes on USART
SIGNAL (SIG_UART_RECV)
{
	unsigned char c = UDR;
	OCR2 = c;
	PORTD ^= _BV(PD7);	//Toggle green led
}

int main(void)
{	
	unsigned char val;
	
	cli();				// disable interrupt globaly
	init_UART();		// init USART
	init_port();		// init I/O
	init_timer();		// init timers
	init_ADC();
	init_PWM();
	sei();  			// enable interrupt globaly

	ADCSRA |= _BV(ADSC);	//Start conversion		
	
	for(;;)		//Run forever...
	{
		while(!sendflag);		//wait for trigger
		
		sendflag = 0;
		
		/* WAIT for ADconverter to finish */
		while( !(ADCSRA & _BV(ADIF)) );
			ADCSRA |= _BV(ADIF);
		
		ADCSRA |= _BV(ADSC);	//Start conversion	
		usart_putc(ADCH);
	
		PORTB = PORTB ^ 0x01;
	}
	return 0;
}

saddox
Inlägg: 132
Blev medlem: 2 januari 2005, 09:46:11
Ort: Karlstad
Kontakt:

Inlägg av saddox »

Nu är inte jag så slängd på C men får väl ta och bli.

Ok.. aha.. 13.. där det skulle in. Borde ju räcka i "slutlig" samplingsfrekvens.. hmm. vänta.. Nyquist börjar spöka... översta frekvensen blir alltså ca 4 kHz.. hmm..
Ska nog stoppa på ett filter på ingången.. för att undvika aliasing då kanske. Inte helt fel kanske.. Så man får så bra förutsättningar som möjligt att kräma ur saker å ting ur denna lilla mojäng.
Skriv svar