Moinmoin zusammen, ich habe probleme beim benutzen des Timer2 auf einem ATMEGA 328P. Grundsätzliche Aufgabenstellung: Ansteuerung von 2 Schrittmotoren mit unabhängiger Drehzahl. Dafür möchte ich Timer 1 und 2 benutzen. Timer 1 funktioniert super. Für Timer2 wollte ich eine Library verwenden. Es handelt sich um MsTimer2. Diese bietet allerdings nur msec resolution, ich brauche aber Mikrosekunden. Ich werde jetzt allerdings aus den genauen Einstellungen nicht schlau. Die Library setzt über die CS-Bits den Prescaler. tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler) Hier fängt mein Verständnisproblem an. Der Rechte Teil wäre ja quasi so zu verstehen F_CPU/prescaler --> Eingangsfrequenz des Timers --> 250kHz * 0.001 um auf Msec zu kommen. 256 - wäre dann der Wert bis zu dem Hochgezählt werden muss um beim Overflow auf 1 Msec zu kommen. Aber ich finde im Datenblatt keine Informationen darüber wie genau das tcnt2 funktioniert.
> Aber ich finde im Datenblatt keine > Informationen darüber wie genau das tcnt2 funktioniert. Datenplatt [0], Kapitel 18 "8-bit Timer/Counter2 with PWM and Asynchronous Operation" HTH [0] http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
cableer schrieb: > Aber ich finde im Datenblatt keine > Informationen darüber wie genau das tcnt2 funktioniert. Datenblatt Seite 157
das beantwortet meine Frage nicht ganz. Ich ging davon aus, dass der Timer bis 0xFF läuft und TCNT2 den aktuellen Zählerstand enthält. Es sieht ja aber so aus als wäre TCNT2 im vorliegenden Fall die Schwelle BIS zu der gezählt wird? nur so ergeben die Rechnungen ja Sinn?
cableer, es steht doch alle zu den verschiedene Timer2-Modi und den Registern im Datenblatt. tcnt2 ist das Zählregister. Es wird bei jedem Timertick, i.a. um 1 erhöht.
Karl M. schrieb: > cableer, > > es steht doch alle zu den verschiedene Timer2-Modi und den Registern im > Datenblatt. > > tcnt2 ist das Zählregister. > Es wird bei jedem Timertick, i.a. um 1 erhöht. Das ist aber keine Antwort die zum Problem und der Library passt. Dort wird TCNT2 explizit auf einen errechneten Wert gesetzt. Das ist das was ich nicht ganz verstehe
cableer schrieb: > Ich ging davon aus, dass der > Timer bis 0xFF läuft und TCNT2 den aktuellen Zählerstand enthält. Das ist auch so. cableer schrieb: > Es > sieht ja aber so aus als wäre TCNT2 im vorliegenden Fall die Schwelle > BIS zu der gezählt wird? Nö. Wenn du einen CTC Modus benutzt, würde MAX durch OCR2A bestimmt. TCNT2 ist der aktuelle Zählerstand. Siehe Tabelle 18-8.
Matthias S. schrieb: > cableer schrieb: >> Ich ging davon aus, dass der >> Timer bis 0xFF läuft und TCNT2 den aktuellen Zählerstand enthält. > > Das ist auch so. > > cableer schrieb: >> Es >> sieht ja aber so aus als wäre TCNT2 im vorliegenden Fall die Schwelle >> BIS zu der gezählt wird? > > Nö. Wenn du einen CTC Modus benutzt, würde MAX durch OCR2A bestimmt. > TCNT2 ist der aktuelle Zählerstand. Siehe Tabelle 18-8. Dann verstehe ich diese Zeile in der Library nicht: tcnt2 = 2; //256 - (int)((float)F_CPU * 0.001 / prescaler);
sorry das war jetzt misleading, im original so: tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler); die 2 war für einen versuch von mir mit dem oszi
cableer,
1 | tcnt2 = 256 - (uint16_t)(1.0 *F_CPU /1000 /prescaler); |
diese Zeile deute darauf hin, das Timer2 im Overflow Modus mit 1000Hz läuft, da brauche ich mir nicht mal den restlichen Code ansehen. Der Overlow Mode ist im Datenblatt beschrieben. Vom der aktuellen Zählerstand bis 0xff wird gezählt und bei 0x00 wird ein Interrupt generiert. So wird meistens der Zählerstand in der ISR wieder auf
1 | tcnt2 = 256 - (uint16_t)(1.0 *F_CPU /1000 /prescaler); |
gesetzt, so dass der Timer2 immer den gleichen Rhythmus (1000Hz) hat.
Karl M. schrieb: > tcnt2 = 256 - (uint16_t)(1.0 *F_CPU /1000 /prescaler);diese Zeile deute > darauf hin, das Timer2 im Overflow Modus mit 1000Hz > läuft, da brauche ich mir nicht mal den restlichen Code ansehen. > > Der Overlow Mode ist im Datenblatt beschrieben. > Vom der aktuellen Zählerstand bis 0xff wird gezählt und bei 0x00 wird > ein Interrupt generiert. > So wird meistens der Zählerstand in der ISR wieder auftcnt2 = 256 - > (uint16_t)(1.0 *F_CPU /1000 /prescaler);gesetzt, so dass der Timer2 > immer den gleichen Rhythmus (1000Hz) hat. Das hatte ich ja auch vermutet, allerdings kann ich in der ISR nichts derartiges sehen?
Karl M. schrieb: > tcnt2 = 256 - (uint16_t)(1.0 *F_CPU /1000 /prescaler);diese Zeile deute > darauf hin, das Timer2 im Overflow Modus mit 1000Hz > läuft, da brauche ich mir nicht mal den restlichen Code ansehen. > > Der Overlow Mode ist im Datenblatt beschrieben. > Vom der aktuellen Zählerstand bis 0xff wird gezählt und bei 0x00 wird > ein Interrupt generiert. > So wird meistens der Zählerstand in der ISR wieder auftcnt2 = 256 - > (uint16_t)(1.0 *F_CPU /1000 /prescaler);gesetzt, so dass der Timer2 > immer den gleichen Rhythmus (1000Hz) hat. Das hatte ich ja auch vermutet, allerdings kann ich in der ISR nichts derartiges sehen? ich 'nehm alles zurück! Danke Karl, ich habe es jetzt verstanden
cableer schrieb: > Ansteuerung von 2 Schrittmotoren mit unabhängiger Drehzahl. > > Dafür möchte ich Timer 1 und 2 benutzen. Warum? Das geht doch mit Timer1 allein. http://mino-elektronik.de/Generator/takte_impulse.htm#bsp3a mit 2 x Poti oder nachfolgend für UART.
Die Hardware dafür existiert schon, ich muss mich also an ein vorgegebenes Pinout halten und deswegen die Ausgänge über Portmanipulationen in der ISR schalten. Allgemein: Wie wäre es denn generell möglich mit nur einem Timer verschiedene Ausgangsfrequenzen zu erzeugen? Also nicht nur irgendwelche Bits abzapfen sondern wirklich mit Timerclock-Auflösung einstellbar?
cableer schrieb: > Wie wäre es denn generell möglich mit nur einem Timer verschiedene > Ausgangsfrequenzen zu erzeugen? Indem man z.B. die beiden Compare-Einheiten des Timers benutzt und in deren ISRs den OC2x-Wert um das gewünschte Intervall erhöht. ...
cableer schrieb: > Die Hardware dafür existiert schon, ich muss mich also an ein > vorgegebenes Pinout halten und deswegen die Ausgänge über > Portmanipulationen in der ISR schalten. Das ist doch kein Problem. cableer schrieb: > Wie wäre es denn generell möglich mit nur einem Timer verschiedene > Ausgangsfrequenzen zu erzeugen? Also nicht nur irgendwelche Bits > abzapfen sondern wirklich mit Timerclock-Auflösung einstellbar? Dafür hatte ich Dir die passenden Routinen geliefert. Aber mach, wie Du meinst.
Mal ne doofe Frage: Warum benutzt du dafür ne fremde Libraray? Sowas macht man doch in 10 Minuten selbst dass Timer 2 jede Mikrosekunde mal zuckt.
M. K. schrieb: > Mal ne doofe Frage: Warum benutzt du dafür ne fremde Libraray? > Sowas > macht man doch in 10 Minuten selbst dass Timer 2 jede Mikrosekunde mal > zuckt. Simple Antwort: Um zu schauen wie andere Leute das gelöst haben und um Timer2 besser zu verstehen. In der Anwendung benutze ich das nicht mehr. Es geht mir ja nicht darum die Library als Ersatz für eigenes Verständnis zu verwenden. Sie war einfach eine Einsteigshilfe für Timer2.
m.n. schrieb: > cableer schrieb: >> Wie wäre es denn generell möglich mit nur einem Timer verschiedene >> Ausgangsfrequenzen zu erzeugen? Also nicht nur irgendwelche Bits >> abzapfen sondern wirklich mit Timerclock-Auflösung einstellbar? > > Dafür hatte ich Dir die passenden Routinen geliefert. Aber mach, wie Du > meinst. Ich hab deinen Code getestet. Das Grundproblem war folgendes: Zu viel Code in der ISR -> zu geringe Fmax. Ich bin mit dem ganzen leider schon fast an der Grenze für den 328 bei 16MHz. Der Stepper hat schon ohne Microstepping 800 steps/turn und ich muss leider sowohl sehr genaue als auch einigermaßen zügige Bewegungen kommandieren können. Vermutliche werde ich Microstepping und Vollschrittbetrieb mixen müssen
cableer schrieb: > Um zu schauen wie andere Leute das gelöst haben und um > Timer2 besser zu verstehen. Das ist auch völlig OK Aber wenn du jetzt was eigenes nutzt: Wo ist das Problem nun? Es ist doch kein Hexenwerk zwei Schrittmotoren mit einem Atmega328 unabhängig voneinander zu steuern. Erst recht wenn man zwei verschiedene Timer benutzt. Ich habe grade irgendwie wirklich ein Problem dein Problem zu erfassen. Dachte du hättest ein Problem mit der Lib, die du benutzt hast aber jetzt schreibst du cableer schrieb: > In der Anwendung benutze ich das nicht mehr. und dann sollte es doch gar kein Problem sein zwei Schrittmotoren anzusteuern. m.n. hat ja auch schon ein gutes Beispiel dafür geliefert.
cableer schrieb: > Ich hab deinen Code getestet. Das Grundproblem war folgendes: Zu viel > Code in der ISR -> zu geringe Fmax. Ich bin mit dem ganzen leider schon > fast an der Grenze für den 328 bei 16MHz. Der Stepper hat schon ohne > Microstepping 800 steps/turn und ich muss leider sowohl sehr genaue als > auch einigermaßen zügige Bewegungen kommandieren können. Vermutliche > werde ich Microstepping und Vollschrittbetrieb mixen müssen Dann wird es wohl nichts mit einem ATmega328. Zur Not kannst Du noch Assembler bemühen und dabei nur die notwendigen Register retten/wiederherstellen. Aber sobald noch eine weitere ISR verwendet wird, kann das Timing in die Hose gehen. Es wird auch nicht besser, zwei Timer zu verwenden, zumal 8-Bit Timer mit hoher Auflösung noch mehr Rechenzeit für die Teilperioden brauchen. Auch ein dynamisches Umschalten zwischen Mikro- und Vollschritt erzeugt mehr Code in der ISR. Beschleunigungsrampen sind auch noch nirgends vorhanden. Sofern der Mega328 schon jetzt an der Grenze arbeitet, sieh Dich nach einem anderen µC um oder verteile die Ansteuerung auf einen zweiten AVR. Sonst kommst Du an den Punkt, an dem die Motore nur noch piepsen, sich aber nicht mehr drehen ;-)
cableer schrieb: > Timer 1 funktioniert super. cableer schrieb: > Simple Antwort: Um zu schauen wie andere Leute das gelöst haben und um > Timer2 besser zu verstehen. In der Anwendung benutze ich das nicht mehr. > Es geht mir ja nicht darum die Library als Ersatz für eigenes > Verständnis zu verwenden. Sie war einfach eine Einsteigshilfe für > Timer2. Eine der beiden Aussagen stimmt nicht... Oliver
Nimm doch den Xmega32E5, der kann doppelt so schnell takten und hat genügend Hardware, die sich um die gestellte Aufgabe kümmert, ohne dass die CPU belastet wird. Achtung: Xmegas vertragen nur maximal 3.6V als Betriebsspannung und Pin-Pegel.
Im Labor auch 40Mhz, normal 32, ich bin von 16Mhz beim ATMega ausgegangen.
Hatte ich die 32 MHz doch richtig in Erinnerung. Und zwei ATmega lasse ich auch mit 24 MHz laufen.
Also Leute. Ein Atmega328 kann aber mal ganz locker auch alleine zwei Schrittmotoren unabhängig von einander ansteuern. Hier jetzt einen Atxmega auszupacken ist das sprichwörtliche "Mit Kanonen auf Spatzen" schießen.
Microstepping mit hoher Geschwindigkeit ist schon eine Hausnummer. Und das Ganze x2... Entweder Programmablauf optimieren oder schnelleren Controller mit aufgebohrter Peripherie verwenden.
Knut B. schrieb: > Microstepping mit hoher Geschwindigkeit ist schon eine Hausnummer. Und > das Ganze x2... Entweder Programmablauf optimieren oder schnelleren > Controller mit aufgebohrter Peripherie verwenden. Das ganze funktioniert jetzt soweit, allerdings habe ich folgendes Problem: In der ISR sieht es folgendermaßen aus void timerISR() { counter1++; counter2++; if(counter1 > timing1 && steps1 > 0) { PORTD ^= B00100000; counter1=0; steps1--; } …gleiches für den 2. Stepper } Wenn ich für steps1 oder 2 ausserhalb des Main-loops Werte setze werden diese sauber abgefahren. Sobald ich auf steps1/2 im Main loop zugreife passiert in der ISR nichts mehr. Die variable erhält den korrekten Wert, am Ausgang ist es aber still. steps sind unsigned long int und global definiert. Was mache ich da falsch/habe ich übersehen? }
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.