Alle Jahre wieder rieselt der Schnee leise auf Rudolf den rotnasigen
Weihnachtsbaum (oder so ähnlich)!
Für eine Weihnachtsbastelei (wie alle Jahre wieder) brauchte ich einen
"Melody-Player".
Mein bisherig verwendete Timer1 (welch Verschwendung), und den benötige
ich nun für anderes.
Also muß 8-Bit Timer0 herhalten. Zu meinem Erschrecken (ich habe mit dem
alten ATmega8 lange nichts gemacht) hat dieser keinen Compare-Match auf
Timer0. (sollte ich mich hier irren und ich bin blind durchs Datenblatt
gelatscht, bitte ich um Korrektur)
Damit der Melody-Player auf so ziemlich allen AVR's läuft habe ich das
nun im
8-Bit Overflow Modus
gelöst und hoffe, dass ich das nicht noch einmal machen muß (für welche
Bastelei auch immer).
Der Melody-Player wurde getestet auf:
ATtiny13, ATtiny2313, ATtiny44 / 84, ATtiny45 / 85, ATmega8, ATmega88,
ATmega168 und ATmega328p.
Die benutzbaren Taktfrequenzen sind:
4,8MHz; 8MHz; 9,6MHz, 16MHz
Der Melody-Player spielt einen String, der die zu spielenden Noten
enthält.
Dieser "Notenparser" versteht folgende Zeichen:
Buchstaben c d e f g a h sowie C D F G A gefolgt von einer numerischen
Ziffer.
Hierbei stellen die Buchstaben die zu spielende Note dar und die Ziffer
die Tonlänge. Die Großbuchstaben sind hierbei Cis, Dis, Fis, Gis, Ais
Bsp.
a2 : spielt eine halbe Note "a"
C4 : spielt eine viertelnote "C"
Eine Besonderheit ist (weil mir die Ziffern ausgegangen sind) die Ziffer
9. Diese spielt (abweichend von der sonstigen Notation) eine sechzehntel
Note.
Das + Zeichen erhöht die zu spielende Oktave, - Zeichen vermindert die
zu spielende Oktave.
Buchstabe "p" gefolgt von einer Ziffer fügt eine Pause mit der
Notenlänge der Ziffer ein.
p2 : fügt eine Pause mit der Dauer einer halben Note ein.
------------------------------------------------------------
Die Frequenzen wurden mittels eines Libre-Office Calc Sheets ermittelt.
Hier würde ich für eine Rückmeldung dankbar sein, ob dieses auch in
Excel funktioniert, besonders die Berechnung der Abweichung von der
gewünschten Frequenz.
Mit dieser Tabellenkalkulation kann der Melody-Player an andere
CPU-Frequenzen angepasst werden.
Innerhalb des Headers toene_melodie.h ist die Angabe zu machen, an
welchen Portpin der Lautsprecher angeschlossen ist:
Aktuell ist hier Portpin PB4 (für die 8-poligen ATtinys) eingestellt.
toene_melodie.c beinhaltet eine globale Variable:
volatile uint8_t sound
Diese Variable wird im Interrupt ausgewertet. Mit ihr kann die
Frequenzerzeugung an- oder ausgeschaltet werden:
sound = 0; // Ton aus
sound = 1; // Ton an
uint16_t playtempo= 5;
Diese Variable bestimmt die grundsätzliche Geschwindigkeit, mit der ein
Notenstring abgespielt wird.
Makro von toene_melodie.h
-------------------------
speaker_init();
Initialisiert den im Kopf der Datei angegebenen Portpin als Ausgang
Funktionen von toene_melodie.c
------------------------------
void timer0_init(void);
Initialisiert den Timer0 als 8-Bit
void playnote(char note);
schaltet den Ton ein und spielt die angegebene Note solange, bis sie
durch
sound= 0;
wieder abgeschaltet wird
void playstring(const unsigned char* const s);
spielt einen Notenstring, der im Codespeicher abgelegt sein muß.
Bsp.
Cool :)
hatte sowas ähnliches angefangen aber noch auf einem quicker and
dirtiger Level. Bei sinds noch zwei 16 Bit Wertpaare - ebenfalls Tonhöhe
und Dauer.
War auch schon auf den Trichter gekommen, das wie du es schon gemacht
hast und sinnvoll ist auf die Notendarstellung zu ändern.
Ich hab bei mir noch vorgesehen, über UART neue Folgen reinspielen zu
können.
Finde ich 1ne nice Idee mit dem + und - zur Oktavenänderung :)
Jasson J. schrieb:> Ich hab bei mir noch vorgesehen, über UART neue Folgen reinspielen zu> können.
kann man gerne machen, allerdings:
Hierfür braucht es einen RAM-Puffer aus dem abgespielt werden kann und
zumindest bei einem ATtiny13 sieht das sehr düster aus.
Allerdings sollte das überhaupt kein Problem für die anderen AVR's sein,
hier ist beim Array dann schlicht das "PROGMEM" weg zu lassen.
Hmmm, und wenn man schon so etwas macht, kann man den eingelesenen
String auch gleich in das interne EEPROM packen, aus dem der
Melodie-Player dann abspielt.
Das überlasse ich dann gerne den Bastlern, für meinen "Verwendungszweck"
benötige ich das nicht !
Danke für das Feedback
Ralph,
wie hast du das gelöst, wenn zwei gleiche Noten hinter einander folgen?
Wenn man für eine Note stumpf eine bestimmte Frequenz für eine gewisse
Dauer erzeugt und danach die selbe nochmal würde man das auf unseren
elektronischen Klimperkästen ja als einzelne längere Note wahrnehmen.
Bei richtigen Instrumenten hat man ja zum einen immer den Effekt, dass
der Anschlag abklingt oder eben die minimale Pause zwischen einer
vorrausgegangenen Note und dem neuen Anschlag.
Mir würde einfallen generisch von der Notendauer einen Prozentsatz als
"tot" zu definieren.
Prozentsatz ist imho nicht richtig - eher ein kurze konstante Zeit (so
lange, wie man halt z.B. bei einer Flöte zum Umgreifen braucht) - in
meiner Klingel hänge ich einfach an jeden Ton ein 20ms Delay.
Grüße,
Egberto
Jasson J. schrieb:> Wenn man für eine Note stumpf eine bestimmte Frequenz für eine gewisse> Dauer erzeugt und danach die selbe nochmal würde man das auf unseren> elektronischen Klimperkästen ja als einzelne längere Note wahrnehmen.Jasson J. schrieb:> Mir würde einfallen generisch von der Notendauer einen Prozentsatz als> "tot" zu definieren.
Nun bin ich leider kein Musiker und habe auch leider niemals ein
Instrument gelernt (das ist etwas, das mir in meinem Leben wirklich
fehlt). Von daher kann ich nur ansatzweise erahnen was du meinst. Bei
mir reicht es nur dafür aus dem Musikunterricht von vor fast 50 Jahren
zum Lesen von Noten, was ein c,d etc. oder ein CIS ist... und was
Achtel- , Viertel-, Halbenoten sind.
Von daher kann ich nur aus einem einfachen Notenblatt eben diesen
Notenstring erzeugen.
Abgespielt wird er bspw. durch ein c2.
Das "c" startet die Frequenz und stellt den Ton an. Die "2" sagt wie
lange er an ist und stellt diesen Ton wieder aus. Damit 2 gleiche Noten
als solche erkannt werden gibt es eine (immer gleiche) Zeit während der
Lautsprecher aus ist. Vllt. meinst du das hier:
1
void tonlen(int w)
2
{
3
int cx;
4
5
w = w*100;
6
for (cx= 0; cx< w; cx++) { _delay_us(100); }
7
sound= 0;
8
_delay_ms(30);
9
}
Wird tonlen aufgerufen (vom Stringparser), bestimmt diese Funktion wie
Lange der Ton eingeschaltet ist. Nach Ablauf dieser Zeit ist der Ton für
30ms aus bevor der nächste Ton wieder einsetzen kann.
So, jetzt habe ich mal auf die allerschnellste Art etwas "gecodet", habe
aber kein Equipment hier um das zu testen.
In den Parser kann ich noch einen weiteren Buchstaben einführen, der
interpretiert wird, sagen wir ein "j" (für mich halt so ähnlich wie ein
Jitter - hey, ich sagte so ähnlich).
Mit diesem "j" kann man dann das "30ms Ton aus" am Ende einer Notendauer
abschalten und einen direkten Notenübergang von einer Note zur anderen
vornehmen.
Leider (oder für mich besser) habe ich Urlaub und kann das erst in ca. 1
1/2 Wochen hier einstellen. Allerdings sollte eine solche Veränderung
von jedem auch selbst durchgeführt werden können. : - )
Ich weiß nicht, wieviele Versionen von Quäkern ich in den letzten 25
Jahren gebaut habe. Die ersten mit PIC, dann AVR AT90 und mittlerweile
ATtiny.
Alle paar Jahre wieder braucht irgendjemand einen kleinen Quälgeist. In
der letzten Interation wurde ein ATtiny412 verbaut, der kann sowohl PWM
als auch 10bit-DAC.
Achtung kommerziell:
http://harerod.de/applications_ger.html#TQ412_melody
+ + +
Weil die Frage der Unterscheidbarkeit von aufeinanderfolgenden gleichen
Tönen aufkam: ein echtes Instrument hat u.a. einen Anschlag. Beim
PWM-Quäker kann man sich behelfen, indem man eine ganz kurze Pause
zwischen den Tönen einfügt, das Ohr ist da sehr aufmerksam.