-
Notifications
You must be signed in to change notification settings - Fork 0
CommunicationESPNowModule
Ten plik definiuje klasę PIDController, która implementuje algorytm sterowania typu PID (Proporcjonalno-Integralno-Różniczkowy), znany z szerokiego zastosowania w systemach automatyki i sterowaniach procesów. Klasa ta pełni rolę centralnego elementu sterującego w systemach, gdzie należy osiągnąć dokładne dopasowanie wartości wyjściowej do wartości docelowej (setpointu) przy minimalnym przebiciu i możliwie szybkim osiągnięciu ustalonego stanu ustalonego.
W kontekście architektury systemu, PIDController może być używany jako komponent w większym systemie sterowania, np. w sterownikach mikrokontrolerów, systemach automatyki przemysłowej, robotyce, lub systemach sterowania ruchem w samochodach (np. w systemach ESP, ABS). Może być również używany w systemach symulacyjnych lub testowych, gdzie symulowane są fizyczne procesy (np. temperatura, położenie, prędkość) i należy je stabilizować.
Klasa PIDController implementuje cykl życia typowy dla komponentów sterujących:
- Inicjalizacja z parametrami PID (
Kp,Ki,Kd) oraz granicami wyjścia (outputMin,outputMax). - Odbiór wartości aktualnej (
input) oraz wartości docelowej (setpoint). - Obliczenie sterowania
outputna podstawie błędu i historii błędu. - Resetowanie historii błędu w przypadku konieczności (np. po przeprowadzeniu zmiany ustawień).
- Współpraca z innymi komponentami poprzez metody
Update()iReset().
Metoda Update() jest centralnym punktem działania kontrolera PID. Przebieg działania jest następujący:
-
Obliczenie błędu:
double error = setpoint - input;
Błąd to różnica między wartością docelową (
setpoint) a aktualną (input). W przypadku, gdyinputprzekraczasetpoint, błąd będzie ujemny. W przeciwnym razie – dodatni. -
Akumulacja błędu (czynnik całkujący):
integral += error * dt;
Wartość
integralreprezentuje sumę błędów z poprzednich kroków.dtto czas od ostatniego wywołaniaUpdate(). W ten sposób czynnikKiwpływa na tendencję do eliminacji błędu statycznego (tzw. błędu ustalonego). -
Obliczenie pochodnej błędu (czynnik różniczkujący):
double derivative = (error - lastError) / dt;
Pochodna błędu reprezentuje szybkość zmiany błędu w czasie. W przypadku szybkiego zmieniającego się błędu, czynnik
Kdzapobiega przebiciom. -
Obliczenie wyjścia PID:
double output = Kp * error + Ki * integral + Kd * derivative;
To podstawowe równanie PID. Zmienia się ono w zależności od wartości
Kp,Ki,Kd, które są parametrami dostrajania systemu. -
Ograniczenie wyjścia:
output = Math.Max(outputMin, Math.Min(outputMax, output));
Wyjście kontrolera jest ograniczone do zakresu
[outputMin, outputMax], co zapobiega nadmiernemu wzbudzeniu sterownika (np. silnika, zaworu). -
Zapisanie błędu poprzedniego:
lastError = error;
Błąd z poprzedniego kroku jest zapisywany w
lastError, aby móc obliczyć pochodną w kolejnym kroku. -
Zwrócenie wartości sterującej:
return output;
W czasie działania PIDController następuje cykliczne wywoływanie metody Update(). Przykład:
-
Początek działania:
-
input= 100,setpoint= 200 →error= 100 -
integral= 0 (początkowo) -
lastError= 0 (początkowo)
-
-
Po pierwszym kroku:
-
integral= 100 * dt -
derivative= (100 - 0) / dt = 100 / dt -
output= Kp * 100 + Ki * integral + Kd * derivative
-
-
Po kolejnym kroku:
-
error= 150 (np. input wzrósł do 150) -
integral= poprzedni integral + 150 * dt -
derivative= (150 - 100) / dt = 50 / dt
-
- Kp (Proporcjonalny): Im większa wartość, tym szybsze reagowanie na błąd, ale także większe przebicia.
- Ki (Całkujący): Eliminuje błąd ustalony, ale może powodować oscylacje, jeśli jest zbyt duży.
- Kd (Różniczkujący): Zmniejsza przebicia, ale może zwiększyć czas reakcji, jeśli jest zbyt duży.
Klasa PIDController nie dziedziczy z żadnej klasy ani nie implementuje interfejsu. Jest to samodzielna klasa sterująca. W systemie może być używana w kontekście komponentów sterujących, ale nie jest narzucona przez jakikolwiek konkretny interfejs. W przypadku rozszerzania systemu, można rozważyć implementację interfejsu IController, który mógłby wymagać metod Update(), Reset(), SetParameters() itd.
-
input– typdouble, reprezentuje aktualną wartość zmiennej sterowanej (np. temperatura, położenie). Jednostka zależy od kontekstu (np. °C, radiany, mm). -
setpoint– typdouble, reprezentuje wartość docelową. Jednostka identyczna jakinput. -
dt– typdouble, czas od ostatniego wywołaniaUpdate(), w sekundach. Musi być dodatni i niezerowy.
-
output– typdouble, wartość sterująca (np. wyjście PWM, napięcie sterujące, siła działania). Ograniczona do zakresu[outputMin, outputMax].
-
Kp,Ki,Kd– parametry PID. Wartości typudouble, odpowiadające wagi odpowiednich członów sterowania. -
integral– typdouble, akumulowana wartość błędu. Zmienia się w czasie, w zależności oddtierror. -
lastError– typdouble, przechowuje błąd z poprzedniego kroku. Używany do obliczenia pochodnej. -
outputMin,outputMax– typdouble, ograniczenia wyjścia sterującego.
Klasa PIDController nie implementuje żadnego konkretnego wzorca projektowego, ale może być użyta w kontekście wzorca Strategy w przypadku, gdy system ma różne strategie sterowania (np. PID, fuzzy logic, LQR). W takim przypadku PIDController może być jednym z implementacji interfejsu IController.
Wzór Observer może być również używany, jeśli PIDController emituje zdarzenia przy zmianie wyjścia (np. OnOutputChanged), ale nie jest to obecnie zaimplementowane.
-
double– typ zmiennoprzecinkowy o podwójnej precyzji. Wartośćdoublezapewnia dokładność potrzebną w systemach sterowania, gdzie błędy mogą być bardzo małe. -
Math.Max()iMath.Min()– funkcje do ograniczania wartości. W kontekście PID, ograniczenie wyjścia zapobiega sytuacjom, gdzie sterowanie może przekroczyć zakres dostępnych zasobów (np. maksymalne napięcie, maksymalny kąt obrotu). -
virtual– w kontekście C#, metodaUpdate()może być oznaczona jakovirtual, co pozwala na nadpisywanie jej w klasach pochodnych (np. w przypadku PID z ograniczeniami wejściowymi, lub PID z adaptacyjnymi parametrami).
-
Brak walidacji
dt– jeślidtwynosi zero lub jest ujemne, to w obliczeniach pochodnej może wystąpić dzielenie przez zero. W praktyce powinno się sprawdzić, czydt > 0i ewentualnie zwrócić błąd lub wykorzystać wartość domyślną. -
Zmienne
integralilastErrornie są zresetowane w przypadku zmiany ustawień – w systemach dynamicznych może być konieczne resetowanieintegralilastError, jeśli zmienia sięsetpointlubKp,Ki,Kd. -
Brak synchronizacji w środowiskach wielowątkowych – jeśli
PIDControllerjest używany w wielowątkowym środowisku, istnieje ryzyko, żeintegralilastErrorbędą modyfikowane przez różne wątki. W takim przypadku należy użyć mechanizmów synchronizacji (np.lock,Interlocked).
- Warto rozważyć zastosowanie
Span<double>lubMemory<double>w przypadku przetwarzania wielu wartości PID w jednym kroku (np. w systemach z wieloma sterowaniami). - W systemach czasu rzeczywistego warto rozważyć zastosowanie
fixedw C# lubconstw C++ dla parametrów PID, jeśli nie zmieniają się w czasie.
Podsumowanie techniczne:
Klasa PIDController to implementacja klasycznego regulatora PID, który działa w systemach sterowania w czasie ciągłym. Działa poprzez obliczanie proporcjonalnego, całkującego i różniczkującego członu błędu i sumowanie ich z odpowiednimi współczynnikami. Używa typu double do zapewnienia precyzji i ogranicza wyjście do zakresu [outputMin, outputMax]. Może być rozszerzona w przyszłości o dodatkowe funkcje takie jak:
- Resetowanie integralnego członu,
- Adaptacyjne ustawianie parametrów PID,
- Wsparcie dla wielu wejść/wyjść (MIMO),
- Integracja z systemem monitorowania i logowania.
To bardzo ważny element w systemach sterowania, gdzie stabilność i precyzja są kluczowe.