Hallo, ich möchte ohne fast pwm einen 440Hz(ungefähr) Dauerton ausgeben. verwende einen avr-8bit mit 16mhz So sieht mein versuch aus: https://gist.github.com/anonymous/2a6c619f6a1f27f41a94e3f9bc924f6e Stimmt die Berechnung bzw. der Code oder bin ich auf dem komplett falschen Weg? OCR1A = (16000000 2 1 / 440) - 1; //mit prescale 1 Hört sich irgendwie nicht nach 440 Hz, wie auf YouTube an. Danke
Hi
>(16000000 2 1 / 440) - 1
Was soll das bedeuten?
MfG Spess
spess53 schrieb: > Was soll das bedeuten? Dass er ein Opfer des Nichtlesens der Bedienungsanleitung geworden ist:
1 | OCR1A = (16000000 / 2 / 1 / 440) - 1; //mit prescale 1 |
Andreas D. schrieb: > verwende einen avr-8bit mit 16mhz Sicher? CLKDIV? Interner Oszillator? > Hört sich irgendwie nicht nach 440 Hz, wie auf YouTube an. Sondern? Was sagt die "Stimmgerät"-APP vom Handy?
:
Bearbeitet durch Moderator
Du hast vergessen, anzugeben, welchem Mikrocontroller du verwendest. Deine Formel ergibt einen Wert von ca 18.000 also muss der Timer ein 16bit Timer sein. Lass uns mal annehmen, dass dies der Fall ist. Mir ist aufgefallen, dass du TCCR1A und die WGM Bits nicht verwendest, daher arbeitet der Timer in "Normal" Modus, so daß er immer von 0 bis 0xFFFF zählt. Was genau willst du eigentlich mti deinen beiden Interrupt-Routinen erreichen und welcher Modus erfüllt deine Anforderung?
Beitrag #5026250 wurde von einem Moderator gelöscht.
Beitrag #5026257 wurde von einem Moderator gelöscht.
Andreas D. schrieb: > Hallo, > ich möchte ohne fast pwm einen 440Hz(ungefähr) Dauerton ausgeben. > verwende einen avr-8bit mit 16mhz Ich als Arduino-Programmierer schreibe zum Erzeugen einer Rechteckfrequenz im Audiobereich für so etwas einfach nur:
1 | tone(8,440); |
Und es läuft. Egal ob 8-bit AVR-Controller, oder ein 32-Bitter, der von der Arduino-IDE unterstützt wird. Der erste Parameter der tone() Funktion gibt den Pin (nach Arduino-Zählweise) an, der zweite Parameter die gewünschte Frequenz). Und wenn der Dauerton wieder stoppen soll, wäre er Befehl dafür:
1 | noTone(); |
Kein Herumrechnen, keine manuelle Timerprogrammierung von internen Registern. Es hat auch seine Vorteile, wenn die IDE bereits umfangreiche Core-Libraries für typische Controller-Aufgaben mitbringt. Kein Wunder, dass Arduino in den letzten 10 Jahren bei Hobbybastlern so beliebt geworden ist. Aber wenn man keine so komfortablen Library-Funktionen zur Verfügung hat, es geht natürlich mit AVR-GCC auch komplizierter (sogar auch in der Arduino-IDE, wenn man möchte).
Hi >Ich als Arduino-Programmierer schreibe zum Erzeugen einer >Rechteckfrequenz im Audiobereich für so etwas einfach nur: > tone(8,440); >Und es läuft. Ist ja gut. Es hat sich ja schon herumgesprochen das Arduino für Musiker, Künstler und ähnlich programmiertechnisch minderbemittelte erfunden wurde. Das brauchst du nicht extra betonen. Oder an wie viele der Arduino Libs hast du selbst mit Hand angelegt? @ Andreas D. (escentf) Wenn du es wirklich ohne PWM-Mode machen willst brauchst du keinen Overflow-Interrupt. Lediglich im ISR(TIMER1_COMPA_vect) TCNT1 auf 0 setzen und den Ausgang invertieren. Einfacher wäre der CTC-Mode. Dazu müsstest du lediglich in TCCR1B noch WGM12 setzen und die Interrupts sperren. Ausgang wäre das PIN OC1A. MfG Spess
Ich verwende den atmega328p. Die Tone Funktion kann ich nicht verwenden. Und die "Formel" hab ich von hier: http://www.avrfreaks.net/forum/generating-frequencies
Andreas D. schrieb: > Ich verwende den atmega328p. Die Tone Funktion kann ich nicht verwenden. Ein Atmega328 hat drei Timer, Timer0, Timer1 und Timer2 Und jeder Timer kann im Prinzip auf "Interrupt on Overflow" oder "Interrupt on compare Match" progammiert werden Programmiere Dir einen dieser drei Timer so, dass er alle 1136 Mikrosekunden einen Timer-Interrupt erzeugt (1136µs= halbe Periodendauer bei 440Hz), und mache Dir eine Interruptbehandlungsfunktion, die beim Auftreten des Timer-Interrupts den gwünschten Pin toggelt! Welchen der drei möglichen Timer möchtest Du verwenden?
:
Bearbeitet durch User
Andreas D. schrieb: > also ohne TIMER1_COMPA_vect ? Wie meinen? Wenn Du Timer1 in der Betriebsart "Interrupt on compare match" verwenden möchtest, dann natürlich MIT einer Interrupt-Behandlungsfunktion , die vom Rumpf her so aussieht: ISR(TIMER1_COMPA_vect){ //interrupt commands for TIMER 1 here } Und in den leeren Funktionsfumpf müßtest Du die Befehle reinschreiben, die den gewünschten Ausgangspin toggeln. Und zwar mit einer Timer-Frequenz von 880Hz für eine Ausgangsfrequenz von 440Hz. Denn eine volle Periode bedeutet: Es sird zweimal getogelt, einmal nach der halben Periodendauer der Ausgangsfreuenz und einmal am Ende der Periodendauer. D.h. die Interruptfrequenz muß daher genau doppelt so hoch sein wie die zu erzeugende Ausgangsfrequenz.
:
Bearbeitet durch User
Wie schon Wilhelm Busch sagte: Mit Kürze, Klarheit und Struktur geht's mit Arduino nur. Hier findet sich beispielhaft die Einstellung der Timer Register: https://github.com/Terbytes/Arduino-Atmel-sPWM http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/
Hallo, aber das Toggeln eines Pins mittels IRQ erzeugt doch einen Jitter, oder nicht? MfG
Lass doch die Hardware arbeiten: CTC mit toggle on compare match
1 | // by selecting OC1B to toggle its logical level on each compare match (COM1B[1:0]=0x1). |
2 | DDRB=1<<PB2; //enable PB2/OC1B output |
3 | ICR1=0x4705; //16000000 / 2 / 440 = 18181,8 gerundet 18182 -1 = 0x4705 |
4 | TCCR1A=(1<<COM1B0) + (0<<WGM10); //0x10 toggle output OC1B, WGM=12 (CTC with ICR1) |
5 | TCCR1B=(3<<WGM12 ) + (1<<CS10 ); //0x19 prescaler=1 |
Dichter schrieb: > Wie schon Wilhelm Busch sagte: > > Mit Kürze, Klarheit und Struktur > geht's mit Arduino nur. > > Hier findet sich beispielhaft die Einstellung der Timer Register: > > https://github.com/Terbytes/Arduino-Atmel-sPWM > > > http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/ Gerade in Deinem zweiten Beispiel-Link erfolgt die Tonerzeugung aber auf vollkomen andere Art. Den Themenstarter hatte ich so verstnaden, als wenn er eine Rechteckfrequenz mit 440Hz, quasi PWM mit 50% Duty-Cycle an einem Ausgang erzeugen möchte, um einen Ton auf einem Piezo-Lautsprecher (Transducer) hörbar zu machen. In Deinem Sinusgenerator-Beispiel läuft es aber so: Es wird eine (für Atmega-Verhältnisse extrem hochfequente PWM erzeugt, und diese wird während einer einzigen Periode dutzendfach im Duty-Cycldangepaßt, der mit einem Sinus steigt und fällt. Da die PWM-Frequenz weit über der Resonanzfrequenz des Lautsprechers liegt, wird quasi die Auslenkung der Lautsprechermembrane über den Duty-Cycle der PWM gesteuert. Und da der Duty-Cycle einem Sinus folgt, folgt auch die Auslenkung der Lautsprechermembrane diesem Sinus. Das Ergebnis ist ein sehr reiner Glockenklang bei dieser Art digitaler Klangsynthese, der sich beim Anhören deutlich wahrnehmbar von einem Square-Wave-Piepsen mit derselben Frequenz unterscheidet.
eProfi schrieb: > Lass doch die Hardware arbeiten: CTC mit toggle on compare match Dann kann er sich den Pin, der getoggelt werden soll, aber NICHT frei aussuchen, sondern der wird ihm vom Datenblatt vorgegeben. Kann man natürlich machen, sofern man bei dem Pin, an dem der Lautsprecher angeschlossen sein soll, flexibel ist und keine eigenen Wünsche hat.
Christian S. schrieb: > Hallo, > > aber das Toggeln eines Pins mittels IRQ erzeugt doch einen Jitter, oder > nicht? Weniger als eine handvoll Contollertakte, vielleicht. Das kommt aber auch drauf an: Wenn Du noch ein halbes Dutzend anderer Interrupts auf dem Controller laufen hast, womöglich alle mit unterschiedlicher Laufzeit der jeweiligenInterruptbehandlungsroutine, dann gibt es natürlich Jitter. Aber wenn es der einzige Interrupt ist, der alle1136µs feuert, dann gibt es keinen Jitter. Wo soll der auch herkomen, es ist ja kein PC mit einem Eigenleben im Betriebssystem, sondern nur ein Mikrocontroller ohne Betriebssystem. Da läuft alles seinen geregelten (auch zeitlichen) Gang, es sei denn, Du hast viele Interrupts gleichzeitig aktiv, die sich im Ablauf gegenseitig behindern.
:
Bearbeitet durch User
Hi >Es wird eine (für Atmega-Verhältnisse extrem hochfequente PWM erzeugt, >und diese wird während einer einzigen Periode dutzendfach im >Duty-Cycldangepaßt, der mit einem Sinus steigt und fällt. Ja. nennt sich DDS (Direkte Digitale Synthese). http://www.mikrocontroller.net/articles/Digitaler_Funktionsgenerator MfG spess
Christian S. schrieb: > aber das Toggeln eines Pins mittels IRQ erzeugt doch einen Jitter, oder > nicht? Kommt drauf an. Man kann durchaus vollständig jitterfreie Timer-ISRs programmieren, wenn man die maximale variable Interruptlatenz des Restsystems kennt. Allerdings läuft dieser Ansatz letztlich darauf hinaus, eben diese variable Latenz (und noch etwas mehr) IMMER in der Timer-ISR zu verheizen, also die Gesamtperformance des Systems runterzuziehen. Und oft viel schlimmer: Man erhöht damit wiederum auch die variable Latenz für alle konkurrierenden Interrupts... Die Entscheidung für eine Anwendung des Prinzips wird man sich deshalb immer sehr gut überlegen und wenn man sie überhaupt nutzt, wird man sie i.d.R. auf eine einzelne ISR beschränken. Manchmal geht's aber halt nicht anders. Typisches Beispiel dürfte wohl wohl eine Ausgabe auf VGA- oder Videomonitore sein. Hierfür ist genau so eine latenzkompensierte ISR für die Ausgabe jeder einzelnen Bildzeile eine recht gute, weil halbwegs universelle Lösung. Besser geht's nur mittels spezieller Hardware, die halt nicht immer verfügbar ist, sei es, weil der µC garnicht darüber verfügt oder sei es, dass sie just in der konkreten Anwendung für einen anderen Zweck benötigt wird.
Christian S. schrieb: > aber das Toggeln eines Pins mittels IRQ erzeugt doch einen Jitter, oder > nicht? Jo, um ein paar Dutzend Nanosekunden könnte das schon wackeln. Jürgen S. schrieb: > Ich als Arduino-Programmierer schreibe zum Erzeugen einer > Rechteckfrequenz im Audiobereich für so etwas einfach nur: > tone(8,440); > > Und es läuft. So, und jetzt variiere dabei mal noch die Impulsbreite... Man kann sich auf dem PC auch ganz einfach eine komplette Tabellenkalkulation "programmieren" (und stolz wie Oskar drauf sein), indem man die Funktion createSpreadShead() der passenden Bibliothek aufruft. Aber wehe, der dritte Button von links soll ein blaues statt ein grünes Icon darstellen. Dann ist der stolze "Coder" schon völlig aufgeschmissen.
Hi Jürgen S. (jurs) schrieb >Aber wenn es der einzige Interrupt ist, der alle1136µs feuert, dann gibt >es keinen Jitter. Kommt dir als "Arduino-Programmierer" nur so vor. Ein Interrupt wird erst angesprungen wenn der gerade laufende Assemblerbefehl abgearbeitet ist. Da ein Assemblerbefehl bis zu 5 Takte dauern kann, ist ein Versatz von bis zu vier Takten, je nach Zeitpunkt der Interruptauslösung, möglich. MfG Spess
spess53 schrieb: > Ein Interrupt wird > erst angesprungen wenn der gerade laufende Assemblerbefehl abgearbeitet > ist. Da ein Assemblerbefehl bis zu 5 Takte dauern kann, ist ein Versatz > von bis zu vier Takten, je nach Zeitpunkt der Interruptauslösung, > möglich. > > MfG Spess Das wären bei 16 MMHz Controllertakt weniger als 400 Nanosekunden bei einem Interrupt, der alle 1136 Mikrosekunden feuern soll. Das halte ich in Anbetracht der Aufgabe, einen Piezo-Transducer im Kammerton A piepsen zu lassen, für vernachläsigbar. Ob der Themenstarter hier überhapt noch mitliest und Interesse an zielführendem AVR-Code hat? Deine Rückfrage, die Du kaum eine Viertelstunde nach dem Start des Themas gestellt hast, ist vom TO bis jetzt jedenfalls nicht beantwortet worden. Für mich sieht da so aus, als wenn er das Interesse an einer Lösung verloren hat, noch innerhalb der ersten Stunde nach dem Start seines Themas.
Vllt, hat er ja auch einfach Atmels Application Note AVR314 oder sogar AVR131 gefunden.
Lothar M. schrieb: >> Was soll das bedeuten? > Dass er ein Opfer des Nichtlesens der Bedienungsanleitung geworden ist: Dir ist schon klar, dass kursiv und unterstreichen in diesem Forum gerne mal Zufallsergebnisse liefern? Ich komme da nur schlecht mit klar.
Hi >Das wären bei 16 MMHz Controllertakt weniger als 400 Nanosekunden bei >einem Interrupt, der alle 1136 Mikrosekunden feuern soll. >Das halte ich in Anbetracht der Aufgabe, einen Piezo-Transducer im >Kammerton A piepsen zu lassen, für vernachläsigbar. Das ist mir klar. Trotzdem ist die Aussage '... dann gibt es keinen Jitter.' falsch. Die Länge der Befehle war nur ein Beispiel. C/C++ hält noch eine ganze Reihe andere Szenarien bereit die Interrupts für eine gewisse Zeit sperren können. >Deine Rückfrage, die Du kaum eine Viertelstunde nach dem Start des >Themas gestellt hast, ist vom TO bis jetzt jedenfalls nicht beantwortet >worden. Du hast meine Frage von 14:27 auch nicht beantwortet. MfG Spess
spess53 schrieb: > Du hast meine Frage von 14:27 auch nicht beantwortet. > MfG Spess Damit kannst Du ja nur Deine Off-Topic Frage meinen: "an wie viele der Arduino Libs hast du selbst mit Hand angelegt?" Hat zwar mit dem Thema dieses Threads nichts zu tun, aber wenn es Dich so stark interessiert, dass Du nochmal darauf zurückkommst, ist meine Antwort: Keine einzige! Meine Beiträge zur Arduino-Community beschränken sich darauf, dass ich im Forum von Arduino.cc gelegentlich mal das eine oder andere Beispielprogramm zu dort geposteten Fragestellungen poste,aber oft sind die Themenstarter so ignorant, dass in ihrem eigenen Thema nicht mal dann mehr antworten, wenn sie vollständig copy-and-paste-fähigen Code als Programmbeispiel gepostet bekommen. Das geht mir zunehmend auf die Nüsse, wenn Leute erst ein Thema starten und nach Code fragen, sich dann aber tot stellen, wenn sie tatsächlich Code gepostet bekommen. Und hier in diesem Forum und diesem Thema bin ich mir auch nicht sicher, ob der Themenstarter noch auf einen copy-and-paste-fähigen AVR-Beispielcode zur Piepstonausgabe mit 440 Hz wartet, oder ob er verschwunden ist und daran gar kein Interesse mehr hat.
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.