AVR-baserad stämapparat

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
BN
Inlägg: 14
Blev medlem: 10 oktober 2005, 16:50:34
Ort: Göteborg

AVR-baserad stämapparat

Inlägg av BN »

Jag har länge tänkt att bygga mig en egen stämapparat för att få en pryl som fungerar på det sätt jag själv vill. Jag hittade det här AVR-programmet för ett tag sedan och tänkte att jag skulle utgå ifrån det och anpassa det efter mina önskemål. http://www.myplace.nu/avr/gtuner/gtuner.c

Jag är ganska grön när det gäller mikroprocessorprogrammering och kan, trots många funderingsförsök, inte fatta hur programmet räknar ut vilken frekvens AVR:en får in.

Skulle någon vänlig själ kunna översätta algoritmen för samplingen till svenska och förklara lite hur det fungerar? Det skulle underlätta en del...

//BN
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

En kort sammanfattning:

Programmet användet timer0 (overflow interrupt) som tidsreferens (här: 172.8 kHz). Sedan räknar den tiden det tar för din mätpinne (I/O) att gå från låg till hög, d.v.s mäter tiden för 32 perioder med tidsreferensen (timern).
Överallt finns det tester för att avbryta om det uppenbart är ett helt galet mätvärde.

Sedan kommer det magiska med siffrorna.
Ett snitt dras ur de 32 ackumulerade periodtiderna. Därefter jämförs de med tabellerna som deklareras i början av programmet.
Först letar den upp vilken sträng som ligger närms till hands för frekvenen i fråga, sedan kollar den vilken ton du försöker spela, om det är en exakt match eller bara nästan.

Den kan alltså inte kolla vilken sträng du spelar på, det krävs betydligt mer sofistikerade algoritmer för det (som inte en AVR pallar med realtid). Däremot är den (förhoppningsvis) bra på att gissa vilken ton du försöker spela. Om du kopplar till lite fler LED kan du nog lätt visa vilken ton som matchas närmst. Du bör även lätt kunna lägga till fler grader av frekvensavvikelse om så önskas.
BN
Inlägg: 14
Blev medlem: 10 oktober 2005, 16:50:34
Ort: Göteborg

Inlägg av BN »

Tackar ödmjukast för hjälpen!

Nu tror jag att jag förstår hur det fungerar. Jag missade att man faktiskt får periodtiden i "pinne_låg till pinne_hög"-övergången. Jag var helt insnöad på att man skulle räkna hur många övergångar/pulser man skulle få under en fördefinierad tid, även om det så här i efterhand förefaller mycket smartare att göra på det andra sättet.

Tack än en gång för hjälpen!

En liten fråga till dock:
I detta kodavsnitt

Kod: Markera allt

// sample loop
		
		for (i=0;i<32;i++)
		{
			while (bit_is_set(PINB,1))		// ignore hi->lo edge transitions
				if (count_hi > 80)			// skip if no edge is seen within
					break;					// a reasonable time


		}
Kommer break:en avbryta exekveringen av while-satsen eller for-satsen?

//BN
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg av JJ »

Citat ur Microsofts kompilatordokumentation:

The break keyword terminates the smallest enclosing do, for, switch, or while statement in which it appears.
Användarvisningsbild
JimmyAndersson
Inlägg: 26593
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

En annan fråga på samma ämne, dvs frekvensräkning:

Låt säga att man har två tongeneraturer som ger två olika frekvenser. Dessa är ihopkopplade till *en* utgång.
Hur gör man för att bestämma/läsa av dessa frekvenser?
Seven11
Inlägg: 547
Blev medlem: 13 maj 2004, 23:43:33

Inlägg av Seven11 »

FFT kan användas för det.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Jag tänkte också förslå FFT, men det kanske inte riktigt funkar på en 2323:a?!
Jimmy: är det någon specifik applikation du syftar på?! Gäller det t.ex. DTMF-avkodning så finns det ju andra sätt... känner man till vilka möjliga frekvenser man kan få in (som med DTMF) så sätter man enklast upp ett bandpassfilter för varje tänkbar ton och kollar var man har signal..
Användarvisningsbild
JimmyAndersson
Inlägg: 26593
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

"Jimmy: är det någon specifik applikation du syftar på?!"

Nä, jag var mest nyfiken på teorin om hur man gör. Men jag har en idé om ett framtida projekt där jag behöver läsa av frekvenserna från en insignal som består av 3-4 samtidiga toner från ett instrumet.

FFT var en bra idé. Kräver visserligen ganska mycket "räknekapacitet" av både mig och någon processor. Det finns ju lite olika FFT-algoritmer, men jag vet inte om någon 8-bitars PIC-krets på 40MHz skulle orka någon sådan algoritm och mata ut frekvenserna på någon utgång (seriellt) samtidigt.

Med tanke på att jag bygger mycket ljud-prylar så borde jag verkligen lära mig att programmera DSP... :)


Nu tänker jag kanske inte tillräckligt "stort" men:
DTMF-standarden kräver att det är en skillnad i volym mellan de tonerna som spelas samtidigt. Sedan bygger det ju på att dessa toner är kända. Det innebär att det *måste* vara fler än en ton som avkodas för att man ska kunna använda DTMF.

Skulle Goertzel's algorithm fungera på flera samtidiga frekvenser som har lika hög amplitud? Den tycker jag är *betydligt* lättare än FFT, som jag knappt kan alls. :)


Det här med bandpassfilter gav mig en idé. Man behöver då ingen FFT eller Goertzel-algorithm för att separera frekvenserna: Man sätter ett bandpassfilter för varje möjlig frekvens. Med "lite" elektronik och D/A-omvandlare kopplat till en PIC kan man då få en 1a eller 0a för varje frekvens. T.ex:

Kod: Markera allt

Möjliga toner: G F E D C
               0 0 0 0 1  = Tonen C spelas
               0 0 0 1 0  = Tonen D spelas
               0 0 0 1 1  = Tonerna C och D spelas samtidigt.
               osv..
D/A-omvandlaren ger ju förstås en analog signal in till PIC-kretsen, men visar man detta binärt så borde det bli som i tabellen ovan.

edit: Glömde skriva att varje utgång på bandpassfiltren kopplas till varsin ingång på D/A-omvandlaren.


Förstår ni hur jag menar?
Det borde väl fungera?
Skriv svar