programowanie pętli PID w C

11

Jestem inżynierem elektrykiem, który w pewnym sensie wcisnął się w cyfrowy świat i uczył się w drodze. Programuję procesor TI do wykonania pętli PID (proporcjonalna-całka-pochodna) , co ilustruje ten schemat:

Obraz w pętli PID z Wikipedii

Opiszę to również:

Wzmacniacz operacyjny z ujemnym sprzężeniem zwrotnym, z nieodwróconym uziemionym terminalem. Wejście przez zacisk ujemny. Pętla sprzężenia zwrotnego to obwód serii RE równolegle z rezystorem i wszystko równolegle z nasadką.

Czy ktoś ma pomysł, jak przekonwertować ten obwód do kodu C? Jestem trochę z tego elementu i mogę skorzystać z pomocy.

Inżynier Jedi
źródło
Możesz utworzyć link do zdjęcia, a ktoś z łatwością przekształci ten link w rzeczywiste zdjęcie.
Joachim Sauer
2
Link, który sam opublikowałeś, zapewnia podstawowy pseudokod do poruszania się po nim. Jeśli nie masz nic przeciwko C #, oto przykład pętli pid w C # .
Neil,
1
Neil ma rację. Zaimplementowałem prawie dokładnie tę pętlę w C na TI. Jedna wskazówka: użyj stałej pętli czasowej i uwzględnij stałą dtw stałych, zamiast robić dodatkowe dzielenia i mnożenia w pętli.
AShelly,
1
@ Neil to był link dodany w wersji 2, ponieważ nie wiedziałem, czym jest pętla PID i podejrzewałem, że wielu innych też nie.
@MichaelT, ach moje przeprosiny.
Neil,

Odpowiedzi:

18

Obwód

Ok, właśnie utworzyłem tutaj konto, kiedy zobaczyłem to pytanie. Nie jestem w stanie edytować Twojego pytania, bym mógł poprawić literówkę, którą zrobiłeś. Myślę, że miałeś na myśli obwód serii RC równolegle zamiast RE (jeśli tak, to nie mam pojęcia, co to znaczy)

Wygląda na to, że obwód analogowy, który chcesz symulować za pomocą C, wygląda mniej więcej tak

                         Ci
                  |------| |--------------|
                  |           Rp          |
                  |----/\/\/\/\-----------|
                  |          Rd    Cd     |
           Rf     |----/\/\/\---| |-------|
Vin o----/\/\/\---|                       |
                  |    |\                 |
                  |    | \                |
                  |----|- \               | 
                       |   \              |
                       |    \-------------|---------o  Vout
                       |    /
                       |   /
                       |+ /
                   ----| /
                  |    |/
                  |
                  |
               ___|___ GND
                _____
                 ___
                  _

LEGEND:
  Vin is the input signal.
  Vout is the Output.
  Rp controls the propotional term ( P in PID) 
  Ci controls the Integral term ( I id PID)
  Rd and Cd controls the differential term ( D in PID)
  Rf is the gain control, which is common to all of the above controllers.

(Nie mogłem się oprzeć mojej potrzebie narysowania tego, ponieważ chciałem powiedzieć, jak inżynierowie elektrycy / elektronicy komunikowali się na forach i wiadomościach e-mail bez zdjęć ... i dlaczego po prostu kochamy kuriera, czcionka o stałej szerokości)

Muszę wyznać, że obwód, którego używasz, jest prosty do skonfigurowania, ale jest bardzo złożony matematycznie, jeśli chodzi o dostrojenie stałych propotionalnych, całkowych i pochodnych systemu do pożądanej wartości indywidualnie, nie jest to możliwe.

Zdecydowanie sugeruję użycie obwodu z tego źródła do nauki.

Chociaż konfiguracja jest trochę uciążliwa, matematycznie jest o wiele łatwiej ją analizować, ponieważ można bezpośrednio odnieść ją do standardowej formy matematycznej zamiast idealnej.

Na koniec Vout kontroluje silnik lub cokolwiek, co wymaga kontroli. A Vin jest zmiennym napięciem procesowym.

Przed zmoczeniem stóp w C (morze?)

Zakładam, że odczytujesz sygnały z jakiegoś przetwornika analogowo-cyfrowego. Jeśli nie, musisz zasymulować sygnał jako wejście.

Jeśli korzystamy ze standardowego formularza, mamy,

Zakładając, że czas działania pętli jest wystarczająco mały (wolny proces), możemy użyć następującej funkcji do obliczenia wyniku,

output = Kp * err + (Ki * int * dt) + (Kd * der /dt);

gdzie

Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
int  = int from previous loop + err; ( i.e. integral error )
der  = err - err from previous loop; ( i.e. differential error)
dt = execution time of loop.

gdzie początkowo „der” i „int” wynosi zero. Jeśli użyjesz funkcji opóźnienia w kodzie, aby dostroić częstotliwość pętli do 1 KHz, wtedy dt wyniesie 0,001 sekundy.

Rysowanie w C

Znalazłem ten doskonały kod dla PID w C, chociaż nie obejmuje on wszystkich jego aspektów, mimo to jest dobry.

//get value of setpoint from user
while(1){
  // reset Timer
  // write code to escape loop on receiving a keyboard interrupt.
  // read the value of Vin from ADC ( Analogue to digital converter).
  // Calculate the output using the formula discussed previously.
  // Apply the calculated outpout to DAC ( digital to analogue converter).
  // wait till the Timer reach 'dt' seconds.
}

Jeśli weźmiemy wolny proces, możemy użyć niższej częstotliwości, aby czas wykonania kodu dt >>> dla pojedynczej pętli (znacznie większy niż). W takich przypadkach możemy zrezygnować z timera i zamiast tego użyć funkcji opóźnienia.

D34dman
źródło
6
Diagram Ascii oszalał. +1
l46kok
1
link „to źródło” nie działa
Ccr
Och, przykro mi to słyszeć, zgubił się dobry zasób :(. Cóż, koncepcja została wyjaśniona w przykładowym kodzie pętli while, który udostępniłem. Nie mam doświadczenia w radzeniu sobie z tą sytuacją, być może niektórzy redaktorzy mogą to naprawić za pomocą właściwa wiadomość. (martwy link)
D34dman
2
Brakujące „to źródło” może być dostępne tutaj: educypedia.karadimov.info/library/piddocs.pdf
David Suarez