Timer/PWM Problem an ATmega16

OP #3007397
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
Angehängte Dateien:
#3007457
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.
OP #3007686
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
Angehängte Dateien:
OP #3007941
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..
#3007965
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.
OP #3007992
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!
#3008007
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.
#3008019
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.
OP #3008060
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 :(
Angehängte Dateien:
Gast #3008066
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?
OP #3008094
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.
#3008099
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren