-
Notifications
You must be signed in to change notification settings - Fork 0
SensorsModule
Ten plik definiuje klasę PIDController, która implementuje regulator PID (Proporcjonalno-Różniczkowo-Integralny) w kontekście systemów sterowania dynamicznego, najczęściej stosowanego w aplikacjach przemysłowych, robotyce, sterowaniach procesów technologicznych oraz systemach autonomicznych. Klasa PIDController działa jako komponent centralny w architekturze sterowania, zapewniając precyzyjne dopasowanie odpowiedzi systemu do zadanej wartości (setpointu) poprzez obliczanie odpowiednich wartości sterujących na podstawie błędu pomiarowego.
W większym kontekście systemowym, PIDController może być używany w ramach większego systemu sterowania, np. w mikrokontrolerach (np. Arduino, STM32), w systemach PLC, albo jako komponent w systemach sterowania typu embedded w kontenerach mikroserwisów (np. w systemach IoT). Klasa może być wykorzystywana w kontekście sterowania temperatury, obrotów silnika, położenia mechanizmu, lub innych wielkości fizycznych, które wymagają stabilnego i szybkiego reagowania na zmiany.
Klasa PIDController ma cykl życia zdefiniowany w sposób proceduralny, gdzie inicjalizacja odbywa się poprzez konstruktor, a następnie w pętli sterowania (np. w Update lub Loop) obliczane są nowe wartości sterujące. W systemach czasu rzeczywistego, może być wywoływana z określonym interwałem (np. co 10 ms), co wymaga odpowiedniego zarządzania pamięcią oraz konieczności optymalizacji obliczeń.
Klasa PIDController zawiera trzy główne parametry: Kp, Ki, Kd – odpowiednio współczynniki proporcjonalny, integralny i różniczkowy. Wartości te są ustawiane w konstruktorze lub dynamicznie poprzez publiczne właściwości (ProportionalGain, IntegralGain, DerivativeGain). Wartości te definiują charakterystykę regulatora:
-
Kp(proporcjonalny): Współczynnik, który determinuje natychmiastową reakcję regulatora na błąd. Im wyższyKp, tym szybsza reakcja, ale może to prowadzić do drgań. -
Ki(integralny): Współczynnik, który eliminuje błąd ustalony (offset). Pracuje na podstawie sumy błędów w czasie. Zbyt wysoka wartość może powodować przebięcia. -
Kd(różniczkowy): Współczynnik, który „przewiduje” przyszły błąd na podstawie zmiany błędu w czasie. Zmniejsza nadmiarowe drgania i poprawia stabilność.
Główne obliczenia odbywają się w metodzie Compute() (lub Update() w innych implementacjach), która oblicza wartość sterującą output na podstawie:
-
Błędu (
error): Różnica między wartością zadana (setpoint) a aktualną wartością pomiarową (input). -
Całkowitego błędu (
integral): Suma błędów z poprzednich kroków (z uwagi na czas, tzn.integral += error * dt). -
Zmiany błędu (
derivative): Różnica między bieżącym i poprzednim błędem, podzielona przez czas (derivative = (error - previousError) / dt).
Wzór PID:
output = Kp * error + Ki * integral + Kd * derivative
-
Pobranie danych wejściowych:
inputisetpointsą pobierane z zewnętrznego źródła (np. czujnika). -
Obliczenie błędu:
error = setpoint - input. -
Aktualizacja całki:
integral += error * dt. -
Obliczenie pochodnej:
derivative = (error - previousError) / dt. -
Obliczenie wyniku PID:
output = Kp * error + Ki * integral + Kd * derivative. -
Zapisanie poprzedniego błędu:
previousError = error.
W implementacji może być dodana logika zapobiegająca przepełnieniu integral (np. integral = clamp(integral, -maxIntegral, maxIntegral)). Dodatkowo, output może być ograniczony do zakresu outputMin i outputMax, aby zapobiec nadmiernemu wyjściu sterującemu (np. w przypadku silnika, który nie może wyjść poza zakres 0–255).
Klasa PIDController nie dziedziczy z żadnej klasy bazowej w podanym kodzie. Może być jednak rozszerzana w przyszłości, np. przez implementację interfejsu IController lub IControlLoop. Interfejs może wymagać metod takich jak Compute, Reset, SetSetpoint, co zapewnia elastyczność i możliwość wstrzykiwania różnych typów regulatorów (np. PID, LQR, fuzzy).
-
input: Typdouble– wartość aktualnego stanu systemu (np. temperatura, położenie). Zwykle pochodzi z czujnika. -
setpoint: Typdouble– wartość zadana, do której system ma dążyć. -
dt: Typdouble– czas od ostatniego obliczenia, wyrażony w sekundach. Istotny dla obliczeń całkowania i różniczkowania.
-
output: Typdouble– wartość sterująca, która może być np. przekazywana do silnika, przekaźnika lub innego elementu sterującego. -
integraliderivative: Wewnętrzne zmienne, nie są bezpośrednio zwracane, ale wpływają naoutput.
-
Kp,Ki,Kd: Współczynniki regulatora PID, ustawiane statycznie lub dynamicznie. -
integral: Akumulator błędów – zmienna typudouble, przechowująca sumę błędów w czasie. -
derivative: Zmienna typudouble, przechowująca pochodną błędu (zmianę w czasie). -
previousError: Zmienna typudouble, przechowująca błąd z poprzedniego kroku – potrzebna do obliczenia pochodnej. -
outputMin,outputMax: Ograniczenia wyjścia regulatora – zapobiegają nadmiernemu sterowaniu.
PIDController działa jak komponent sterowania w architekturze mikroserwisowej lub systemu sterowania typu embedded. Jest to wzorzec typu "Komponent sterowania", który może być wstrzyknięty do systemu sterowania w miejscu, gdzie potrzebne jest dopasowanie do wartości zadanej.
Wzorzec ten zapewnia:
-
Niezależność:
PIDControllernie wie, skąd pochodzą dane wejściowe ani co robi sterowanie – zapewnia tylko funkcję obliczeniową. - Elastyczność: Możliwość podmiany regulatora (np. z PID na fuzzy logic) bez zmiany reszty systemu.
- Testowalność: Można przeprowadzać testy jednostkowe z użyciem mockowanych danych.
W przypadku braku wzorca, kod może być zapisany w formie procedury (np. void ComputePID(...)), co utrudnia testowanie i utrzymanie. Wzorzec obiektowy (klasa) zapewnia modularność, łatwiejsze debugowanie i skalowalność.
-
public double Compute(double input, double setpoint, double dt): Metoda publiczna, zwracająca wartośćdouble. W C# typdoubleto 64-bitowa liczba zmiennoprzecinkowa, co zapewnia wysoką dokładność obliczeń. -
private double integral,private double derivative,private double previousError: Zmienne prywatne, zapobiegają nieautoryzowanemu dostępowi do stanu regulatora. -
public double ProportionalGain,public double IntegralGain,public double DerivativeGain: Właściwości publiczne (get/set), umożliwiające dynamiczną modyfikację parametrów PID – wykorzystuje się to w systemach z adaptacją PID (np. Auto-tuning). -
output = clamp(output, outputMin, outputMax): Funkcjaclampzapewnia, że wartośćoutputnie przekracza zakresu. Może być zaimplementowana jako:
public static double Clamp(double value, double min, double max)
{
return value < min ? min : value > max ? max : value;
}-
Przepełnienie całki (
integral): W przypadku długiego czasu działania i dużych błędów,integralmoże przekroczyć zakresdouble. W praktyce może to prowadzić do "windupu integralnego". Rozwiązaniem jest ograniczenieintegral(np.integral = clamp(integral, -maxIntegral, maxIntegral)). -
Niestabilność z powodu
Kd: WysokieKdmoże powodować nadmierną reakcję na szumy w danych wejściowych. W praktyce stosuje się filtry lub ograniczenie pochodnej. -
Brak synchronizacji: W systemach wielowątkowych,
PIDControllermoże być niebezpieczny bez synchronizacji. W C# można użyćlocklubInterlockeddo zapewnienia bezpieczeństwa.
// Błędna implementacja – brak ograniczenia całki
integral += error * dt;
output = Kp * error + Ki * integral + Kd * derivative;
// Poprawna implementacja – ograniczenie całki
integral += error * dt;
integral = Clamp(integral, -maxIntegral, maxIntegral);
output = Kp * error + Ki * integral + Kd * derivative;- Zmniejszenie obciążenia procesora: W systemach czasu rzeczywistego, obliczenia PID mogą być wykonywane w tle lub w wydzielonym wątku.
-
Czas
dt: Wartośćdtpowinna być stała lub interpolowana, aby zapewnić stabilność obliczeń. W systemach nieliniowych można stosowaćdt = Time.Now - LastTime. - Zarządzanie pamięcią: W C# nie ma potrzeby ręcznego zarządzania pamięcią, ale w C++ trzeba uważać na alokację i dealokację pamięci w przypadku dynamicznego tworzenia obiektów.
Klasa PIDController to kluczowy element w systemach sterowania, zapewniający stabilne i precyzyjne dopasowanie do wartości zadanej. Zastosowanie wzorców, optymalizacji obliczeniowych i odpowiednie zarządzanie stanem pozwala na jej zastosowanie w złożonych systemach czasu rzeczywistego. Warto zwrócić uwagę na potencjalne problemy takie jak przepełnienie całki, szumy i niestabilność, które mogą być eliminowane poprzez odpowiednie filtrowanie i ograniczenia.