Forum: Mikrocontroller und Digitale Elektronik Timer/PWM Problem an ATmega16


von Fabian B. (fanick)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein kleines Problem mit Timern und PWM an einem ATmega16.


Es handelt sich um einen kleinen DC Motor angesteuert per IRLZ34N Mosfet 
an PB3.

Ich möchte nun lediglich alle 2 Sekunden (muss nicht genau sein!) die 
PWM Geschwindigkeit erhöhen, Timer Überlauf und co habe ich erstmal 
rausgenommen (der Timer1 sollte 67 Sekunden laufen bei 1MHz und 
clk/1024?).

Im Anhang befindet sich eine Minimalversion vom Quelltext (die habe ich 
auch kompiliert und zum Testen verwendet).


was ich erwarte : Alle 2 Sekunden die nächste Geschwindigkeit und dann 
wieder von vorne. Wenigstens 67 Sekunden lang.

was der Motor tut : Alles nur nicht das, er wechselt zwar die 
Geschwindigkeiten aber weder in der Reihenfolge wie im Array, noch alle 
2 Sekunden.

Ich denke also ich hab da irgendwie einen großen Denkfehler, den ich 
ständig übersehe. Bin noch sehr unerfahren in der Arbeit mit 
Mikrocontrollern.
Vielen Dank für eure Hilfe!

fanick

von Falk B. (falk)


Lesenswert?

@  Fabian B. (fanick)

>Ich möchte nun lediglich alle 2 Sekunden (muss nicht genau sein!) die
>PWM Geschwindigkeit erhöhen, Timer Überlauf und co habe ich erstmal
>rausgenommen

Warum? Gerade DAS ist eine perfekte Zeitbasis und genau der richtige Ort 
für deinen Zähler!

>was ich erwarte : Alle 2 Sekunden die nächste Geschwindigkeit und dann
>wieder von vorne. Wenigstens 67 Sekunden lang.

>ständig übersehe. Bin noch sehr unerfahren in der Arbeit mit
>Mikrocontrollern.

Pack die ISR für den Timerüberlauf wieder rein und dort deinen Zähler.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Etwa so.

von Fabian B. (fanick)


Angehängte Dateien:

Lesenswert?

vielen Dank!

Ich denke die Interrupts sind noch nicht vollständig initialisiert?

Im Anhang ist mein aktueller Stand, ich habe nur noch eine globale cnt 
Variable als volatile definiert und in dem Interrupt zähle ich nur noch 
diesen hoch.

Den Prescaler habe ich auf 64 gestellt und einen Preload von 34286 
eingestellt, damit sollte ich 2 Sekunden pro Overflow haben.


Es funktioniert nun nach einigem Testen auch recht rund :-)

Ist das so der "konforme" Weg?

herzlichen Dank noch einmal für die schnelle Hilfe


fanick

von Fabian B. (fanick)


Lesenswert?

Es funktioniert leider immer noch nicht so richtig.

Entweder ist was falsch mit der Frequenz oder aber mit dem Array zur PWM 
Ausgabe.

Zumindest bleibt der Motor grad immer mit der letzten Version auf der 
gleichen Geschwindigkeit.

Edit: Die Geschwindigkeit kann es nicht sein. Mit runtergesetzter 
Geschwindigkeit dauert es lange bis der Motor anfängt (also bis zum 
ersten Mal in die if Bedingung gegangen wird.
Es scheint dann wohl irgendwo ein kleiner Fehler mit dem Array zu sein, 
in der Simulation funktioniert es allerdings..

von Karl H. (kbuchegg)


Lesenswert?

Fabian B. schrieb:
> Es funktioniert leider immer noch nicht so richtig.

Mit dem Programm, das du zuletzt gepostest hat?

Du änderst die Motor_PWM alle 0.5 Sekunden.
So ein Motor ist doch kein Federgewicht. Du musst der trägen Masse schon 
etwas Zeit lassen um auf deine veränderte PWM zu reagieren.


PS: verstreu die wesentlichen Konstanten nicht quer übers ganze 
Programm. Gerade in der Entwicklungsphase ist es IMHO keine so gute 
Idee, die Bit-Werte aus main rauszunehmen. Man muss dann ständig hin und 
her scrollen um zu sehen, was du eigentlich wo eingestellt hast.

von Karl H. (kbuchegg)


Lesenswert?

Und zieh das UMstellen der PWM ruhig in die Timer-ISR rein. Die 3 
Zuweisungen und das bischen rechnen macht der µC mit links in der ISR 
noch mit.

von Fabian B. (fanick)


Lesenswert?

Danke erstmal, ich gucke dass ich das nochmal etwas übersichtlicher 
aufbaue.

Zu der PWM Geschwindigkeit:

Ich habe eine Periodendauer von 2s mir ausgerechnet:
Wenn ich dann also
1
      
2
if (cnt > lasttime) {
3
  lasttime = cnt;
4
  if(cnt==1)
5
    MOTOR = 40;
6
  else if(cnt>2)
7
    MOTOR = 0;
8
}
für die Geschwindigkeit auswählen würde, würde ich erwarten, dass der 
Motor kurz angeht für 2s und dann wieder ausgeht. Es ist aber so, dass 
der Motor nur einmal mit Geschwindigkeit 40 angeht und dann auch an 
bliebt.
"cnt" wird also im Interrupt nicht erhöht.

Ich habe das ganze jetzt in die Interrupt Routine gesetzt und es 
funktioniert!

Nur sehe ich noch nicht den Fehler, warum das in der main nicht 
funktioniert, schließlich will ich ja bei erweitertem Programm nicht 
alles im ISR machen.


Danke nochmals an euch für die sehr schnelle Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

Fabian B. schrieb:
> Danke erstmal, ich gucke dass ich das nochmal etwas übersichtlicher
> aufbaue.
>
> Zu der PWM Geschwindigkeit:
>
> Ich habe eine Periodendauer von 2s mir ausgerechnet:

Es sind sogar 4 Sekunden. Ich hab mich von deiner Timer Vorladerei ins 
Boxhorn jagen lassen.

von Karl H. (kbuchegg)


Lesenswert?

Fabian B. schrieb:

Sorry. Hab mich verrechnet.

> Ich habe das ganze jetzt in die Interrupt Routine gesetzt und es
> funktioniert!
>
> Nur sehe ich noch nicht den Fehler, warum das in der main nicht
> funktioniert, schließlich will ich ja bei erweitertem Programm nicht
> alles im ISR machen.

Ich seh dein jetziges Programm nicht.
Aber
cnt muss volatile sein. Und es sollte ein uint8_t sein. Mit einem 
uint16_t hast du das Problem des atomaren Zugriffs.

von Fabian B. (fanick)


Lesenswert?

dann ist es das ein Problem mit uint16_t. Schade, ich hatte gehofft ich 
muss nicht noch eine überlaufende cnt variable in betracht ziehen.

Ich schreibe das gleich nochmal neu zusammen, teste und lade dann 
nochmal zur Vollständigkeit hoch.

von Karl H. (kbuchegg)


Lesenswert?

Fabian B. schrieb:
> dann ist es das ein Problem mit uint16_t. Schade, ich hatte gehofft ich
> muss nicht noch eine überlaufende cnt variable in betracht ziehen.

Das hat mit Überlauf nichts zu tun. Die Sache ist wesentlich 
unangenehmer. Vergleichbar mit der Situation in der du steckst, wenn du 
eine Geschichte in einem Buch liest und während du aufs Klo gehst, 
tauscht jemand das Buch aus. Dann passt die Fortsetzung der Geschichte 
nicht zu dem, was du vor dem Klogang gelesen hast.

Und es muss nicht das Problem sein. Es könnte es sein.

>
> Ich schreibe das gleich nochmal neu zusammen, teste und lade dann
> nochmal zur Vollständigkeit hoch.

Das ist IMMER gut.
Wenn du das Programm veränderst, dann sehen wir das nicht. Unser 
WIssenstand ist immer die letzte Programmversion, die du postest.

von Fabian B. (fanick)


Angehängte Dateien:

Lesenswert?

So ich hab nochmal eine kompakte, leider nicht funktionierende Datei in 
den Anhang gepackt.

Ich hab nun hoffentlich das mit den Konstanten usw. vernünftig 
berücksichtigt und den Quelltext so kurz wie möglich gehalten.

Ich hab mal scherzweise probiert mit
1
ISR(TIMER1_OVF_vect) {
2
  cnt++;
3
  MOTOR = speed_normal[cnt];
4
}
und habe erwartet, dass der Motor die Stufen schneller wird, bis dann 
eben das Array nicht mehr definiert ist.
Stattdessen wird der Motor mal schneller mal langsamer, aber meine 
Schritte erkenne ich da nicht.

Nochmals danke für die ganze Hilfe, ich habe nicht erwartet, dass ich so 
große Probleme mit einem eigentlich relativ einfachem Problem :(

von holger (Gast)


Lesenswert?

>Ich hab mal scherzweise probiert mit
>
>ISR(TIMER1_OVF_vect) {
>  cnt++;
>  MOTOR = speed_normal[cnt];
>}


Das ist echt ein Scherz. Wie viele Elemente
hat speed_normal[]? Und wie schnell zählt cnt?
Wann passt der Index nicht mehr für das Array?
Wann greifst du dann über cnt ins Klo?

von Fabian B. (fanick)


Lesenswert?

holger schrieb:
> Das ist echt ein Scherz.

So scherzweise doch wohl auch hoffentlich wieder nicht ;-)

Gemäß http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer habe 
ich an 4,2 Sekunden pro Timer Overflow gedacht und dementsprechend auch 
rund 20 Sekunden ein vernünftiges Verhalten erwartet.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@  Fabian B. (fanick)

>So ich hab nochmal eine kompakte, leider nicht funktionierende Datei in
>den Anhang gepackt.

Du brauchst nur einen Timer, der kann PWM und Zeitbasis gleichzeitg 
erzeugen. Siehe Anhang.

von Fabian B. (fanick)


Lesenswert?

Das Programm macht bei mir 2,5 sek lang nichts, geht dann auf langsame 
Geschwindigkeit (Geschwindigkeit 40) und dann dauerhaft auf einer 
"mittleren" Geschwindigkeit, entsprechend etwa 80, dem Mittelwert der 
Geschwindigkeitsstufen.
Im Simulator funktioniert es allerdings wiedermal.




Mit den 2 Timern wollte ich mir die einfache Möglichkeit zur Erweiterung 
bzw Timing im Sekunden/Minuten Bereich für andere Anwendung abseits von 
dem PWM lassen.

von Karl H. (kbuchegg)


Lesenswert?

Fabian B. schrieb:
> Das Programm macht bei mir 2,5 sek lang nichts, geht dann auf langsame
> Geschwindigkeit (Geschwindigkeit 40) und dann dauerhaft auf einer
> "mittleren" Geschwindigkeit, entsprechend etwa 80, dem Mittelwert der
> Geschwindigkeitsstufen.
> Im Simulator funktioniert es allerdings wiedermal.

Der Simulator hat aber auch keinen realen Motor, der eine 
Mindestspannung braucht um erst mal die Haftreibung zu überwinden und 
der träge Masse hat um den Rotor zu beschleunigen bzw. abzubremsen.
In deinem Simulator hat der simulierte Motor auch nicht die 
Eigenschaften Bürstenfeuer zu erzeugen, welche den µC zum Absturz 
bringen können. Dein simulierter Motor bzw. der simulierte µC hat auch 
keine Probleme mit der SPannungsversorgung bzw. fehlenden 
Blockkondensatoren bzw. fehlenden Entstörkondensatoren am Motor. Er hat 
weder die Eigenschaft, dass sein simulierte Versorgungsspannung 
einbricht, noch dass der Motor Störspikes einkoppelt.

von Fabian B. (fanick)


Lesenswert?

Es scheint die einzige Möglichkeit zu sein. Die Programme laufen ja 
vernünftig.

Ich baue in den nächsten Tagen die Schaltung auf meinem Breadboard neu 
auf und teste weiter, vermutlich ist ja doch irgendwas verschaltet.

Danke auf jeden Fall an alle die geholfen haben!

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.