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
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 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
>>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