-
Frequenz beim Beeper
Hi,
auh ich hab jetzt das M32 Erweiterungsboard. Nun habe ich eine Frage zum Beeper:
Man kann da Tonhöhen von 0-255 eingeben. Wie kann man nun rausfinden, welche Frequenz diese Töne in Wirklichkeit haben? Ich würde den RP6 nämlich gern ein Lied singen lassen, zu dem ich die Noten auf Papier hab. (z.B. a' = 440hz). Allerdings weiß ich nicht, was ich für eine Zahl eingeben muss, damit ich 440hz bekomme.
lg
Michi
-
Frequenzen kannst du mit einem Frequenzmesser, mit einem Oszilloskop und teilweiße mit DMM messen. Wenn du einen µC übrig hast könntest du ein Porgramm schreiben, der die Frequenz misst und dann anzeigt.
MfG Hannes
-
Hallo
Gleich vorweg: Ich bin ziemlich unmusikalisch, ein mäsiger Mathematiker und ich besitze kein M32. Aber ich kann versuchen, dir (mehr oder weniger gut) die Funktion von beep() erklären:
Basis ist der Timer2 der im CTC-Mode mit Perscaler /256 betrieben wird. Die Funktion des OC2-Pins steht dabei auf togglen:
Code:
void beep(uint8_t pitch, uint16_t time)
{
controlStatus.beep = true;
sound_timer = time;
OCR2 = 255-pitch;
// CTC-Mode, toggle OC2, prescaler /256
TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS22) | (1 << CS21);
}
(Die Funktion beep() aus der Datei RP6ControlLib.c)
Der Prescaler teilt den Kontrollertakt und erzeugt den Countertakt. Bei jedem Countertakt zählt der Counter das Zählregister TCNT2 um einen Schritt weiter. Wenn das Zählregister gleich dem Wert im OCR2-Register ist, wird der Ausgang OC2 (an dem der Lautsprecher angeschlossen ist) umgeschaltet und das Zählregister startet wieder bei 0. Wenn wir uns nun auf die Formeln stürzen, müssen wir noch beachten, dass eine Schwingung aus zwei Counterdurchläufen besteht, der OC2-Pin also zweimal umgeschaltet werden muss und dass der maximale Wert für OCR2 255 ist (Timer2 hat 8 Bit):
Höchste Frequenz bei OCR2=1:
16000000MHz/256 Prescaler/2 Halbwellen=31250 Hz
Tiefste Frequenz bei OCR2=255:
16000000MHz/256 Prescaler/2 Halbwellen/255 Countertakte= ca. 120 Hz
Berechnung des OCR2-Wertes aus der gewünschten Frequenz des Tones:
16000000MHz/256 Prescaler/2 Halbwellen/ Tonfrequenz ergibt für den Kammerton "A" 31250Hz/440Hz ca. 71
Da die beep()-Funktion den Parameter nicht direkt ins OCR2-Register schreibt, müssen wir den Parameter noch anpassen:
beep(255-(31250/440), dauer)
(Keine Gewähr für diese Berechnung;)
Gruß
mic
-
Hallo!
@ RobotMichi
Musik ist nur mein Hobby, weiss ich aber sicher, dass die benachbarte Töne in einer Oktave in im Code skizziertem Verhältniss zueinander sind.
Daraus ergibt sich z.B. für a´= 440 Hz ais´= 446,... also rund 466 Hz usw.
Wahrscheinlich weiss du es... :)
MfG
Code:
12
__ _____
Ton1 \ /
----- = \ / 2 = 1,059463094...
Ton2 \/
-
Hallo RobotMichi,
ich habe dies für die M32 herausgefunden:
H - 2
c - 16
cis - 30
d - 42
dis - 54
e - 65
f - 76
fis - 86
g - 96
gis - 105
a - 113
ais - 121
h - 128
C1 - 136
Cis1 - 142
D1 - 149
Dis1 - 155
E1 - 160
F1 - 166
Fis1 - 171
G1 - 175
Gis1 - 180
A1 - 184
Ais1 - 188
H1 - 192
C2 - 195
Cis2 - 199
D2 - 202
Dis2 - 205
E2 - 208
F2 - 210
Fis2 - 213
G2 - 215
Gis2 - 217
A2 - 219
Ais2 - 221
H2 - 223
C3 - 225
Cis3 - 227
D3 - 228
Dis3 - 230
E3 - 231
F3 - 233
Fis3 - 234
G3 - 235
Gis3 - 236
A3 - 237
Ais3 - 238
H3 - 239
Höhere Töne sind nicht mehr genau reproduzierbar.
Gruß Dirk
-
Hallo
Zur Einstimmung erstmal ein kleines Video:
Bild hier
http://www.youtube.com/watch?v=a60aLP9_1_A
Mein Jukebox-Speaker hängt an SCL, die Frequenzen werden wie beim M32 mit dem Timer2 erzeugt und am OC2 ausgegeben (die IR-COMM-LEDs blinken im Takt). Bei der Ausgabe wird der Pegel an OC2 eingelesen und auf den SCL-Pin kopiert (der selbe Trick funktioniert ja auch am TXD):
Code:
// Tonerzeugung am RP6-Base mit beep() aus der M32-Library 9.1.2010 mic
// Der Speaker hängt an PC0(SCL)
// https://www.roboternetz.de/phpBB2/viewtopic.php?t=52013
#define ton_c 255-(15625/264)
#define ton_d 255-(15625/297)
#define ton_e 255-(15625/330)
#define ton_f 255-(15625/352)
#define ton_g 255-(15625/396)
#define ton_a 255-(15625/440)
#define ton_h 255-(15625/495)
#define ton_c1 255-(15625/528)
#define ganzton 400
#include "RP6RobotBaseLib.h"
void beep(uint8_t pitch, uint16_t time) // aus der Lib des M32
{
//controlStatus.beep = true;
//sound_timer = time;
OCR2 = 255-pitch;
// CTC-Mode, toggle OC2, prescaler /256
TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS22) | (1 << CS21);
setStopwatch1(0);
DDRD |= (1<<PD7); // OC2-Pin auf Ausgang für Timer2 ;)
while(getStopwatch1()<time)
{
if(PIND & (1<<PD7)) PORTC |= 1; else PORTC &= ~1; // SCL mit OC2 togglen ;)
}
TCCR2 = 0; // Ton aus
DDRD &= ~(1<<PD7); // OC2-Pin auf Eingang ;)
PORTD &= ~(1<<PD7); // damit die IR-Comm-LED nicht durchbrennt
PORTC &= ~1; // Lautsprecher aus
mSleep(ganzton/10); // Trennung zwischen den Tönen
}
int main(void)
{
initRobotBase();
DDRC |= 1; // SCL auf Ausgang und Low Der Speaker
PORTC &= ~1;
DDRD &= ~(1<<PD7); // OC2-Pin auf Eingang
PORTD &= ~(1<<PD7); // ohne PullUp
startStopwatch1();
beep(ton_c, ganzton); // Tonleiter rauf
beep(ton_d, ganzton);
beep(ton_e, ganzton);
beep(ton_f, ganzton);
beep(ton_g, ganzton);
beep(ton_a, ganzton);
beep(ton_h, ganzton);
beep(ton_c1, ganzton);
mSleep(1000);
beep(ton_c1, ganzton/2); // und wieder runter
beep(ton_h, ganzton/2);
beep(ton_a, ganzton/2);
beep(ton_g, ganzton/2);
beep(ton_f, ganzton/2);
beep(ton_e, ganzton/2);
beep(ton_d, ganzton/2);
beep(ton_c, ganzton/2);
mSleep(2000);
while(1)
{
//Ode an die Freude (http://www.doktus.de/dok/25443/ode-an-die-freude.html)
beep(ton_e, ganzton);
beep(ton_e, ganzton);
beep(ton_f, ganzton);
beep(ton_g, ganzton);
beep(ton_g, ganzton);
beep(ton_f, ganzton);
beep(ton_e, ganzton);
beep(ton_d, ganzton);
beep(ton_c, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton);
beep(ton_e, ganzton+ganzton/2);
beep(ton_d, ganzton/2);
beep(ton_d, ganzton*2);
beep(ton_e, ganzton);
beep(ton_e, ganzton);
beep(ton_f, ganzton);
beep(ton_g, ganzton);
beep(ton_g, ganzton);
beep(ton_f, ganzton);
beep(ton_e, ganzton);
beep(ton_d, ganzton);
beep(ton_c, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton);
beep(ton_d, ganzton+ganzton/2);
beep(ton_c, ganzton/2);
beep(ton_c, ganzton*2);
beep(ton_d, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton/2);
beep(ton_f, ganzton/2);
beep(ton_e, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton/2);
beep(ton_f, ganzton/2);
beep(ton_e, ganzton);
beep(ton_d, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
mSleep(ganzton*2);
beep(ton_e, ganzton);
beep(ton_e, ganzton);
beep(ton_f, ganzton);
beep(ton_g, ganzton);
beep(ton_g, ganzton);
beep(ton_f, ganzton);
beep(ton_e, ganzton);
beep(ton_d, ganzton);
beep(ton_c, ganzton);
beep(ton_c, ganzton);
beep(ton_d, ganzton);
beep(ton_e, ganzton);
beep(ton_d, ganzton+ganzton/2);
beep(ton_c, ganzton/2);
beep(ton_c, ganzton*2);
mSleep(2000);
}
return(0);
}
Die Formel habe ich an die 8MHz des Base angepasst. Warum die Stopwatch() gelegentlich "stolpert" habe ich noch nicht rausbekommen, aber als Demo scheint mir das schon recht nett :)
@Dirk: Wie hast du deine Werte für die beep()-Funktion ermittelt?
Gruß
mic
[Edit]
Lautsprecher aus nach beep()
-
@radbruch:
Pitch = 255 - (16000000 / 256 / Tonfrequenz / 2)
Für "Tonfrequenz" habe ich die temperierte Stimmung genommen.
Gruß Dirk
-
Hallo Dirk
Na wunderbar. Dann hätte ich mir das ja auch alles ersparen können, wenn du die Formel schon hast ;)
Gruß
mic
-
Übrigens, Leute:
Wer auch die RP6CCPRO M128 "singen" lassen will:
Pitch = 14745600 / 64 / Tonfrequenz / 2
Gruß Dirk
P.S.: Die klingt auch wesentlich besser und schafft 7,5 Oktaven.
-
Habe gerade überlegt ob man mit dem M32 auch Wave Klänge wiedergeben könnte. Über beep könnte man das Wave in kurze 1 ms Happen verteilen, den durchschnittswert der Frequenz während der milisekunde ermitteln und einen passenden beep für 1 ms abspielen. Aber bestimmt gibs eh schon eine wave funktion, oder?