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
@ 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.
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
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..
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.
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.
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!
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.
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.
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.
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.
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 :(
>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?
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.
@ 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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.