© Harry Broeders.
Deze pagina is bestemd voor studenten van de Haagse Hogeschool - Academie voor Technology, Innovation & Society Delft groep EQ1.2.
De AVR STK500 systemen van de opleiding Elektrotechniek aan de Academie voor Technology, Innovation & Society Delft zijn uitgerust met een luidspreker die aangestuurd kan worden met pin PD5 = OC1A van de ATmega32. Maak een muziek-generator waarmee een (monofoon) melodietje via de luidspreker ten gehore kan worden gebracht.
Muziek bestaat uit tonen. Elke toon heeft zijn eigen frequentie = toonhoogte. De frequentie van de zogenaamde kamertoon (A') is 440Hz. Een octaaf bestaat uit 12 noten. De frequentie van een noot bij een gelijkzwevende stemming is exact 21/12 = 1,05946309... hoger dan de frequentie van de vorige noot. De twaalf noten heten: A, AIS, B, C, CIS, D, DIS, E, F, FIS, G en GIS. Na 12 noten begint de volgende octaaf (met weer opnieuw 12 noten). De frequentie van de A'', die een octaaf hoger is dan A', is dus exact (21/12)12 = 2 maal zo hoog als de A'.
De file noten@3686000.h bevat een groot
aantal #define
's waar aan de naam van elke noot een waarde wordt
toegekend. Deze waarde komt overeen met het aantal perioden - 1 van de
klokfrequentiue van de ATmega32 (3.686000 MHz) dat een halve periode
van die betreffende toon duurt. Dit is dus de waarde die in het
OCR1A
register geladen moet worden als Timer/Counter1 in de
CTC mode wordt gebruikt. Telkens als de timer gereset wordt moet pin PD5
geïnverteerd worden.
De kamertoon A' is in C gedefinieerd als:
#define A1 4188
Even narekenen: De frequentie van de A' is 440Hz. Een periode duurt dus 1/440 = 2272,72... µs. Dit zijn 2272,72 * 3,686 = 8377,27 perioden van de clock als de ATmega32 op 3,686 MHz draait. Een halve periode van de A' duurt dus 8377,27/2 = 4188,64 perioden van de clock van de ATmega32. Omdat we alleen maar hele perioden van de clock van de ATmega32 kunnen tellen ronden we dit af tot 4189. In de tabel staat deze waarde - 1 = 4188. Klopt dus :-)
De muziek die de muziek-generator gaat maken is exact in de maat. Dat wil zegen dat elke noot exact even lang (een "tel") gespeeld wordt. Bij een tijdsduur van 0,25 s per noot klinkt de muziek heel redelijk. Je kunt Timer/Counter0 gebruiken om 0,25 s af te tellen.
De muziek die moet worden gespeeld wordt in een tabel in het geheugen opgeslagen. Een tabel die het herkenningsmuziekje van de Adams Family definieerd ziet er als volgt buit:
/* ADDAMS FAMILY */
uint16_t muziekTabel[] = {
F1,G1,A1,AIS1,AIS1,R,R,R,R,
G1,A1,B1,C2,C2,R,R,R,R,
G1,A1,B1,C2,C2,G1,A1,B1,C2,C2,F1,G1,A1,AIS1,AIS1,R,R,R,R,R,R,
AIS2,D3,AIS2,G2,DIS2,C3,R,
GIS2,A2,C2,A2,F2,D2,AIS2,R,
F2,AIS2,D3,AIS2,G2,DIS2,C3,R,
AIS2,A2,F2,G2,A2,AIS2,AIS2,R,
F2,AIS2,D3,AIS2,G2,DIS2,C3,R,
GIS2,A2,C2,A2,F2,D2,AIS2,R,
F2,AIS2,D3,AIS2,G2,DIS2,C3,R,
AIS2,A2,F2,G2,A2,AIS2,AIS2,F1,G1,A1,AIS1,AIS1,R,R,R,R,
G1,A1,B1,C2,R,R,R,R,
G1,A1,B1,C2,C2,G1,A1,B1,C2,C2,F1,G1,A1,AIS1,AIS1,R,R,R,R,R,R,
AIS2,D3,AIS2,G2,AIS1,C3,GIS2,A2,C3,A2,F2,D2,AIS2,R,
F2,AIS2,D3,AIS2,G2,AIS1,C3,R,
AIS2,A2,A2,F2,F2,G2,G2,A2,A2,AIS2,AIS2,S
};
Om de muziek uit de tabel te kunnen spelen moet de muziekgenerator dus eerst
0,25 seconde noot F1
opwekken, daarna 0,25 seconde noot
G1
enz. Naast de constanten voor de noten zijn nog drie
speciale constanten gedefinieerd die in de muziek tabel gebruikt kunnen worden.
Dit zijn:
#define H 1 /* herhaal */
#define R 2 /* rust */
#define S 3 /* stop */
De betekenis van deze speciale labels staat in het commentaar achter de constante definitie. Let op: De muziektabel wordt nu afgesloten door een S (stop). Als deze S vervangen wordt door een H moet het muziekje continue blijven spelen!
Tijdens de tel rust kun je PD5 het beste hoog maken omdat anders (als je
PD5 tijdens een rust laag maakt) aan het einde van de rust een vervelende
tik uit de luidspreker komt. Als je helemaal geen tikken op de speaker wilt
horen moet je het OCR1A
register alleen laden als er net een
Compare Match is geweest.
Maak een stappenplan en maak voordat je een (deel)programma gaat coderen eerst een ontwerp op papier. De practicumdocent zal naar dit stappenplan en ontwerp vragen bij het aftekenen van je opdracht.
Ben je het "Addams Family" muziekje ook een beetje zat? Probeer dan deze eens:
/* POPCORN */
uint16_t muziekTabel[] = {
A2,G2,A2,E2,C2,E2,A1,R, A2,G2,A2,E2,C2,E2,A1,R, A2,B2,C3,B2,C3,A2,B2,A2,B2,G2,A2,G2,A2,F2,A2,R, A2,G2,A2,E2,C2,E2,A1,R, A2,G2,A2,E2,C2,E2,A1,R, A2,B2,C3,B2,C3,A2,B2,A2,B2,G2,A2,G2,A2,B2,C3,R, E3,D3,E3,C3,G2,C3,E2,R, E3,D3,E3,C3,G2,C3,E2,R, E3,FIS3,G3,FIS3,G3,E3,FIS3,E3,FIS3,D3,E3,D3,E3,C3,E3,R, E3,D3,E3,C3,G2,C3,E2,R, E3,D3,E3,C3,G2,C3,E2,R, E3,FIS3,G3,FIS3,G3,E3,FIS3,E3,FIS3,D3,E3,D3,E3,C3,E3,R, A2,G2,A2,E2,C2,E2,A1,R, A2,G2,A2,E2,C2,E2,A1,R, A2,B2,C3,B2,C3,A2,B2,A2,B2,G2,A2,G2,A2,F2,A2,R, A2,G2,A2,E2,C2,E2,A1,R, A2,G2,A2,E2,C2,E2,A1,R, A2,B2,C3,B2,C3,A2,B2,A2,B2,G2,A2,G2,B2,G2,C3,C3,C3,S};
Of deze:
/* SCOOP */
uint16_t muziekTabel[] = {
C2,C2,R,R, C2,C2,A1,B1,B1,R, B1,B1,B1,G1,A1,G1,A1,A1,R,R, A1,A1,C2,A1,A1,R, A1,A1,A1,G1,A1,G1, C2,C2,R,R, C2,C2,A1,B1,B1,R, B1,B1,B1,G1,A1,G1,A1,A1,R,R, A1,A1,C2,A1,A1,R,A1,A1,R,R,R,R,H
};
Wie opent de eerste website voor AVR muziek? (Weer eens wat anders dan MP3 of beltoontjes ;-).
Hier is een test tabel:
/* TEST */
uint16_t muziekTabel[] = {
A1,A1,A1,R,R,R, C0,CIS0,D0,DIS0,E0,F0,FIS0,G0,GIS0,A0,AIS0,B0, C1,CIS1,D1,DIS1,E1,F1,FIS1,G1,GIS1,A1,AIS1,B1, C2,CIS2,D2,DIS2,E2,F2,FIS2,G2,GIS2,A2,AIS2,B2, C3,CIS3,D3,DIS3,E3,F3,FIS3,G3,GIS3,A3,AIS3,B3, R,R,R,A1,A1,A1,S};