Hallo, ich hab ein kleines Problem mit PWM. Ich will ein Stimmgerät für meine Trompete bauen und will auch mit einem Piezo-Piepser einen Referenzton erzeugen nachdem ich dann meine Trompete stimmen kann. Dafür versuch ich nun ein Rechtecksignal zu generieren das ich dann auf meinen Piezo-Piepser loslasse. Folgedes Programm hab ich dazu geschrieben: #include <avr/io.h> #include <avr/interrupt.h> #include <stdint.h> void port_init(void) { PORTD = 0xFF; DDRD = 0xFF; } void timer1_init(void) { TCCR1A = 0x00; //Timer stoppen TCCR1B = 0x00; OCR1A=512; // Pulsbreite 50% High 50% Low TCCR1A = (1 << WGM11) | (1 << WGM10) | (1 << COM1A1); // nicht inv. 10Bit PWM TCCR1B = (1 << CS10) | (1<<CS11); // Counterfrequenz = Taktfrequenz (8MHz) / 64 } void init_devices(void) { cli(); //Alle Interrupts ausschalten port_init(); timer1_init(); } int main(void) { init_devices(); while(1); return(0); } So nun kurz zur Erklärung, ich setze alle Pins des Ports D als Ausgang. Dann initialisiere ich den PWM-Timer und setze die Werte für PWM also welche Pulsbreite das Signal haben soll. So das kompiliert auch und ich bekomm auch ein Rechtecksignal an PIN 19 meines Atmega32. Aber das hat laut meinem Oszi eine Freuenz von 7,6Hz. Ich dachte nun das sich die Frequenz anhand des oben stehenden Codes folgendermaßen berechnet: F-PWM = F-CPU(8Mhz) / 64 (durch Bit CS10 und CS11) / 2046 (durch WGM10 und WGM11 also 10Bit Counter) So das ergibt bei mir 61,09Hz. Wie oben geschrieben messe ich aber 7,6Hz. Irgendwo steckt da noch ein Faktor 8 drin. Nur leider weiß ich nicht wo. Mache ich irgendwo nen Denkfehler? Gruß Maruu
Hallo, könnte es sein, dass dein µC mit internem Quarz, das entspricht 1MHz, läuft, das könnte den Faktor 8 erklären.
@ sch_michael (Gast) >könnte es sein, dass dein µC mit internem Quarz, das entspricht 1MHz, >läuft, das könnte den Faktor 8 erklären. uCs haben keinen internen Quarz, nur interne RC-Oszillatoren. MFG Falk
Hallo, das könnte natürlich sehr gut sein. Bisher hab ich leider immer PIC's programmiert. Habt Ihr mir nen Tip welches Register ich wie beschreiben muss für nen Externen Quarz mit 8Mhz? Gruß Maruu
Hi, @ Düsentrieb: Danke für den Tip den Link kannte ich schon und auf dessen Basis werd ich wohl auch das Stimmgerät entwickeln, nur werd ich wohl den dort geposteten C-Code modifizieren und die Nulldurchgänge des Signals mit einem Comperator zählen. Den Referenzton wollte ich noch als Feature inbauen. Auch ein Metronom wäre noch schön. Naja alles noch Spielerei und ein nettes erstes Projekt für nen Atmel. Bisher hatte ich immer mit PIC's programmiert, da is die Doku für Assembler sehr gut siehe Sprut aber es gibt keine guten kostenlosen C-Compilier. Ab einer gewissen komplexität wird es aber mit Assembler schwer. Deshalb will ich für die Zukunft eher auf AVR setzen. Is zwar schade aber sooo unterschiedlich sind die beiden ja nicht. Gruß Maruu
@ Maruu ;-) (maruu) >programmiert. Habt Ihr mir nen Tip welches Register ich wie beschreiben >muss für nen Externen Quarz mit 8Mhz? AVR Fuses MFG Falk
Ahhh super, den Beitrag hab ich zu spät gesehen. Hab mir erst mal einen meiner 2 AVR's Ver-Fused den werd ich dann morgen (falls ich da schon nüchtern bin ;-) retten mit nem externen Takt. Jetzt funktionieren auch meine berechneten 61,1Hz. So nun hab ich noch eine letzte Frage. Ich will genau eine Frequenz von 440Hz erzeugen. Aber wie bitte bekomm ich das hin? Geht das überhaupt mit PWM? Gruß Maruu
Hallo, Du willst doch nor eine Tonfrequenz erzeugen? Im einfachsten Fall ist das ein Rechtecksignal mit Tastverhältnis 1:1. Schau mal vei den Timern nach CTC-Mode, der ist für sowas gedacht. Den Link zum passenden Tutorial hat sicher Falk parat. :) PS: Bei 8MHz sind genau 440Hz nicht möglich, bei Teiler 18182 kämen nur 439,9956Hz raus, bei Teiler 18181 wären es 440,0198Hz. Gruß aus Berlin Michael
@ Michael U. (amiga) >Den Link zum passenden Tutorial hat sicher Falk parat. :) Kann man sich auch ggf. selber suchen. http://www.mikrocontroller.net/articles/Spezial:Allpages AVR-Tutorial: Timer >PS: Bei 8MHz sind genau 440Hz nicht möglich, bei Teiler 18182 kämen nur >439,9956Hz raus, bei Teiler 18181 wären es 440,0198Hz. Karajan ist tot. Und nicht mal der hätte den Unterschied zwischen 440 und 4439,9956 Hzb gehört. ;-) MFG Falk
Hallo, danke euch Beiden für den Tipp. Das mit dem CTC scheint das passende zu sein. Hab mich mal ein bisschen eingelesen und folgendes Programm geschrieben:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <stdint.h> |
4 | |
5 | void Init_Timer_2(void) |
6 | {
|
7 | |
8 | //440,1408Hz
|
9 | TCCR2 = (1 << WGM21)|(1 << CS22)|(1 << COM20); //CTC-Modus, Teiler auf 64, Toggel des Pins D7 |
10 | OCR2 = 141; |
11 | }
|
12 | |
13 | int main (void) |
14 | {
|
15 | DDRD |= (1<<PD7); |
16 | sei(); |
17 | Init_Timer_2(); |
18 | |
19 | while(1); |
20 | }
|
Das liefert mir eine Frequenz von 440,1408Hz. Aber wieso? Ich hab einen 8Mhz Quarz dran. Dann teile ich durch 64 mit dem Prescaler. Also 8000000 / 64 = 125000 so nun noch durch den Wert der in OCR2 steht teilen: 125000 / 141 = 886,5248 Da für eine 1Hz ja 2 mal getoggelt werden muss muss ich den Wert noch durch 2 teilen: 886,5248 / 2 = 443,262 Hz So das sollte das Ergebnis sein das ich mit den obigen Einstellungen erwartet hab aber raus kommen 440,1...Hz. Mach ich da irgendwas falsch? Hat mein Quarz keine 8Mhz (drauf steht aber 8,000000b Mhz) oder woran liegt das? Gruß Maruu
Maruu ;-) wrote: > > 125000 / 141 = 886,5248 125000 / 142 Wenn der Timer von 0 bis 141 zählt, dann braucht er dazu 142 Zyklen. 125000 / 142 = 880,28 880,28 / 2 = 440.14
Ahhhhh jetzt wird es Tag ;-) Deshalb, hab mich schon gefragt woher das kommt. So nun noch ne kleine Frage, Michael U. hat oben geschrieben das ich nen Teiler von 18181 verwenden könnte. Durch das oben eingestellte Verhältnis hab ich ja nen Teiler von: 142*64*2 = 18176 Wie komm ich denn jetzt auf den Teiler 18181? Das OCR2 Register is ja nur 8bit groß da kann ich dann doch keine höhere genauigkeit mehr einstellen oder? Gruß Maruu
Maruu ;-) wrote: > Wie komm ich denn jetzt auf den Teiler 18181? Das OCR2 Register is ja > nur 8bit groß da kann ich dann doch keine höhere genauigkeit mehr > einstellen oder? Richtig. Aber der Timer 1 ist 16-bittig (Denke ich zumindest. Du hast ja nicht gesagt welchen Prozessor du benutzt) Du solltest dich aber fragen, ob dieses eine Zehntel Herz tatsächlich hörbar ist.
Hi, ich verwende den Atmega32. Stimmt der Timer1 is ja ein 16Bit Timer. Hab den jetzt auch verwendet. Da kann ich dann auch höhere Werte ins OCR Register schreiben. So für alle die es noch interessiert hier die Quellcode:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <stdint.h> |
4 | |
5 | void Init_Timer_1(void) |
6 | {
|
7 | |
8 | //440Hz
|
9 | //TCCR1A = (1 << COM1A0);
|
10 | //TCCR1B = (1 << WGM12)|(1 << CS10);
|
11 | //OCR1A = 9090;
|
12 | |
13 | //442Hz
|
14 | TCCR1A = (1 << COM1A0); |
15 | TCCR1B = (1 << WGM12)|(1 << CS10); |
16 | OCR1A = 9049; |
17 | }
|
18 | |
19 | int main (void) |
20 | {
|
21 | DDRD |= (1<<PD5); |
22 | sei(); |
23 | Init_Timer_1(); |
24 | |
25 | while(1); |
26 | }
|
Danke für eure Hilfe, damit ist der erste Teil schon mal geschafft. Gruß Maruu
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.