Pętle kontrolne PID z dużymi i nieprzewidywalnymi anomaliami


10

Krótkie pytanie
Czy istnieje wspólny sposób radzenia sobie z bardzo dużymi anomaliami (rząd wielkości) w obrębie poza tym jednolitego regionu kontrolnego?

Tło
pracuję nad algorytmem sterowania, który napędza silnik w ogólnie jednolitym obszarze sterowania. Przy braku / minimalnym obciążeniu kontrola PID działa świetnie (szybka reakcja, przeregulowanie od niewielkiego do zerowego). Problem, na który wpadam, to zwykle jest co najmniej jedna lokalizacja wysokiego obciążenia. Pozycja jest ustalana przez użytkownika podczas instalacji, więc nie ma rozsądnego sposobu, aby wiedzieć, kiedy / gdzie się spodziewać.

Kiedy dostrajam PID do obsługi miejsca o dużym obciążeniu, powoduje to duże przesady w obszarach nieobciążonych (czego się w pełni spodziewałem). Podczas gdy przekraczanie środkowego odcinka drogi jest w porządku , nie ma mechanicznych twardych ograniczników na obudowie. Brak ograniczników oznacza, że ​​każde znaczące przekroczenie może / powoduje odłączenie ramienia sterującego od silnika (w wyniku czego powstaje martwa jednostka).

Rzeczy, które prototypuję

  • Zagnieżdżone PID (bardzo agresywne, gdy daleko od celu, konserwatywne, gdy w pobliżu)
  • Naprawiono wzmocnienie, gdy jest daleko, PID, gdy blisko
  • Konserwatywny PID (działa bez obciążenia) + sterowanie zewnętrzne, które sprawdza, czy PID utknie i zastosuje dodatkową energię do momentu: osiągnięcia celu lub wykrycia szybkiego tempa zmian (tj. Opuszczenia obszaru wysokiego obciążenia)

Ograniczenia

  • Określono pełną podróż
  • Nie można dodać przystanków (w tym momencie)
  • Błąd prawdopodobnie nigdy się nie wyzeruje
  • Wysokie obciążenie można było uzyskać przy skoku mniejszym niż 10% (co oznacza brak „rozruchu”)

Odpowiedzi:


2

Obliczenia błędów wydają się nie kumulować błędu podczas pracy z terminem pochodnym i możesz to zmienić, ponieważ tylko termin pochodny jest w stanie reagować na szybkie zmiany w procesie.

Jeśli dobrze to zrozumiałem, twój kod

// Determine the error delta
dE = abs(last_error - new_error);
last_error = new_error;

zawsze obliczy warunek kontrolny na podstawie bieżącego błędu, który jest tradycyjnym sposobem implementacji PID. Jest w porządku, ponieważ I termin powinien i tak zająć się nagromadzonym błędem.

Miałem jednak klienta, który wpadł na następujący pomysł, który możesz wypróbować. Ponieważ masz część krzywej procesu, w której potrzebne są bardziej agresywne zmiany, możesz pozwolić, aby nawet błąd części D kumulował się:

if(TD)                                                 // Calculate D term
{  
   Last_C += (Error - Last_C) / TD;                    // D term simulates
   Dterm = (Error - Last_C) * KD;                      // capacitor discharging
}
else    
   Dterm = 0;                                          // D term is OFF (TD is 0)

Warto tutaj zwrócić uwagę na dwie interesujące rzeczy:

  • Wartość TD nie jest przyrostem pochodnej (czyli KD), ale czasem pochodnej, stałą użytkownika, która kontroluje czas gromadzenia się błędu. Jeśli był ustawiony na zero, część D PID jest wyłączona, niezależnie od ustawionej wartości wzmocnienia KD.

  • Zwróć uwagę, w jaki sposób bieżący błąd został wykorzystany do „naładowania” wartości Last_C przed przeniesieniem jej do obliczenia części D. Zmienna Last_C działa jak kondensator, narastałaby, gdy błąd był duży, tak że twoja część pochodna działałaby również na podstawie niedawnej „historii” błędu, a następnie (gdy błąd był mniejszy) tej „historii” „rozładuje się jak kondensator.

Oczywiście, powinieneś ograniczyć całkowitą moc wyjściową w sposób, w jaki prawdopodobnie już to robisz (resetowanie przed windą, automatyczne uruchamianie bezumienne do ręcznego przesyłania i inne zwykłe rzeczy).

Mogę opublikować więcej szczegółów na temat innych warunków mojego algorytmu PID, jeśli uznasz to za przydatne, ale możesz spróbować tego i zobaczyć, co się stanie. Przez lata dobrze służył mojemu klientowi.


Dzięki za wkład. Będę musiał spróbować. Na pierwszy rzut oka wydaje się to mieć sens.
Adam Lewis,

Rozumiem, więc masz wkład w składniku D w swoim „głównym” PID plus to, co wykrycie utknięcia wprowadza do obliczeń.
Drazen Cika 12.03.13

1
To jest poprawne. PID's Dterm jest używany, choć niezbyt agresywny, podczas strojenia. Jeszcze trudniejsze jest to, że ładunek może się uwolnić w bardzo krótkim czasie. IE połączenie jest odłączone. To nagłe usunięcie siły powoduje duże przekroczenia, gdy do sił utknięcia zostanie zastosowana dowolna funkcja wygładzania (sumowania).
Adam Lewis,

Podstępny problem, ciekawie byłoby wiedzieć, jak dobrze poradziłby sobie z tym algorytm rozmytej logiki. Przynajmniej mógłbyś w większym stopniu wykorzystać doświadczenie związane z problemami w algorytmie, zamiast ograniczać się do standardowych rozwiązań. W każdym razie, powodzenia z tym :-)
Drazen Cika

1

Wstępne rozwiązanie

stalled_pwm_output = PWM / | ΔE |

PWM = maksymalna wartość PWM
ΔE = ostatni błąd - nowy błąd

Początkowa zależność z powodzeniem zwiększa moc wyjściową PWM w oparciu o brak zmian w silniku. Przykładowy wynik przedstawiono na poniższym wykresie.

Takie podejście powoduje, że utknął nieagresywny PID. Ma jednak niefortunny (i oczywisty) problem, że gdy nieagresywny PID jest w stanie osiągnąć wartość zadaną i próbuje spowolnić, utknięty_pwm_output rośnie. To przyspieszenie powoduje duże przeregulowanie podczas podróży do pozycji nieobciążonej.

1 / ΔE vs ΔE

Aktualne rozwiązanie

Teoria

stalled_pwm_output = (kE * PID_PWM) / | ΔE |


kE = stała skalowania PID_PWM = bieżące żądanie PWM z
nieagresywnego PID ΔE = ostatni błąd - nowy błąd

Moja obecna relacja nadal wykorzystuje koncepcję 1 / ΔE, ale wykorzystuje nieagresywne wyjście PID PWM do określenia wyjścia stall_pwm_output. Pozwala to PID na dławienie wyjścia stall_pwm_output, gdy zaczyna zbliżać się do docelowej wartości zadanej, ale pozwala na 100% mocy wyjściowej PWM po zablokowaniu. Stała skalowania kE jest potrzebna, aby PWM dostał się do punktu nasycenia (powyżej 10 000 na poniższych wykresach).

Pseudo kod

Zauważ, że wynik z cal_stall_pwm jest dodawany do wyjścia PID PWM w mojej obecnej logice sterowania.

int calc_stall_pwm(int pid_pwm, int new_error)
{
    int ret = 0;
    int dE = 0;
    static int last_error = 0;
    const int kE = 1;

    // Allow the stall_control until the setpoint is achived
    if( FALSE == motor_has_reached_target())
    {
        // Determine the error delta
        dE = abs(last_error - new_error);
        last_error = new_error;

        // Protect from divide by zeros
        dE = (dE == 0) ? 1 : dE;

        // Determine the stall_pwm_output
        ret = (kE * pid_pwm) / dE;
    }

    return ret;
}

Dane wyjściowe

Zatrzymane wyjście PWM Zatrzymane wyjście PWM

Należy zauważyć, że na wykresie zablokowanego wyjścia PWM nagły spadek PWM przy ~ 3400 jest wbudowaną funkcją bezpieczeństwa aktywowaną, ponieważ silnik nie był w stanie osiągnąć pozycji w określonym czasie.

Nieobciążone wyjście PWM Wyjście PWM bez obciążenia


1

Nie mówisz, co kontrolujesz ... prędkość silnika? pozycja? Cokolwiek to jest, pierwszym krokiem byłoby określenie, jaki byłby dopuszczalny błąd. Na przykład, jeśli kontrola dotyczy prędkości, można ustawić błąd maksymalny w granicach 1% wartości docelowej. Bez zdefiniowania dopuszczalnego błędu nie można ustalić, ile rozdzielczości potrzeba dla ADC lub liczby PWM. Bez tego kompensacja PID mogłaby być idealna, ale nadal miałaby ograniczenia oscylacji cyklu.

Następnie musisz znać dynamikę systemu otwartej pętli. Bez tego nie możesz wiedzieć, jakie wzmocnienia są potrzebne dla proporcjonalnej (P), całkowej (I) i pochodnej (D) części pętli. Możesz zmierzyć dynamikę krokiem wejściowym (zmiana poziomu napędu lub PWM) lub zmiana obciążenia (wydaje się, że byłoby to dla Ciebie odpowiednie).

Za pomocą zmiany błędu między cyklami, w mianowniku kontrolnego algorytmu, w celu zmodyfikowania wartości PWM zapewnia się, że pętla nigdy się nie ustabilizuje. Zapewnia to ograniczenie oscylacji cyklu w sterowaniu. Większość klientów nie zniesie tego.

Część P pętli zajmuje się natychmiastowym błędem (natychmiast reaguje na błąd). Ale będzie miał skończony zysk, więc zostanie trochę błędu. Część I pętli reaguje powoli w czasie, aby zastosować nieskończone wzmocnienie (nieskończony czas dla nieskończonego wzmocnienia), aby skorygować ten błąd, który został pozostawiony przez część P.

Ponieważ część I jest wolna, może wyjść z fazy z korektą potrzebną do minimalizacji błędów, nawet jeśli masz dla niej odpowiednie wzmocnienie. Tak więc zostaje zlikwidowany, a powrót do zdrowia zajmuje dużo czasu. Lub pozostaje w opozycji do części P.

Najlepszym sposobem radzenia sobie z likwidacją jest ograniczenie maksymalnej wartości przechowywanej w integratorze do nieco więcej niż jest to konieczne do skorygowania błędu proporcjonalności w najgorszym przypadku. Jeśli integrator wychodzi poza fazę i jest w opozycji do P, najlepiej jest ustawić wartość integratora na zero. Algo można zaprojektować tak, aby wykrywało to i resetuje integrator w razie potrzeby.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.