PID-Steuerung des Motorfaders

Ich versuche, einen motorisierten Fader (lineares Schiebepotentiometer) mit einem Arduino zu steuern.
Die PID-Steuerung liefert gute Ergebnisse beim "Springen" zu einer bestimmten Zielposition, aber das Verfolgen von Rampen ist ein Problem, es ist überhaupt nicht glatt. Die Bewegung ist sehr ruckelig, egal was ich versuche.

Hier ist ein Diagramm der Referenzposition, der gemessenen Position und der Motorleistung beim Verfolgen einer Rampe:Eine Rampe verfolgen

Und hier ist ein Video desselben Tests.

Auf kommerziellen Systemen scheint es viel glatter zu sein, siehe hier .

Details :
Der Motorfader ist ein Alps RSA0N11M9A0K . Um es anzutreiben, verwende ich eine ST L293D H-Brücke, die von einem geregelten 10-V-DC-Netzteil ( 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 wird zwischen Masse und 5V verdrahtet, wobei der Schleifer wie üblich auf ADC0 geht.

Der Controller :
Ich verwende einen einfachen PID-Controller mit Anti-Windup, der mit einer Rate von 1 kHz aktualisiert (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 Controllers ist ein Wert von -127 bis 127. Der PWM-Ausgang wird wie folgt erzeugt:

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 48 zum 7-Bit-PWM-Signal hinzugefügt, weil dort der Motor mit 31 kHz anfängt, sich zu bewegen, und dann skaliere ich es auf eine 8-Bit-Zahl hoch (weil die Funktion das erwartet) analogWrite:PWM-Geschwindigkeit

Was ich versucht habe :
Ich habe versucht, dem Eingang, dem Steuersignal und der abgeleiteten Komponente des PID-Reglers einen EMA-Filter hinzuzufügen, aber ohne Erfolg. Ich habe auch versucht, die Auflösung des Analogeingangs zu verringern, indem ich Hysterese verwendete , 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 auch nicht zu helfen.

Ich habe auch versucht, eine Systemidentifikation in MATLAB durchzuführen und sie in Simulink zu optimieren (nach dieser Videoserie ). Ich habe ein Modell mit einer Anpassung von 91 % erhalten, aber ich wusste nicht, wie ich mit den Eingabe- und Ausgabe-Nichtlinearitäten des MATLAB-Modells umgehen sollte, wie sie sich auf die PID-Abstimmung auswirken und wie ich sie auf dem Arduino implementieren sollte.

Als letztes habe ich versucht, zwei verschiedene Controller zu erstellen: einen für große Sprünge in der Referenzposition und einen für kleine Fehler beim Verfolgen einer Rampe. Das scheint etwas zu helfen, denn dann kann ich den Integralkoeffizienten beim Nachführen erhöhen, ohne das Überschwingen beim Springen zu erhöhen.
Durch Erhöhen der integralen (und proportionalen) Verstärkung tut der Motor jetzt jedoch immer etwas, selbst wenn er stationär sein sollte und sich der Sollwert nicht ändert. (Es bewegt sich nicht wirklich, aber Sie können es vibrieren fühlen.)
Ich habe praktisch keine abgeleitete Verstärkung, weil eine Erhöhung auf mehr als 1e-4 es noch ruckeliger zu machen scheint, und ich bemerke keinen wirklichen Unterschied zwischen 0 und 1e-4.

Meine Vermutung ist, dass es mehr Kraft braucht, um die Haftreibung zu überwinden, dann ist die dynamische Reibung geringer, also schießt es über, also treibt es den Motor rückwärts, wodurch er wieder stoppt, dann muss es wieder die Haftreibung überwinden, es schießt wieder nach vorne , usw.

Wie überwinden kommerzielle Controller dieses Problem?

Mein Hintergrund :
Ich bin in meinem dritten Bachelorjahr in Elektrotechnik, ich habe Kurse zu Steuerungstheorie, digitaler Signalverarbeitung, LQR-Steuerung usw. besucht, also habe ich etwas theoretisches Hintergrundwissen, aber ich habe Probleme, all diese Theorien anzuwenden dieses reale System.


Bearbeiten :
Ich habe die Open-Loop-Sensormessungen getestet, wie von laptop2d empfohlen, und ich bin ziemlich überrascht von den Ergebnissen: Bei hohen PWM-Frequenzen gibt es böse Spitzen in den Messwerten. Bei 490 Hz gibt es keine.
Und dies bei einem konstanten Arbeitszyklus, daher kann ich mir nicht vorstellen, welche Art von Geräusch ich bekomme, wenn der Motor sehr schnell die Richtung umkehrt.

Geben Sie hier die Bildbeschreibung ein

Ich muss also einen Weg finden, dieses Rauschen herauszufiltern, bevor ich wieder mit der Arbeit am Controller beginne.

Bearbeiten 2 :
Die Verwendung eines exponentiellen gleitenden Durchschnittsfilters reichte nicht aus, um das Rauschen herauszufiltern.

EMA

Ich habe es mit Stangen in 0,25, 0,50 und 0,75 versucht. Kleine Stangen hatten nicht viel Wirkung und größere Stangen fügten zu viel Latenz hinzu, also musste ich die Verstärkungen verringern, um sie stabil zu halten, was zu einer schlechteren Gesamtleistung führte.

Ich habe einen 0,1-µF-Kondensator über dem Potentiometer (zwischen Schleifer und Masse) hinzugefügt, und das scheint es zu bereinigen.

Im Moment funktioniert es gut genug. In der Zwischenzeit lese ich den Artikel von Tim Wescott durch .
Vielen Dank für Ihre Hilfe.

Kannst du 31KHz PWM genau steuern?
@Hasanalattar: Nein, die Frequenzen, die ich verwenden kann, befinden sich im zweiten Diagramm (Prescaler von 1, 8, 64, 256, 1024). 4 kHz und 500 Hz sind hörbar, erzeugen also ein nerviges Piepsen, was ich gerne vermeiden möchte. Bleiben also 31 kHz, 120 Hz und 30 Hz. Und die letzten beiden sind zu langsam, denke ich. Die PWM-Auflösung beträgt 8 Bit, aber ich verwende weniger, da mein Steuersignal nur 7 Bit beträgt und ich nur PWM-Werte über 96 verwende.
Die von Ihnen verlinkte H-Brücke hat auf der Titelseite des Datenblatts: This device is suitable for use in switching applications at frequencies up to 5 kHz.Aber die elektrischen Eigenschaften auf Seite 3 deuten auf ein absolutes Maximum von 690 kHz hin, wenn Sie alle Verzögerungen addieren. (untere 4 Zeilen) Persönlich würde ich viel langsamer gehen, aber ich würde denken, dass 31 kHz angemessen sein sollten ... wenn da nicht der Hinweis auf Seite 1 wäre.
Dies setzt jedoch ein festes Tastverhältnis voraus. (oder ein "egal"-Tastverhältnis für die absolute Maximalfrequenz, um "einfach damit zu wackeln" - Sie werden feststellen, dass es asymmetrisch ist.) Hohe und niedrige Tastverhältnisse können einige sehr schmale Impulse erzeugen, also wie breit sind diese im Vergleich zu unten auf Seite 3?
Umkehrmotoren können problematisch sein, wenn Sie ein Spiel in Ihrem mechanischen System haben. Eine ratengesteuerte PID könnte in dieser Anwendung besser sein, es wäre auf jeden Fall einen Versuch wert, aber in einigen Fällen können sie lauter sein.
Ich bin mir nicht sicher, ob es Ihr Problem ist, aber wenn der Zeitstempel variieren kann, sollten Sie dem Integral Fehler * Ts hinzufügen, nicht nur Fehler, und das Integral nicht mit Ts multiplizieren. (Wenn Ts immer eine Konstante ist, spielt es keine Rolle)

Antworten (4)

Ein Steuersystem ist nur so gut wie sein Sensor, lassen Sie den Sensor im offenen Regelkreis laufen und entfernen Sie den Steuereingang. Erstellen Sie Ihre eigene Eingabe für den Sensor und schieben Sie ihn langsam (oder finden Sie einen Weg, ihn zuverlässig langsam zu schieben), während Sie Positionsdaten erfassen, um sicherzustellen, dass es nicht der Sensor ist. Wenn der Sensor verrauscht ist, verbessern Sie die Leistung des Sensors, indem Sie einen neuen Sensor kaufen oder ihn parallel schalten oder indem Sie die Ausgabe des Sensors filtern . Möglicherweise benötigen Sie einen Sensor mit höherer Auflösung.

Wenn der Sensor nicht laut ist, müssen Sie einen anderen Regelkreis verwenden. PIDs sind Systeme erster Ordnung und bei der Ratensteuerung nicht wirklich großartig.

Danke, es gibt tatsächlich viel Rauschen bei höheren PWM-Frequenzen, also muss ich einen Weg finden, das zu verbessern. Hast du zufällig einen Hinweis, wie man das macht?
Verwenden Sie einen Filter, mechanisch oder digital. Wenn Sie das nicht können, wäre es vielleicht gut, Sensoren parallel zu schalten. meta.stackexchange.com/questions/126180/…

Sie haben Recht, dass das Problem von Reibung oder möglicherweise einer Kombination aus Reibung und Spiel herrührt. Ihr Diagramm der Durchschnittsgeschwindigkeit gegenüber dem Arbeitszyklus für verschiedene Impulsbreiten ist charakteristisch für ein System mit Reibung. Dieses Dokument erklärt, was Sie sehen, und enthält ein Kompendium von Lösungen, die seit jeher zur Bewältigung der Probleme verwendet werden. Sie werden sie in Ihrem Lehrplan für Ingenieure nicht gesehen haben, weil sie schwer zu analysieren sind; Sie müssen im Grunde von Fall zu Fall mit ihnen herumspielen, um sie zum Laufen zu bringen.

Ich weiß nicht, was kommerzielle Controller tun, obwohl ich vermute, dass es eine Vielzahl von Lösungen gibt. Was ich in der Vergangenheit mit solchen Dingen gemacht habe, ist, wenn das Motorantriebssignal aus meinem PID-Regler unter einen bestimmten Schwellenwert fällt (in Ihrem Fall wahrscheinlich 60 bis 70), beginne ich, den Motorantrieb an dem Schwellenwert mit einer Pflicht zu pulsieren Zyklus, der den durchschnittlichen Antrieb gleich dem PID-Ausgang macht. Ich verwende dafür im Allgemeinen einen Sigma-Delta-Modulator, da er in sehr wenigen Zeilen implementiert werden kann, aber Sie können alles verwenden, was für Sie funktioniert.

Es scheint, dass das meiste Rauschen vom PWM-Antriebssignal kommt.

Haben Sie versucht, die ADC-Erfassung mit dem PWM-Zyklus zu synchronisieren? Die meisten Mikrocontroller haben eine Möglichkeit, die ADC-Erfassung per Timer auszulösen, sodass Sie immer am selben Punkt des Zyklus auslösen können.

Für das niedrigste Rauschen wäre die optimale Abtastposition direkt vor dem Einschalten der Stromversorgung des Motors, da dann etwaige Spitzen die längste Zeit hatten, sich zu beruhigen. Aber unabhängig von der Position werden durch die Synchronisierung der Erfassung Spitzen reduziert, da der Betrag des Offsets am gleichen Punkt des PWM-Zyklus ungefähr gleich bleibt.

Ich muss also einen Weg finden, dieses Rauschen herauszufiltern, bevor ich wieder mit der Arbeit am Controller beginne.

Sie könnten das Sensorrauschen (oder jede andere verrauschte Messung/Variable) im Code mit so etwas filtern (Tiefpassfilterung):

S gefiltert [ k ] = a S gefiltert [ k 1 ] + ( 1 a ) S roh [ k ]

Wo 0 << a 1 . Je näher an 1, desto glatter wird es aussehen, aber es fügt auch mehr Verzögerung hinzu, beginnen Sie beispielsweise mit einem Wert von 0,9 und sehen Sie, wie es sich verhält.

Ich habe das versucht, aber es reicht nicht aus, um die Spitzen loszuwerden, und es fügt zu viel Verzögerung hinzu.
@tttapa Ich verstehe. Welchen Wert für Alpha hast du probiert? (0.8,0.9) Es wird einige Abstimmungen erfordern, die Sie möglicherweise bereits durchgeführt haben, nur um sich zu wundern.
Ich habe meinen ursprünglichen Beitrag aktualisiert, um eine Darstellung der EMA-Filter hinzuzufügen, die ich ausprobiert habe. Ich habe auch 0,9 ausprobiert, und es war noch schlechter als 0,75, die Gewinne müssen wegen der Verzögerung viel niedriger sein. Ich denke, ich werde einen begrenzten EMA verwenden, um das ADC-Rauschen zu bereinigen, aber im Moment reicht der Kondensator aus.