Próbuję sterować zmotoryzowanym suwakiem (potencjometrem liniowym) za pomocą Arduino.
Kontrola PID daje dobre wyniki „skakania” do określonej pozycji docelowej, ale śledzenie ramp jest problemem, wcale nie jest płynne. Ruch jest bardzo gwałtowny, bez względu na to, czego próbuję.
Oto wykres pozycji odniesienia, zmierzonej pozycji i mocy silnika podczas śledzenia rampy:
A oto wideo z tego samego testu.
W systemach komercyjnych wydaje się to znacznie płynniejsze, zobacz to .
Szczegóły :
Motor fader to Alps RSA0N11M9A0K . Do jego napędzania używam mostka H ST L293D , zasilanego z regulowanego zasilacza 10 V DC ( XL6009 ).
Na Arduino UNO (ATmega328P) używam pinów 9 i 10, o częstotliwości PWM 31,372 kHz, aby uczynić go niesłyszalnym (Timer 1 z preskalatorem 1 TCCR1B = (TCCR1B & 0b11111000) | 0b001
).
Potencjometr jest podłączony między masą a 5 V, a wycieraczka przechodzi do ADC0, jak zwykle.
Kontroler :
Używam prostego regulatora PID z funkcją zapobiegającą zwijaniu, który aktualizuje się z częstotliwością 1 kHz (Ts = 1e-3 s):
float update(int16_t input) {
int16_t error = setpoint - input;
int16_t newIntegral = integral + error;
float output = k_p * error
+ k_i * newIntegral * Ts
+ k_d * (input - previousInput) / Ts;
if (output > maxOutput)
output = maxOutput;
else if (output < -maxOutput)
output = -maxOutput;
else
integral = newIntegral;
previousInput = input;
return output;
}
Wyjście sterownika ma wartość od -127 do 127. Wyjście PWM jest generowane w następujący sposób:
const int8_t knee = 48;
uint8_t activation(int8_t val) {
if (val == 0)
return 0;
else {
return map(val, 0, 127, 2 * knee, 255);
}
}
void writeMotor(int8_t val) {
if (val >= 0) {
analogWrite(forward, activation(val));
digitalWrite(backward, 0);
} else {
analogWrite(backward, activation(-val));
digitalWrite(forward, 0);
}
}
Dodałem 48 do 7-bitowego sygnału PWM, ponieważ w tym miejscu silnik zaczyna się poruszać przy 31 kHz, a następnie skaluję go do liczby 8-bitowej (ponieważ tego analogWrite
oczekuje funkcja):
Co próbowałem :
próbowałem dodać filtr EMA do wejścia, do sygnału sterującego, do pochodnej kontrolera PID, ale bezskutecznie. Próbowałem również obniżyć rozdzielczość wejścia analogowego, używając histerezy, aby powstrzymać ją przed przełączaniem się między dwiema wartościami podczas postoju. Wydaje się, że to nic nie wpływa. Wydłużenie kroku czasowego do 10 ms również nie pomaga.
Próbowałem również przeprowadzić identyfikację systemu w MATLAB i próbowałem dostroić ją w Simulink (po tej serii filmów ). Mam model z dopasowaniem wynoszącym 91%, ale nie wiedziałem, jak poradzić sobie z nieliniowościami wejściowymi i wyjściowymi modelu MATLAB, jak wpływają one na strojenie PID i jak zaimplementować je na Arduino.
Ostatnią rzeczą, której próbowałem, jest wykonanie dwóch różnych kontrolerów: jeden do dużych skoków w pozycji odniesienia i jeden do małych błędów podczas śledzenia rampy. Wydaje się to nieco pomóc, ponieważ wtedy mogę zwiększyć współczynnik całkowania podczas śledzenia, bez zwiększania przekroczenia podczas skoku.
Jednak zwiększając całkę (i proporcjonalność) wzmocnienia, silnik zawsze robi coś, nawet gdy powinien być nieruchomy, a wartość zadana nie zmienia się. (Nie porusza się tak naprawdę, ale można poczuć, że wibruje.)
Nie mam praktycznie żadnego wzmocnienia pochodnej, ponieważ zwiększenie go powyżej 1e-4 wydaje się jeszcze bardziej nieprzyjemne i naprawdę nie zauważam żadnej różnicy między 0 a 1e-4.
Domyślam się, że potrzebuje więcej mocy, aby pokonać tarcie statyczne, a następnie tarcie dynamiczne jest mniejsze, więc przekracza, więc napędza silnik do tyłu, powodując jego zatrzymanie, a następnie musi ponownie pokonać tarcie statyczne, ponownie strzela do przodu itp.
Jak kontrolery komercyjne pokonują ten problem?
Moje doświadczenie :
Jestem na trzecim roku licencjackim z inżynierii elektrycznej, uczestniczyłem w kursach teorii teorii, cyfrowego przetwarzania sygnałów, kontroli LQR itp., Więc mam pewne podstawy teoretyczne, ale mam problem z zastosowaniem wszystkich tych teorii do ten rzeczywisty system.
Edycja :
Przetestowałem pomiary czujnika w otwartej pętli, zgodnie z zaleceniem laptop2d, i jestem dość zaskoczony wynikami: przy wysokich częstotliwościach PWM występują nieprzyjemne piki w odczytach. Przy 490 Hz nie ma żadnych.
I to jest przy stałym cyklu pracy, więc nie wyobrażam sobie, jaki hałas mam, gdy silnik bardzo szybko zmienia kierunek.
Będę musiał znaleźć sposób na odfiltrowanie tego szumu, zanim zacznę ponownie pracować na kontrolerze.
Edycja 2 :
Zastosowanie wykładniczego filtra średniej ruchomej nie było wystarczające do odfiltrowania szumu.
Próbowałem z biegunami w 0,25, 0,50 i 0,75. Małe słupy nie miały większego efektu, a większe bieguny dodawały zbyt wiele opóźnień, więc musiałem obniżyć zyski, aby zachować stabilność, co spowodowało gorszą ogólną wydajność.
Dodałem kondensator 0,1 µF do potencjometru (między wycieraczką a ziemią) i wydaje się, że to oczyszcza.
Na razie działa wystarczająco dobrze. W międzyczasie czytam artykuł napisany przez Tima Wescotta .
Dziękuję wszystkim za pomoc.
This device is suitable for use in switching applications at frequencies up to 5 kHz.
Charakterystyka elektryczna na stronie 3 sugeruje absolutne maksimum 690 kHz, jeśli dodasz wszystkie opóźnienia. (dolne 4 wiersze) Osobiście poszedłbym o wiele wolniej, ale uważam, że 31 kHz powinno być wystarczające ... gdyby nie notatka na stronie 1.