Hallo! ich möchte ein AtMega16 benutzen. Damit sollen 4 PWMs mit 1-400Hz erzeugt werden. Ist das mit einem internem RC-Oszillator möglich? Nebenbei möchte ich 2-3 taster abfragen, um programmabläufe zu steuern. Es werden außerdem ein Paar Pins als 0/1 benutzt. quarz möchte ich nicht nehmen. bei mir klappt das irgendwie nicht :( ich kriege das dummerweise nie hin, mit den fusebits. Ich habe hier ein Beispielprogramm gefunden in Bascom. einige erfahrung ist schon vorhanden. Im programm ist zwar ein Mega8, aber egal. ich wollte noch wissen, wie es mit 4 PWMs geht? einfach so logisch das Programm ergänzen? Und die andere Frage noch mal: geht das mit 1MHz int.-Oszill.? Bitte nicht gleich schimpfen und steinigen. Bin halt einsteiger und habe schon hier viel gelesen, ist aber einiges noch unklar. Beispielprogramm: Erklärung: $regfile = "m8def.dat" $crystal = 8000000 Definiert den Mega8 und den 8MHz Quarz Config Portb.1 = Output Config Portb.2 = Output Definiert die zwei Ausgänge von Timer1 auf Ausgabe. Portb.1 = für Compare1a (= Compare A) = Pin 15 Portb.2 = für Compare1b (= Compare B) = Pin 16 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1 Config Timer1 = Pwm Timer1 auf PWM einstellen Pwm = 8 Timer Auflösung = 8 Bit einstellen Compare A Pwm = Clear Up Definiert, wie der Compare A schalten soll. Bei „Clear Up“ schaltet der Ausgang beim erreichen des Compare-Wertes zuerst auf High und dann auf Low. Bei „Clear Down“, umgekehrt. Compare B Pwm = Clear Up Das gleiche noch mal mit Compare B Prescale = 1 Hier wird der Prescaler auf 1 eingestellt. (Wert 1 heißt, direkte Frequenz vom Quarz zum Timer.) Weitere Teilungen, wie z.B.: 8, 64, 256 und 1024 sind möglich. Compare1a = 205 Compare1b = 51 Hier kann man nun die Werte für das Tastverhältnis, in dem Register Compare1a und Compare1b übergeben. Oder man kann, statt Compare1a und 1b, auch die Bezeichnungen Pwm1a und Pwm1b verwenden, Bascom nimmt beides. Mit diesem kurzen Programm, hat man nun zwei PWM Signale erzeugt, bei dem eines ein Tastverhältnis von 20% (Compare1a) und das andere 80 % hat. :-) Gruss Alex
Alex schrieb: > ich möchte ein AtMega16 benutzen. > Damit sollen 4 PWMs mit 1-400Hz erzeugt werden. > Ist das mit einem internem RC-Oszillator möglich? Kommt drauf an, wieviele Stufen deine PWM haben soll. Wenn du 4 PWM Ausgänge haben willst, bleibt dir nichts anderes übrig als eine Software-PWM zu machen.
achso, ja, sorry. es soll natürlich eine Software-PWM werden. Stufen? Hm, kann ich noch nicht voraussagen. es soll halt die Frequenz von 1Hz auf 350Hz relativ langsam steigen. Da die Zeiger als Ausgabe verwendet werden ist die Anzeige einiger Maßen träge. also in Stritten von 10Hz jede sekunde soll sich die Frequenz erhöhen. Noch eine kurze Frage, der Beispiel da oben ist doch eine Software-pwm, oder? danke euch für die Hilfe.
Alex schrieb: > achso, ja, sorry. > es soll natürlich eine Software-PWM werden. > Stufen? > Hm, kann ich noch nicht voraussagen. > es soll halt die Frequenz von 1Hz auf 350Hz relativ langsam steigen. Ähm. Bei einer PWM verändert sich die Frequenz gar nicht. Die bleibt immer konstant. Lediglich der Tastgrad verändert sich > Noch eine kurze Frage, der Beispiel da oben ist doch eine > Software-pwm, oder? Genau. Deswegen wird auch der Hardware Timer 1 dahingehend programmiert, dass er eigenständig eine PWM erzeugt. :-) Software-PWM bedeutet, dass der Timer lediglich einen Takt vorgibt und alles weitere erledigt dein Program!
moment mal :))) wie erzeuge ich denn eine Frequenz? Ich dachte die Pulsweitenmodulation ist eine Folge von den Impulsen. Und je kleiner der Abstand zwischen 2 Positiven Flanken ist, desto höher ist die "Frequenz". Habe ich nun was ganz falsches im Kopf?
Alex schrieb: > moment mal :))) > wie erzeuge ich denn eine Frequenz? > Ich dachte die Pulsweitenmodulation ist eine Folge von den Impulsen. > Und je kleiner der Abstand zwischen 2 Positiven Flanken ist, desto höher > ist die "Frequenz". > Habe ich nun was ganz falsches im Kopf? Hast du
oohhh neiiiin! Geht das überhaupt mit einem atmega16 die Frequenz zu erzeugen?
Alex schrieb: > oohhh neiiiin! > > Geht das überhaupt mit einem atmega16 die Frequenz zu erzeugen? 1 bis 400Hz? Nein. Da macht der Mega16 nicht mit. Ist ihm zu langweilig Natürlich geht das! Dein µC ist rund 2500 mal schneller als diese popelige Frequenz. Aber auch hier wieder: Du du nicht genügend Timer hast, musst du das in Software machen. Ist doch aber simpel. Du brauchst nur zum richtigen Zeitpunkt einen Ausgangspin von 0 auf 1 bzw. von 1 auf 0 schalten und schon hast du einen Ausgangspin, der ein Signal mit einer bestimmmten Frequenz abgibt.
@ Alex (Gast) >oohhh neiiiin! Oh doch. Lies mal was über PWM. >Geht das überhaupt mit einem atmega16 die Frequenz zu erzeugen? Nein. Das kann nur ein Pentium 4 mit mind. zwei Kernen. MfG Falk, wer Ironie findet darf sie behalten.
>1 bis 400Hz?
und das mal 4
also an den 4 Pins, aber nicht die gleiche Frequenz auf allen 4 Pins.
so zu sagen pi1 100Hz, pin2 160Hz, pin3 80Hz und pin4 280Hz.
die frequenz wird sich ändern von 1Hz bis 400Hz.
bitte ernst nehmen, ich glaube ich habe einen riesen Problem.
Alex schrieb:
> ich glaube ich habe einen riesen Problem.
Das denke ich auch.
Gehen wir es mal so an.
Du kannst dir einen Timer so aufsetzen, dass er dir alle, Hausnummer,
0.00001 Sekunden einen Interrupt auslöst.
Bei 400Hz musst du alle 0.00125 Sekunden einen Ausgangspin von 0 auf 1
und von 1 auf 0 schalten, dann entsteht am Ausgang eine Frequenz von
400Hz.
Da deine Interrupt Routine alle 0.00001 Sekunden aufgerufen wird,
brauchst du in der Interrupt Routine also nur eine Variable die bei
jedem Aufruf um 1 erhöht wird. Hat die Variable 125 erreicht, sind daher
0.00125 Sekunden vergangen und es ist Zeit den Ausgangspin umzuschalten
und die Zählerei wieder bei 0 beginnen zu lassen.
Willst du 135Hz erzeugen, dann ist der Zeitabstand zwischen dem
Umschalten 1/(135*2) = 0.00370 Sekunden.
Folgerichtig muss in der Interrupt Routine nicht bis 125, sondern bis
370 gezählt werden, damit am Ausgang eine Frequenz von 135Hz entsteht.
Aber ansonsten bleibt alles andere gleich.
Und natürlich kannst du das nicht nur für 1 Ausgang mit 1 Zähler machen,
sondern auch mit 4 Ausgängen und 4 Zählern oder 15 Ausgängen und 15
Zähler.
danke, es ist schon eine grosse Hilfe und gute Erklärung. >Du kannst dir einen Timer so aufsetzen, dass er dir alle, Hausnummer, >0.00001 Sekunden einen Interrupt auslöst. Weiss nur nicht wie ich das in der Praxis realisieren soll. ansonsten ist alles klar. Gibt es ein Bespielprogramm im bascom um 100Hz zu erzeugen? Dann könnte ich das auf meine Frequenzen übertragen und so weiter machen.
Alex schrieb: > danke, es ist schon eine grosse Hilfe und gute Erklärung. > >>Du kannst dir einen Timer so aufsetzen, dass er dir alle, Hausnummer, >>0.00001 Sekunden einen Interrupt auslöst. > > Weiss nur nicht wie ich das in der Praxis realisieren soll. Ich hab jetzt die Zahlen nicht kontrolliert. Aber mit dem 16 Bit Timer1 und einem Clear On Compare müsste man in die Nähe dieser 0.00001 Sekunden kommen. Wenns nicht ganz genau ist, macht das auch nichts, dann muss man eben die Berechnung der Zähler an diese Zahl anpassen.
Oops. Seh gerade, das wird eng mit 1Mhz Wenn der Timer mit vollem Speed läuft, dann macht der alle 0.000001 Sekunden einen Timer-Tick. Man müsste also alle 10 Timerticks einen Interrupt auslösen. Das wird nicht reichen um in BASCOM deine 4 Zähler zu bedienen. Also wirst du wohl deine Genauigkeitsanforderungen etwas zurückschrauben müssen (oder die µC Taktfrequenz erhöhen)
>Also wirst du wohl deine Genauigkeitsanforderungen etwas zurückschrauben >müssen wenn ich eine Frequenzerhöhung von 15Hz pro sekunde nehme, wird das dann reichen?
Alex schrieb: >>Also wirst du wohl deine Genauigkeitsanforderungen etwas zurückschrauben >>müssen > > wenn ich eine Frequenzerhöhung von 15Hz pro sekunde nehme, wird das dann > reichen? Selber rechnen.
weiss nicht wie ich das rechnen kann. bitte nicht übel nehmen, ist keine Faulheit oder so. mir fehlt wohl was um es zu kapieren. ich werde jetzt mal was praktisch probieren. vielleicht werde ich daraus schlauer. ich melde mich noch. Danke schon mal.
ja, also ich habe es so gemacht: $regfile = "M8def.dat" $crystal = 1000000 Drehzahl Alias Portc.5 Config Drehzahl = Output Config Timer0 = Timer , Prescale = 1 On Ovf0 On_ovf0 Enable Ovf0 Enable Interrupts Do Loop End On_ovf0: Toggle Drehzahl Return es kommt fast 2kHz raus an der Frequenz. so solle es auch sein. der Timer läuft bei 255 über und löst den Interrupt aus, so wird der Pin getoggelt. was muss ich im Programm ändern, damit der Timer bereits bei 100 überläuft? wenn ich es erfahre, sollen es keine offenen Fragen mehr geben. bitte, helft mir. der quellecode ist von Folgender Seite übernommen und angepasst worden: http://www.halvar.at/elektronik/kleiner_bascom_avr_kurs/timer0_als_timer/ Nicht wundern, dass bei mir mega8 steht und nicht 16. habe beide gerade da.
Alex schrieb: > > was muss ich im Programm ändern, damit der Timer bereits bei 100 > überläuft? um den Timer überlaufen zu lassen, nachdem er 100 mal getaktet hat, musst du ihn auf den Wert 155 "vorladen". Das geht mit dem Befehl : Timer0 = 155
Hi >um den Timer überlaufen zu lassen, nachdem er 100 mal getaktet hat, >musst du ihn auf den Wert 155 "vorladen". Das geht mit dem Befehl :... Dafür gibt es CTC. MfG Spess
>um den Timer überlaufen zu lassen, nachdem er 100 mal getaktet hat, >musst du ihn auf den Wert 155 "vorladen". Das geht mit dem Befehl : >Timer0 = 155 das ist doch so logisch und einfach. aber ich komme nicht darauf. ich denke immer an was anderes, viel komplizierteres. Danke dir sehr, es funktioniert. Versuche dann weiter selbst zu machen. ich will jetzt die Frequenz von 50Hz auf 200Hz langsam (in 20Hz Schritten) zu erhöhen. Also dass es das Programm halt für mich macht. ich denke mal ich schreibe nach jedem Interrupt Timer0 + (etwa) 15 so soll es doch gehen, oder? ich meine wenn der Timer0 = 50 ist nach dem Überlauf wird der Pin Getoggelt und dann Timer0 + 15 wird er denn zu den 50 die er hatte 15 addieren? und dann zu 75 noch mal 15? wird das so klappen?
Hi
>Hi, was ist CTC?
'Clear Timer on Compare Match' . Oder für alle, die noch kein Datenblatt
gelesen haben: Der Endwert des Timers wird in einem
Output-Compare-Register geladen. Wenn der Timer diesen Wert erreicht,
wird er wieder auf Null gesetzt und wenn erlaubt ein Interrupt
ausgelöst.
@Daniel: Kann man mit soviel Nichtwissen programmieren?
MfG Spess
Hi Alex, der Timer überschreibt die "50" sofort mit "51", "52" usw., bis er "255" erreicht hat. Deshalb geht das nicht mit deiner Methode. Du musst ganz zu Anfang eine eigene Variable definieren, z.B. Dim Timervorspannung As Long Im Timerüberlauf schreibst du: Timervorspannung = Timervorspannung + 15 und übergibst die "50", "65", "80" usw. über folgenden Befehl an den Timer0: Timer0 = Timervorspannung
Die Idee ist schon klar, und auch logisch, aber er will irgendwie nichts addieren. die Ausgangsfrequenz ändert sich nicht. Bin ich zu blöd was ein zu fügen? so sieht es aus: $regfile = "M8def.dat" $crystal = 1000000 Drehzahl Alias Portc.5 Config Drehzahl = Output Dim Timervorspannung As Long Config Timer0 = Timer , Prescale = 64 Timer0 = Timervorspannung On Ovf0 On_ovf0 Enable Ovf0 Enable Interrupts Do Loop End On_ovf0: Timervorspannung = Timervorspannung + 10 Toggle Drehzahl Timer0 = 10 Return
also es muss doch so sein: $regfile = "M8def.dat" (mega16) $crystal = 1000000 ( RC-Osz. 1MHz) Drehzahl Alias Portc.5 (Definition) Config Drehzahl = Output (als ausgang setzen) Dim Timervorspannung As Long ("Timervorspannung" als "Einheit" festlegen) Timervorspannung = Timer0 (Timervorspannung heisst soviel wie Timer0) Config Timer0 = Timer , Prescale = 64 (Timer, Vorteiler definieren) On Ovf0 On_ovf0 (Beim Überlauf gehe zu On_ovf0) Enable Ovf0 ( Aktiviere Überlauf) Enable Interrupts (aktiviere Interrupts) Do Loop End On_ovf0: (Hier bei Überlauf anfangen) Toggle Drehzahl (Toggeln "Drehzahl" Pin 5 PortC) Timer0 = 10 (Timer hat den Wert 10) Timervorspannung = Timervorspannung + 20 (Timervorspannung ist nun alter Wert der Timervorspannung und 20 dazu) Return (Rückkehr) "nur WOHIN?" Ich verstehe schon was hier abläuft, weiss aber nicht warum er die 20 nicht addieren will. Bitte, gibt mir noch paar Tipps. Ich mache das ja nicht mit Absicht, blöde Fragen zu stellen. Gruss Alex
Hi Alex. On_ovf0: Timervorspannung = Timervorspannung + 10 If Timervorspannung > 255 Then Timervorspannung = 10 Toggle Drehzahl Timer0 = Timervorspannung Return
Hi Daniel. Die Frequenz bleibt bei 60Hz stehen, und geht weber hoch, noch runter. Gibt es noch eine Möglichkeit so etwas zu machen? es kann doch nicht schwer sein, die Frequenz von genau 50Hz in 10Hz Schritten (1 Schritt etwa 0,1 sekunde) auf 350Hz zu bringen, oder? Erstmal auf einem Pin. und nicht auf 4 Pins gleichzeitig.
Hi Alex, also mit diesem Beispiel geht die Frequenz hoch und runter : $regfile = "M8def.dat" $crystal = 1000000 Drehzahl Alias Portc.5 Config Drehzahl = Output Dim Timervorspannung As Long Timervorspannung = 50 Config Timer0 = Timer , Prescale = 64 On Ovf0 On_ovf0 Enable Ovf0 Enable Interrupts Do Loop End On_ovf0: Timervorspannung = Timervorspannung + 10 If Timervorspannung > 255 Then Timervorspannung = 10 Toggle Drehzahl Timer0 = Timervorspannung Return
da hast du bestimmt recht, sie geht dann so schnell hoch, dass es der F.Counter gar nicht mitbekommt und immer etwas um 60Hz anzeigt. Danke aber für deine Mühe.
statt ... Timervorspannung = Timervorspannung + 10 kannst du Timervorspannung = Timervorspannung + 1 ...schreiben. Dann wird die Frequenz langsamer erhöht, und der Frequenzzähler kommt besser mit dem Anzeigen der Frequenz mit.
Glaube kaum. :) Ihr erhöht die "Vorspannung" bei jedem Timeroverflow, d.h. die Frequenz steigt bei jeder halben Periode des Ausgangssignals (bei jedem Pintoggle) schon an. Also seid ihr nach wenigen Perioden bei der Maximalfrequenz. Ihr braucht da noch einen Zähler, der die gewünschte Anzahl an Perioden des Ausgangssignals gleicher Frequenz bestimmt und erst dann die Aktulaisierung der "Vorspannung" zulässt.
ich habe jetzt statt den F.Counter, die anzeige angeschlossen. mit entsprechender Hardware natürlich. es ist so, dass die Frequenz im Programm sich quadratisch erhöht. das ganze soll nachher das kombiinstrument des Autos simulieren. und es ist blöd, wenn das auto, wenn es auf 200km/h zukommt, 6 oder8 mal schneller beschleunigt als bei 120km/h.
>Ihr braucht da noch einen Zähler, der die gewünschte Anzahl an Perioden >des Ausgangssignals gleicher Frequenz bestimmt und erst dann die >Aktulaisierung der "Vorspannung" zulässt. Genau so ist das. nur mir fehlt der anhaltspunkt, bzw. die Erfahrung oder Syntax-wissen um das zu machen
Hi Alex, hier ein Beispiel mit Timer0 und Timer1. Timer1 erhöht sekündlich die "Timervorspannung" um "10". Die Frequenz von Timer0 wird also exakt einmal pro Sekunde höher. Du kannst die Zahl "2975" auch rausnehmen, und durch eine höhere Zahl ersetzen. Dann wird eine schnellere Aktualisierungsrate erreicht, als einmal pro Sekunde. $regfile = "M8def.dat" $crystal = 1000000 Drehzahl Alias Portc.5 Config Drehzahl = Output Dim Timervorspannung As Long Dim Jederzweite As Byte Timervorspannung = 50 Config Timer0 = Timer , Prescale = 64 Config Timer1 = Timer , Prescale = 8 On Timer1 Togglehorst Enable Timer1 On Ovf0 On_ovf0 Enable Ovf0 Enable Interrupts Do Loop End On_ovf0: Toggle Drehzahl Timer0 = Timervorspannung Return Togglehorst: Timer1 = 2975 'Timer1 auf 2975 (von 65535 möglichen) vorladen If Jederzweite = 0 Then Jederzweite = 1 Else Jederzweite = 0 If Jederzweite = 0 Then Goto Bravo Timervorspannung = Timervorspannung + 10 If Timervorspannung > 255 Then Timervorspannung = 50 Bravo: Return
ich habe mal ein Video gemacht ;) leider schlechte qualität. sonst kann ich das hier nicht anhängen. es ist aber denkeich mal deutlich zu sehen. ach ja, ich habe mit einem f.generator geguckt f bei 100km/h = f/2 bei 200km/h also linear.
Hi Axel, -Echt cool. Man sieht in deinem Video einen mit einem Atmega angesteuerten (analogen) Autotacho. Habe das mp4-Video in Mpg umgewandelt (Grösse 4,39 MB)
Hi Alex, dieses Code-Beispiel hat eine Funktion, um eine gewünschte Frequenz errechnen zu können! Jede Sekunde wird die Frequenz automatisch um 50 Hertz erhöht. Der Frequenzbereich ist 50 - 400 Hz. Sind 400 Hz erreicht, fängt die Frequenz wieder bei 50 Hz an. $regfile = "M8def.dat" $crystal = 1000000 Drehzahl Alias Portc.5 Config Drehzahl = Output Dim Myfrequency As Long Dim Timervorspannung As Long Dim Jederzweite As Byte Dim Tmp As Single Config Timer0 = Timer , Prescale = 64 Config Timer1 = Timer , Prescale = 8 On Timer1 Togglehorst Enable Timer1 On Ovf0 On_ovf0 Enable Ovf0 Enable Interrupts Myfrequency = 50 Do Loop End On_ovf0: Toggle Drehzahl Timer0 = Timervorspannung Return Togglehorst: Timer1 = 2975 'Timer1 auf 2975 (von 65535 möglichen) vorladen, um 1s zu erzeugen If Jederzweite = 0 Then Jederzweite = 1 Else Jederzweite = 0 If Jederzweite = 0 Then Goto Bravo Myfrequency = Myfrequency + 50 If Myfrequency > 400 Then Myfrequency = 50 'Maximalfrequenz von 30,5 bis 7812 Hertz möglich Tmp = 1000000 'Quarzoszillator 1 MHz Tmp = Tmp / 64 'Timer0 Prescale = 64 Tmp = Tmp / Myfrequency Tmp = Tmp / 2 'Korrektur, um Halbwelle in Vollwelle umzuwandeln Tmp = Tmp - 1 Tmp = 256 - Tmp 'Timer0 mit einem Wert 0-255 vorladen Tmp = Round(tmp) 'aus 2.3 wird 2 und aus 2.8 wird 3 Timervorspannung = Tmp Bravo: Return
danke dir. ich habe es erst mal probeweise so gelöst: $regfile = "m8def.dat" $crystal = 1000000 Drehzahl Alias Portc.4 Config Drehzahl = Output Dim Pause As Long Do A1b: Waitus 3150 Toggle Drehzahl Waitus 3150 Reset Drehzahl Pause = Pause + 1 If Pause > 700 Then Goto A1a Else Goto A1b End If A1a: Pause = 1 A2: Waitus 3100 Toggle Drehzahl Waitus 3100 Reset Drehzahl Pause = Pause + 1 If Pause > 20 Then Goto A2a Else Goto A2 End If A2a: Pause = 1 A3: Waitus 3050 Toggle Drehzahl Waitus 3050 Reset Drehzahl Pause = Pause + 1 If Pause > 20 Then Goto A3a Else Goto A3 End If A3a: Pause = 1 A4: Waitus 3000 Toggle Drehzahl Waitus 3000 Reset Drehzahl Pause = Pause + 1 If Pause > 20 Then Goto A4a Else Goto A4 End If A4a: Pause = 1 A5: Waitus 2950 Toggle Drehzahl Waitus 2950 Reset Drehzahl Pause = Pause + 1 If Pause > 20 Then Goto A5a Else Goto A5 End If usw. werde dein Code noch ausprobieren. Gruss alex
>>werde dein Code noch ausprobieren.
dann kannst du mir mal sagen, welche Frequenz notwendig ist, um deinen
analogen Automobil-Tacho auf 20 km/h und auf 200 km/h auszusteuern.
(Tacho siehe Video)
>dann kannst du mir mal sagen, welche Frequenz notwendig ist, um deinen >analogen Automobil-Tacho auf 20 km/h und auf 200 km/h auszusteuern. habe leider letzte Tage keine Zeit gehabt da weiter noch was zu machen, aber es wird noch fertig gemacht alles :) 20km/h - 30Hz 200 km/h -300Hz die f darf nicht in Grossen Schritten steigen, sonst läuft das nicht ruckelfrei :) Gruss Alex
Frager? :))) das ist ein öfftl. PC bei uns auf der Arbeit. Ich bin Alex
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.