Forum: Mikrocontroller und Digitale Elektronik ATMEGA 328 Timer 2 Issues


von cableer (Gast)


Angehängte Dateien:

Lesenswert?

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.

von g457 (Gast)


Lesenswert?

> 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

von Harry L. (mysth)


Lesenswert?

cableer schrieb:
> Aber ich finde im Datenblatt keine
> Informationen darüber wie genau das tcnt2 funktioniert.

Datenblatt Seite 157

von cableer (Gast)


Lesenswert?

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?

von Karl M. (Gast)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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

von cableer (Gast)


Lesenswert?

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

von Karl M. (Gast)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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?

von cableer (Gast)


Lesenswert?

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

von m.n. (Gast)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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?

von Hannes L. (hannes)


Lesenswert?

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.

...

von m.n. (Gast)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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.

von cableer (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von m.n. (Gast)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> Xmega32E5, der kann doppelt so schnell takten

40 MHz?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Im Labor auch 40Mhz, normal 32, ich bin von 16Mhz beim ATMega 
ausgegangen.

von S. Landolt (Gast)


Lesenswert?

Hatte ich die 32 MHz doch richtig in Erinnerung.
Und zwei ATmega lasse ich auch mit 24 MHz laufen.

von M. K. (sylaina)


Lesenswert?

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.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Microstepping mit hoher Geschwindigkeit ist schon eine Hausnummer. Und 
das Ganze x2... Entweder Programmablauf optimieren oder schnelleren 
Controller mit aufgebohrter Peripherie verwenden.

von cableer (Gast)


Lesenswert?

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?



}

von cableer (Gast)


Lesenswert?

ganzer Code kommt morgen. Ich bin grade nicht richtigen Rechner.

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
Noch kein Account? Hier anmelden.