Tag zusammen, ich arbeite im Moment mit dem Attiny25 und der 16MHz internen Clock. Mit dem Controller werte ich Signale im 10-30µs Bereich aus. Im Prinzip funktioniert das ganze wie eine Art Servoregelung, nur dass das Signal kein typisches Servosignal ist, sondern ein 9-Bit Signal mit diesen µs Pegeln. Der Ablauf des Controllers ist folgender: -Signal einlesen und auswerten (Sollwert) -A/D Wandlung für die Ist-Position des Motors -Regelung und wieder von vorne. Soweit klappt das ganze schon ganz gut, nur irgendwie hab ich das Gefühl das die Regelung dabei zu langsam von statten geht. Der Motor zittert ein wenig beim einregeln und dieses Zittern häte ich gerne weg. Nun ist meine Frage jemand einen Controller von der Größe des Attiny25 kennt, der mehr als 16MHz interne Clock besitzt? Einen externen Quarz kann ich wegen Platzmangel leider nicht verwenden. Eine andere Frage wäre noch ob es etwas bringen würde, das Programm in Assembler anstatt C zu schreiben? Über ein Paar Tips würd ich mich freuen. Gruß Kuen
Schau mal das du nicht die CHKDIV/8 Fuse gesezt hast (weiß nicht ob der Tiny sowas besizt) und lad am besten auch mal die Korrekturwerte des internen RC Ozilators. Achja ASM kann natürlich was bringen gerade wenns Zeitkritisch ist...
Hmm ja, prinzipiell gibt es noch 20 MHz Atmel Controller. Da das aber nicht viel mehr ist, kann es durch optimieren deines Codes möglich sein, dass du mehr raus holst. Wenn du mit AVR-GCC proggst, stell die Codeoptimierung mal auf "Speed". Ansonsten poste mal dein Programm. Grundsätzlich ist es möglich mit ASM schnellere Programme zu schreiben -Wenn du weisst wie und es dir antun willst.
Wenn der Motor zittert, kann das auch an ungünstig eingestellten Regelparametern liegen. Ich denke, dass Deine Regelung schon schnell genug ist. Vielleicht auch ein Software-Fehler?
>Da das aber nicht viel mehr ist
25% mehr ist schon einiges.
Ich denke durch Software-Optimierung kann man vielleicht mehr als die 25% rausholen. Bis jetzt habe ich es immer geschafft, auch wenn es auf den 1. Blick hoffnungslos aussieht. Poste doch mal deinen Code. Ich denke die Leute werden dir bestimmt helfen und Optimierungspotential aufzeigen.
Morgen, erst eimal vielen Dank für eure Antworten. Also das CHKDIV/8 Fuse ist nicht gesetzt. Der Controller läuft mit den 16MHz, das hab ich mir am Oscar angeschaut. Zittern tut der Motor nur, wenn er in Position fährt, aber das liegt denke ich am über bzw. unter Regeln. Wenn er die Position dann erreicht hat ist das Zittern weg. Hab den Code mal angehängt, vielleicht habt ihr ja ein paar Verbesserungsvorschläge für mich. Gruß Kuen
@ Kuen (Gast) >Hab den Code mal angehängt, vielleicht habt ihr ja ein paar >Verbesserungsvorschläge für mich. Pulsdauer = TCNT0; Das würde ich als ERSTE Anweisungh in den INterrupt schreiben. Nur so hat man einen konstanten Zeitbezug zwischen externer Flanke an INT0 und dem Zähler. Bei dir sind noch die Abfragen davor, die je nach Zweig unterschiedlich lange dauern. Damit kommt es zu einem Messfehler. MFG Falk
> Wenn der Motor zittert, kann das auch an ungünstig eingestellten > Regelparametern liegen. Das wird mit Sicherheit der Fall sein. Das einzige was an so einer Regelung schnell sein muss ist die Abtastung des Istwertes von den Winkelencodern und auch nur deshalb weil die bei Maximalgeschwindigkeit mithalten muss. Der eigentliche Regler kann sehr langsam sein. Olaf
@Falk Danke für den Tip! @Olaf >> Wenn der Motor zittert, kann das auch an ungünstig eingestellten >> Regelparametern liegen. > Das wird mit Sicherheit der Fall sein. Aber in wie fern. Im Prinzip ist die Regelung ja nur ein Soll- Istwert Vergleich. Das ganze läuft ja so ab: -Sollwert einlesen -Istwert einlesen -Vergleichen -Regeln Wie kann ich da die Abtastung des Istwertes beschleunigen? Hab das AD-Wandeln mal etwas beschleunigt indem ich den Wandler etwas schneller getaktet hab. Bei 8-Bit Auflösung dürfte es dabei eigentlich keine Probleme geben. Bringt aber keine wesentliche Verbeserung. Was könnte ich noch optimieren?
Was für ne Regelung hast du denn? P, PI, PID oder PD? Spiel einfach mal mit den einzelnen Parametern.
Wenn ich es richtig verstehe, Regelst du, wenn c=0. c wird vom externen Interrupt auf 0 gesetzt. Wann und wieviel Mal pro Sekunde wird c=0 ? Kann es sein das du zu schnell regelst? Vielleicht mal eine Totzeit einbauen? Sehe ich es richtig, dass du keine P(I)(D) Regelung verwendest sondern einfach nur auf Schwellwerte schaust und somit eine gewisse Hysterese hast?
@ Kuen (Gast) >Aber in wie fern. Im Prinzip ist die Regelung ja nur ein Soll- Istwert >Vergleich. Wenns soooo einfach wäre . . . ;-) Reglerparametrierung ist eine Wissenschaft für sich. >Das ganze läuft ja so ab: >-Sollwert einlesen >-Istwert einlesen >-Vergleichen Das ist relativ einfach >-Regeln Hinter diesen kleinen Wort steckt eine Wissenschaft! >Wie kann ich da die Abtastung des Istwertes beschleunigen? Wozu? Du weisst doch gar nicht wodurch das Ruckeln verursacht wird. >keine Probleme geben. Bringt aber keine wesentliche Verbeserung. Was >könnte ich noch optimieren? Die Parameter. Wobei ich nicht so recht in deinem Code durchsteige. Deine Stellgrösse ist rein digital in motor(), wenn ich das recht sehe ist da reines ON/OFF mit einer Vollbrücke, nicht wahr? Du hast keinen Filter für deine Istwerte, und der Regelalgorithmus erschliesst sich mir auch nicht so wirklich. MfG Falk
Es ist ein Zweipunktregler und hat keine Regelparameter. Es gibt nur den Ist- und den Sollwert. > Wann und wieviel Mal proSekunde wird c=0 ? Also c wird immer zwischen den Signalpegeln 0. Ein komplettes Signal dauert ca. 1,5ms. Zwischen den einzelnen Pulsen des Signals hat der Controller ca. 120µs Zeit die AD-Wandlung und die Regelung zu machen. Zwischen den Signalen gibt es eine Pause von ca. 60ms in der auch gewandelt und geregelt wird. >Sehe ich es richtig, dass du keine P(I)(D) Regelung verwendest sondern >einfach nur auf Schwellwerte schaust und somit eine gewisse Hysterese >hast? Ist richtig, hab schon überlegt eventuell mal ne PI-Regelung zu versuchen. Hatte auch mal irgendwo ne Seite gefunden wo die Regler für Mikrocontroller erklärt waren. RC-Wissen oder Kreatives Chaos, find die Seite leider nicht mehr wieder.
Ich steige bei deinem Code auch nicht ganz durch. Ich könnte mir aber vorstellen dass das Zittern von daher kommt: Du hast ja eine Hyterese von +-3 = 6 von max. 256. Das ist schon ziemlich viel und ich denke das verursacht das Zittern. Wahrscheinlich bist du auch viel zu schnell mit "Regeln", der Motor braucht auch seine Zeit, bis er den Sollwert erreicht hat.
Dann hast Du einen P-Regler gebaut bzw. programmiert und der Kollege P-Regler hat eine bleibende Regelabweichung. Das heißt, daß die Ausgangsgröße immer um den Sollwert herum schwankt. Darum wird der Motor zittern. Ich nehme mal an, daß ein PI-Regler dafür besser wäre, weil der Motor ja eine gewisse Totzeit hat. MfG Paul
>Die Parameter. Wobei ich nicht so recht in deinem Code durchsteige. >Deine Stellgrösse ist rein digital in motor(), wenn ich das recht sehe >ist da reines ON/OFF mit einer Vollbrücke, nicht wahr? Richtig! Also der Motor wird über einen Motortreiber gesteuert. Der brauch drei Eingangszustände. Zwei Zustände(Ausgänge PB0 und PB3) sagen der Treiber in welche Richtung der Motor drehen soll), der andere ist dauerhaft High und sagt Vollgas. Dabei gäbe es eventuell noch die Möglichkeit anstatt Vollgas die Geschwindigkeit über PWM zu regeln. >Du hast keinen Filter für deine Istwerte, und der Regelalgorithmus >erschliesst sich mir auch nicht so wirklich. Das mit den Filtern versteh ich nicht ganz? Der Regelalgorithmus ist aber Recht einfach. Es wird das Signal über den externen Interrupt eingelsen(Sollwert). Die Position des Motors wird vom AD-Wandler eingelsen(Istwert). Dann wird so geregelt: if((lenkung_ist <= (lenkung_soll +3))&&(lenkung_ist >= (lenkung_soll - 3))) { PORTB &= ~(1 << PB3); PORTB &= ~(1 << PB0); } if((lenkung_ist +3) < (lenkung_soll)) { PORTB |= (1 << PB3); PORTB &= ~(1 << PB0); } if((lenkung_ist -3) > (lenkung_soll)) { PORTB |= (1 << PB0); PORTB &= ~(1 << PB3); } es wird also immer der Ist und Sollwert verglichen. In dem einen Fall dreht der Motor rechts rum, im anderen links rum. Sind sie "gleich"(+-3)" bleibt der Motor stehen. Wenn ich die Hysterese von +-3 kleiner mache, wird das Zittern stärker.
Ok, du willst bei 16MHz nen Regelintervall von 10-30µs. hast also pro Intervall 160-480 Taktzyklen. Wenn du wirklich so nen Intervall willst, würde ich mal in Assembler schreiben. In C halte ich das für grenzwertig. Schau mal auf die Atmel-Seite, da gibbet ne AN für nen PID-Regler. Is nich das optimale, aber sollte reichen. nen Tiny zu verwenden halte ich auch für gewagt, weil keinen multiplikator...
Also ich würde eine PI-Regelung machen und den Sollwert über PWM, auch 8-Bit, an den Treiber ausgeben.
@ Kuen (Gast) >dauerhaft High und sagt Vollgas. Dabei gäbe es eventuell noch die >Möglichkeit anstatt Vollgas die Geschwindigkeit über PWM zu regeln. Das würde ich mal nicht aus den Augen verlieren wollen. >>Du hast keinen Filter für deine Istwerte, und der Regelalgorithmus >>erschliesst sich mir auch nicht so wirklich. >Das mit den Filtern versteh ich nicht ganz? PID Regler wirken wie ein Filter, dadruch wird die Reglung besser. > Der Regelalgorithmus ist >aber Recht einfach. Es wird das Signal über den externen Interrupt >eingelsen(Sollwert). Die Position des Motors wird vom AD-Wandler >eingelsen(Istwert). Du willst also ein Servo nachbauen. OK. >"gleich"(+-3)" bleibt der Motor stehen. Wenn ich die Hysterese von +-3 >kleiner mache, wird das Zittern stärker. Scheint so, dass sich Soll und Istwert überholen, durch das harte Anfahren vom Motor -> Zittern. @ Lars Kollros (Gast) >Ok, du willst bei 16MHz nen Regelintervall von 10-30µs. hast also pro >Intervall 160-480 Taktzyklen. Ich glaube kaum, dass für diese Servostuerung 30us Zyklus gebraucht werden. Ich tippe mal, dass 1ms locker reicht. Aber dazu muss konstant im 1ms Raster geregelt werden! Das sehe ich nicht! Dazu sollte man einen Timer verwenden. Allerding würde ich dann die Pulsbreitenmessung besser mit ICP machen, das stresst die CPU WESENTLICH weniger. MFG Falk
Also wie würdet ihr denn den Ablauf gestalten? Nach den ganzen Beiträgen würde ich nun wie folgt vorgehen: -Timer Compare Interrupt erzeugen welches alle 2ms einen Interrupt ausführt. In diesem Interrupt würde ich dann die Regelung machen. (Nur welche? Zweipunkt PI?) Gut, das kann man ja dann ausprobieren. -Zwischen diesen 2ms genau einmal das Signal einlesen(Sollwert) und einmal AD-Wandeln(Istwert).
> Ich glaube kaum, dass für diese Servostuerung 30us Zyklus gebraucht > werden. Ich tippe mal, dass 1ms locker reicht. Diese Einschatzun teile ich. :-) Uebelege doch mal wie schnell sich die Masse deines Motors ueberhaubt bewegen kann. > In diesem Interrupt würde ich dann die Regelung machen. (Nur welche? > Zweipunkt PI?) Gut, das kann man ja dann ausprobieren. Das Problem ist nicht der Regler, ein PI-Regler ist da sicher erstmal ein guter Anfang, das Problem sind die Regelparameter. Olaf
Das Signal kommt ja nur alle 60ms. Aber in der Zeit kann ich ja trotzdem den Istwert einlesen und Regeln. Dann muss nur das Timing passen, dass das Signal auch alle 60ms eingelsen wird und der Interrupt da nicht zwischen haut.
@ Kuen (Gast) >Das Signal kommt ja nur alle 60ms. Aber in der Zeit kann ich ja trotzdem >den Istwert einlesen und Regeln. Dann muss nur das Timing passen, dass Sicher. >das Signal auch alle 60ms eingelsen wird und der Interrupt da nicht >zwischen haut. Lässt sich machen. Wie gesagt, ich würde ICP nehmen. MFG Falk
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.