Ich versuche, einen motorisierten Fader (lineares Schiebepotentiometer) mit einem Arduino zu steuern.
Die PID-Regelung liefert gute Ergebnisse für das "Springen" zu einer bestimmten Zielposition, aber Tracking-Rampen sind ein Problem, sie sind überhaupt nicht reibungslos. Die Bewegung ist sehr ruckelig, egal was ich versuche.
Hier ist eine grafische Darstellung der Referenzposition, der gemessenen Position und der Motorleistung beim Verfolgen einer Rampe:
Und hier ist ein Video des gleichen Tests.
Auf kommerziellen Systemen scheint es viel flüssiger zu sein, siehe dies .
Details :
Der Motor - Fader eine ist Alpen RSA0N11M9A0K . Für den Antrieb verwende ich eine ST L293D H-Brücke, die von einem geregelten 10-V-Gleichstromnetzteil ( XL6009 ) gespeist wird .
Auf dem Arduino UNO (ATmega328P) verwende ich die Pins 9 und 10 mit einer PWM-Frequenz von 31,372 kHz, um es unhörbar zu machen (Timer1 mit einem Prescaler von 1 TCCR1B = (TCCR1B & 0b11111000) | 0b001
).
Das Potentiometer ist zwischen Masse und 5 V verdrahtet, wobei der Wischer wie üblich auf ADC0 geht.
Der Regler :
Ich verwende einen einfachen PID-Regler mit Anti-Windup, der mit einer Rate von 1 kHz aktualisiert wird (Ts = 1e-3 s):
float update(int16_t input) {
int16_t error = setpoint - input;
int16_t newIntegral = integral + error;
float output = k_p * error
+ k_i * newIntegral * Ts
+ k_d * (input - previousInput) / Ts;
if (output > maxOutput)
output = maxOutput;
else if (output < -maxOutput)
output = -maxOutput;
else
integral = newIntegral;
previousInput = input;
return output;
}
Der Ausgang des Reglers hat einen Wert von -127 bis 127. Der PWM-Ausgang wird wie folgt generiert:
const int8_t knee = 48;
uint8_t activation(int8_t val) {
if (val == 0)
return 0;
else {
return map(val, 0, 127, 2 * knee, 255);
}
}
void writeMotor(int8_t val) {
if (val >= 0) {
analogWrite(forward, activation(val));
digitalWrite(backward, 0);
} else {
analogWrite(backward, activation(-val));
digitalWrite(forward, 0);
}
}
Ich habe dem 7-Bit-PWM-Signal 48 hinzugefügt, weil der Motor dort mit 31 kHz beginnt, sich zu bewegen, und skaliere ihn dann auf eine 8-Bit-Zahl (weil die analogWrite
Funktion dies erwartet):
Was ich versucht habe :
Ich habe versucht, dem Eingang, dem Steuersignal, der Ableitungskomponente des PID-Reglers einen EMA-Filter hinzuzufügen, aber ohne Erfolg. Ich habe auch versucht, die Auflösung des Analogeingangs zu verringern, indem ich die Hysterese verwendet habe , um zu verhindern, dass er im Stillstand zwischen zwei Werten wechselt. Dies scheint nichts zu beeinflussen. Das Erhöhen des Zeitschritts auf 10 ms scheint ebenfalls nicht zu helfen.
Ich habe auch versucht, ein System in MATLAB zu identifizieren und es in Simulink zu optimieren (im Anschluss an diese Videoserie ). Ich habe ein Modell mit einer Anpassung von 91% erhalten, aber ich wusste nicht, wie ich mit den Nichtlinearitäten der Eingabe und Ausgabe des MATLAB-Modells umgehen sollte, wie sie sich auf die PID-Optimierung auswirken und wie sie auf dem Arduino implementiert werden.
Als letztes habe ich versucht, zwei verschiedene Steuerungen herzustellen: eine für große Sprünge in der Referenzposition und eine für kleine Fehler beim Verfolgen einer Rampe. Dies scheint ein bisschen zu helfen, denn dann kann ich den Integralkoeffizienten beim Verfolgen erhöhen, ohne das Überschwingen beim Springen zu erhöhen.
Durch Erhöhen der integralen (und proportionalen) Verstärkung tut der Motor jetzt immer etwas, auch wenn er stationär sein sollte und sich die Referenz nicht ändert. (Es bewegt sich nicht wirklich, aber Sie spüren, wie es vibriert.)
Ich habe praktisch keine abgeleitete Verstärkung, da eine Erhöhung über 1e-4 es noch ruckeliger zu machen scheint und ich keinen Unterschied zwischen 0 und bemerke 1e-4.
Ich vermute, dass es mehr Kraft benötigt, um statische Reibung zu überwinden, dann ist die dynamische Reibung geringer, so dass es überschießt, so dass es den Motor rückwärts antreibt und ihn wieder zum Stillstand bringt, dann muss es statische Reibung wieder überwinden, es schießt wieder vorwärts , etc.
Wie überwinden kommerzielle Controller dieses Problem?
Mein Hintergrund :
Ich bin in meinem dritten Bachelor-Jahr der Elektrotechnik und habe Kurse in Steuerungstheorie, digitaler Signalverarbeitung, LQR-Steuerung usw. besucht. Daher habe ich einige theoretische Hintergrundinformationen, aber ich habe Probleme, all diese Theorien auf diese anzuwenden dieses reale System.
Edit :
Ich habe die Open-Loop-Sensormessungen getestet, wie von laptop2d empfohlen, und bin ziemlich überrascht von den Ergebnissen: Bei hohen PWM-Frequenzen gibt es unangenehme Spitzen in den Messwerten. Bei 490 Hz gibt es keine.
Und das bei einem konstanten Arbeitszyklus, also kann ich mir nicht vorstellen, welche Geräusche ich bekomme, wenn der Motor die Richtung sehr schnell umkehrt.
Also muss ich einen Weg finden, dieses Rauschen herauszufiltern, bevor ich wieder an der Steuerung arbeite.
Edit 2 :
Ein exponentielles Filter für den gleitenden Durchschnitt war nicht ausreichend, um das Rauschen herauszufiltern.
Ich habe es mit Stangen in 0.25, 0.50 und 0.75 versucht. Kleine Pole hatten keinen großen Effekt, und größere Pole erhöhten die Latenz, sodass ich die Verstärkung verringern musste, um sie stabil zu halten, was zu einer schlechteren Gesamtleistung führte.
Ich habe einen 0,1-µF-Kondensator über das Potentiometer (zwischen Wischer und Masse) gelegt, und das scheint es zu bereinigen.
Im Moment funktioniert es gut genug. In der Zwischenzeit lese ich die Zeitung von Tim Wescott durch .
Vielen Dank für Ihre Hilfe.
This device is suitable for use in switching applications at frequencies up to 5 kHz.
Die elektrischen Eigenschaften auf Seite 3 schlagen jedoch ein absolutes Maximum von 690 kHz vor, wenn Sie alle Verzögerungen addieren. (unterste 4 Zeilen) Persönlich würde ich viel langsamer fahren, aber ich würde denken, dass 31kHz angemessen sein sollte ... ohne den Hinweis auf Seite 1.