Proiectul este un acordor de chitara. Selectia unei corzi de acordat se face prin apasarea butonului corespunzator corzii. Dupa selectia microfonul va prelua sunetul si ii va testa frecventa cu frecventa de referinta a sunetului, urmand sa afiseze gradul de corectitudine prin aprinderea unuia dintre cele 3 leduri astfel:
Scopul proiectului este acela de a permite o acordare cat mai simpla a unei chitare.
In afara modulelor hardware din cadrul placutei de baza din prima etapa, se disting urmatoarele module:
Se disting 5 module software:
void correct_led()
{ PORTB |= (1<<PB1); PORTB &= ~(1<<PB0) & ~(1<<PB2); }
void lower_led()
{ PORTB |= (1<<PB0); PORTB &= ~(1<<PB1) & ~(1<<PB2); }
void higher_led()
{ PORTB |= (1<<PB2); PORTB &= ~(1<<PB0) & ~(1<<PB1); }
void err_led()
{ PORTB |= (1<<PB0) | (1<<PB2); PORTB &= ~(1<<PB1); }
int sel_but()
{ int b_sel = -1; int selected = 0; if (!(PINC & (1<<PC0))) { b_sel = 0; selected = 1; } if (!(PINC & (1<<PC1))) { if(selected) return -2; else { b_sel = 1; selected = 1; } } if (!(PINC & (1<<PC2))) { if(selected) return -2; else { b_sel = 2; selected = 1; } } if (!(PINC & (1<<PC3))) { if(selected) return -2; else { b_sel = 3; selected = 1; } } if (!(PINC & (1<<PC4))) { if(selected) return -2; else { b_sel = 4; selected = 1; } } if (!(PINC & (1<<PC5))) { if(selected) return -2; else { b_sel = 5; selected = 1; } } return b_sel; }
void ADC_init()
{ ADMUX = 0; ADMUX |= (1<<REFS0) | (1<<ADLAR); ADCSRA = 0; ADCSRA |= (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADATE); SFIOR &= ~(1<<ADTS0) & ~(1<<ADTS1) & ~(1<<ADTS2); ADCSRA |= (1<<ADEN); }
float ADC_get()
{ ADCSRA |= (1<<ADSC); loop_until_bit_is_set(ADCSRA,ADIF); return ADCH; }
void fourier(float *x)
{ long i,j,k,logN,le,le2; float *p, *q,t, ur, ui,arg,wr,wi,*p1r,*p1i,*p2r,*p2i,tr,ti; logN = (long)(log(16)/log(2.) + .5); for(i=2;i< 30;i+=2) { for(k=2, j=0;k<32;k<<=1) { if ( i & k ) j++; j <<=1; } if (i < j) { p = x + i; q = x + j; t = *p; *(p++) = *q; *(q++) = t; t = *p; *p = *q; *q = t; } } for (k = 0, le = 2; k<logN; k++) { le <<= 1; le2 = le >> 1; ur = 1.0; ui = 0.0; arg = M_PI/(le2>>1); wr = cos(arg); wi = -sin(arg); for(j=0;j<le2;j+=2) { p1r = x + j; p1i = p1r + 1; p2r = p1r + le2; p2i= p2r + 1; for(i=j;i<32;i+=le) { tr = *p2r * ur - *p2i * ui; ti = *p2r * ui + *p2i * ur; *p2r = *p1r - tr; *p2i = *p1i - ti; *p1r += tr; *p1i += ti; p1r += le; p1i += le; p2r += le; p2i += le; } tr = ur *wr - ui * wi; ui = ur * wi + ui * wr; ur = tr; } } }
Acordarea nu se face corespunzator deoarece nu s-a putut realiza extragerea corecta a frecventei din sirul rezultat in urma transformatei fourier.
Nu s-a putut finisa proiectul in lipsa unei metode corecte de a extrage frecventa din sirul intors de transformata fourier. Metoda recomandata intoarce intotdeauna o frecventa cu valoarea 0:
fourier(v); max = -100; maxi = 0; F_curent = F_ref[x]; for(i=0;i<16;i++)
if ( v[i] > max ) {max = v[i]; maxi = i; }
max = maxi * sampleRate/ transformLength;
if(max < F_curent +15 && max > F_curent -15)
correct_led();
else
if (max > F_curent) higher_led(); else lower_led();
Sampelul ales a fost de 16 valori de la ADC. A fost testata placuta si cu sampeluri mai mari (32,64,128) dar cu acelasi rezultat.
Arhiva cu surse si scheme: acordor_de_chitara.zip
Arhiva contine: