Hallo Zusammen,
zunächst, ich habe leider (noch) kein Setup und kann meine "Behauptungen" daher nicht "beweisen"; die folgenden Bemerkungen basieren auf allgemein gültigen Regeln und Grundlagen, manche würden es als "reine Theorie" bezeichnen (abtun?), aber es ist dann doch oft so dass diese allgemeinen Regeln und Grundlagen tatsächlich auch in der Praxis gelten, und daher nehme ich für meinen Teil zumindest darauf aufbauende Schlussfolgerungen ernst. Aber bitte, zerreist es mit Freude, macht mir nichts
Ich habe mir den Code, insb. die Regelung nochmals genauer betrachtet, und IMHO enthält sie einige Designfehler.
- Vielleicht am wichtigsten, der Algorithmus zum Verwerten des Beschleunigungssensors (bzw. dessen Messwerte natürlich) funktioniert so wie implementiert nur wenn keine Eigenbeschleunigungen des Copters vorliegen. Der Winkel wird nämlich direkt aus den Messwerten berechnet. Damit ist sofort das von verschiedenen Leuten berichtete Abdriften bei langen Kurven etc erklärt. Der Effekt müsste auch genauso auftretten, wenn der Kopter in die quer oder längs (vorwärts/rückwärts) Richtung beschleunigt wird. Und der Effekt müsste um so stärker sein je größer accelWeight ist, womit die Beobachtung erklärt wäre dass dieser wert sehr klein gewählt werden sollte.
EDIT: siehe henry's Post zuvor...
Die einfachste Lösung wäre eines der Standardverfahren zum data fusing, z.B. ein Komplementär-Filter, bei dem nur die niederfrequenten Anteile durchgelassen werden (es ist zwar ein LPF für die ACC Werte eingebaut, aber das Filter ist nicht komplementär).
- Der Regelwert für den Regler wird als z.B.
gyroRoll = gyroRoll + config.accelWeight * (rollAngleACC - rollSetpoint)* fabs(rollAngleACC - rollSetpoint) /sampleTimeACC;
gebildet, d.h. die Drehraten und Winkel werden (gewichtet) zusammengerechnet. Im Regler wird nacher so etwas wie P + I +D gebildet. Da nun aber Drehraten und Winkel über eine Ableitung zusammenhängen, hat man hier eine Vermischung. Vereinfacht, symbolisch, um zu sagen was ich meine, P*(Drehrate+Winkel) + I*Sum(Drehrate+Winkel). Funktional kein Problem, nur wird dann das Einstellen der Parameter extrem unintuitiv, weil z.B. eine Änderung von P gleichzeitig, auf die Regelgröße betrachtet, den Proportional (~1) und Integralanteil (~1/s) verändert. Damit ist evtl. das schwierige Einstellen begründet.
Die einfachste Lösung wäre ein sinnvolles Data fusing.
Den Vorschlag statt P+I+D P*(1+I+D) für eine einfacherer Einstellbarkeit zu benutzen wiederhole ich an der Stelle gleich nochmal.
- Die Beschleunigungswerte werden nur alle ca. 50ms gelesen und zusätzlich noch mit einem 1:10 LPF gefiltert, die Zeitkonstante ist also 500 ms. Hinzukommt ein kleiner Wert für accelWeight. Damit ist erklärt warum die Initialisierung beim Start, so wie es berichtet wurde, teils sehr lange dauert.
Die einfachste Lösung wäre eine dedizierte Initialisierungsroutine.
- Der Vorschlag MAX PWM solange verkleinern bis der Motor schwächelt ist aus reglertheoretischer Sicht Unsinn.
Es ist an dieser Stelle interessant sich die GUI von AlexMos' Teil anzusehen... einige (wichtige?!) Unterschiede werden da klar deutlich...
OK, gut gebrüllt, werdet ihr nun sagen (zu Recht), warum hast du dann den Code nicht gleich verbessert? Antwort: weil ich leider (noch) kein Setup habe, und weil das was nun die beste Verbesserung ist doch am Besten in der Praxis getestet wird
LOL
Als quick&dirty patch für die Eiligen könnte ich vorschlagen Main so zu ändern
/**********************************************/
/* Main Loop */
/**********************************************/
int count=0;
int _count= 200;
void loop()
{
:
:
:
if( _count ){
gyroRoll = gyroRoll + 100 * config.accelWeight * (rollAngleACC - rollSetpoint)* fabs(rollAngleACC - rollSetpoint) /sampleTimeACC;
gyroPitch = gyroPitch + 100 * config.accelWeight * (pitchAngleACC - pitchSetpoint)* fabs(pitchAngleACC - pitchSetpoint) /sampleTimeACC;
_count--;
}
:
}
Der Effekt ist einfach das in den ersten 10 Sekunden accelWeight groß gesetzt wird um das Initialisieren zu beschleunigen, und anschliessend auf Null gesetzt wird um nur noch die Gyrowerte in der Regelung zu benutzen (eine Driftkorrektur durch den Beschleunigungssensor gibts dann nicht mehr).
cheers
Olli