LinuxCNC - sterowanie wrzecionem w zamkniętej pętli sprzężenia zwrotnego
: 01 lis 2023, 20:03
Poniższa instrukcja ma charakter poradnika, jak skonfigurować regulator obrotów wrzeciona w LinuxCNC poprzez sterowanie PWM. Jeśli komuś się nie przyda, to pewnie przyda się mi za jakiś czas, bo pewnie zapomnę jak się to robiło, a pamięć mam krótką.
Dokumentacja LinuxCNC jest obszerna i wiele wyjaśnia, jednak raczej nikt, kto buduje maszynę CNC, nie poświęci wielu godzin na jej przestudiowanie. A nawet gdyby, to pewne zagadnienia nie są łatwe do „ogarnięcia” ot tak po przeczytaniu. Czasami to nawet nie wiadomo czego szukać i pod jakim hasłem.
Lista osób, które można zaliczyć do grona tych, którzy „znają się” na LinuxCNC jest zapewne bardzo krótka i nawet nie można oczekiwać, że każdy kto buduje maszynę, musi się na LinuxCNC „znać” bardziej, niż to niezbędne. Ja dopiero raczkuję, więc pewne kwestie w niniejszym poradniku mogą być nieprecyzyjne, jeśli ktoś coś takiego zauważy, warto od razu to zgłosić.
Potrzeba regulowania prędkością wrzeciona nie jest oczywista w każdej maszynie. Jeśli wrzeciono ma się po prostu kręcić z określoną prędkością i nie ma znaczenia, czy nieco przysiądzie oraz czy rzeczywista prędkości różni się od zadanej , regulator taki nie ma sensu. Ale np. w tokarce CNC uważam, że jest niezbędny, szczególnie, jeśli pracuje się z szerokim zakresem obrotów i potrzeba zachować stałą prędkość nawet przy bardzo niskich obrotach.
Zacząłem szukać jak to skonfigurować, ale tak naprawdę, albo jest mało informacji na ten temat, albo źle szukałem. Szukając pod hasłem „Closed loop spindle control”, w zasadzie jedyny użyteczny materiał jaki znalazłem, to ten:
http://wiki.linuxcnc.org/cgi-bin/wiki.p ... ed_Control
Ale to nie jest tak prosto, że przekopiujesz fragmenty konfiguracji hal i już zadziała w każdej innej.
Dlatego korzystając z tego przykładu zrobiłem to nieco po swojemu.
Ja tworząc konfigurację, przez stepconf wizard, podłączyłem już enkoder do pomiaru prędkości i ustawiłem wyjście LPT do sterowania PWM. Niestety proces konfiguracji u każdego przebiega nieco inaczej i ciężko podać tutaj uniwersalną instrukcję.
Na temat sterowania wrzecionem i podłączenia enkodera można znaleźć wiele informacj.
https://linuxcnc.org/docs/html/examples/spindle.html
dlatego przyjmuję, że enkoder i wyjście pwm jest już skonfigurowane i są odpowiednie zapisy w pliku .hal
Noto zaczynamy.
Do sterowania prędkością wrzeciona potrzebny będzie regulator.
HAL udostępnia różnego rodzaju komponenty, między innymi regulator PID.
Aby użyć regulator, trzeba dodać i skonfigurować komponent PID, w tym celu należy dodać kod do pliku .hal
Kod ten ładuje jeden kanał regulatora, uruchamia go w procesie servo-thread (czyli domyślnie z częstotliwością 1ms chyba, że zostało to zmienione w pliku .ini)
Pgain, Igain i Dgain to nastawy regulatora. Na początek zerujemy nastawy poza nastawą proporcjonalną.
maxoutput to maksymalna wartość wyjścia regulatora. Ustawiamy ją np. na 100, będzie to odpowiadać 100% wypełnienia PWM.
MaxerrorI to maksymalna wartość nacałkowania błędu – parametr istotny, aby nie powodować długotrwałemu całkowaniu błędu, w przypadku gdy napęd nie może osiągnąć prędkości zadanej.
MaxerrorI powinien być regulowany równocześnie z nastawą Igain i powinien wynosić nie więcej niż maxoutput/ Igain
Następnie trzeba ustawić, aby komponent PID włączał się wraz z łączeniem wrzeciona.
A więc do linii, która załącza pwmgen wraz z uruchomieniem wrzeciona:
dopisałem podłączenie tego sygnału również do sygnału załączającego PID
Następnie trzeba podłączyć do regulatora odpowiednie dane:
-Prędkość zadaną
-prędkość aktualną
-wyjście regulatora
W celu odnalezienia prędkości zadanej, sprawdziłem w pliku i zweryfikowałem w pomiarze HAL który sygnał temu odpowiada – jest to sygnał spindle.0.speed-out
W moim pliku hal, sygnał spindle.0.speed-out jest już połączony ze zmienną spindle-cmd-rpm
a ta z kolei podłączona jest do sygnału pwmgen.0.value
który odpowiada za wartość pwm generowaną na wyjściu.
Pwmgen to komponent służący do generowania sygnałów pwm i jest on już ustawiony w mojej konfiguracji przez stepconf wizard.
Ponieważ chcemy, aby to regulator PID sterował wartością PWM, trzeba odłączyć sygnał spindle.0.speed-out od sygnału pwmgen.0.value w tym celu trzeba usunąć następujące linie (lub zakomentować)
Następnie sygnał spindle.0.speed-out (czyli wartość zadana prędkości) trzeba podłączyć na wejście regulatora PID który został utworzony:
A wyjście regulatora PID podłączyć do sygnału pwmgen.0.value
Trzeba jeszcze sprawdzić konfigurację pwmgen. Ponieważ wartość 100% wypełnienia to wartość 1, dla pwmgen trzeba ustawić odpowiednią skalę. Ponieważ maksymalne wyjście regulatora PID zostało ustawione na 100, teraz należy ustawić skalę pwmgen również na 100, aby w efekcie maksymalne wyjście regulatora odpowiadało 100% wypełnieniu czyli wartości 1 dla pwmgen.
Pwmgen ma kilka ustawień istotnych:
Częstotliwość według uznania, offset na 0.
Pozostało jeszcze podłączyć prędkość aktualną wrzeciona (czyli sprzężenie zwrotne tego regulatora) na wejście feedback regulatora PID.
Należy pamiętać, aby na wejście regulatora podawać rzeczywistą wartość prędkości a nie jakieś uśrednienia.
Ponieważ LinuxCNC steruje wartością prędkości bez znaku (zadajemy wartość prędkości oraz kierunek), pomiar prędkości wrzeciona musi być także bez znaku.
Odszukałem sygnał, który odpowiada aktualnej prędkości wrzeciona
encoder.0.velocity-rpm
jednak jest to sygnał prędkości ze znakiem.
Aby uzyskać wartość bezwzględna prędkości, trzeba użyć moduł abs
W mojej konfiguracji jest już ładowanie jednej „instancji” modułu abs
więc po prostu zmieniłem, aby załadowane były 2 kanały modułu i drugi moduł również uruchomiony z wątkiem servo-thread
Następnie wartość prędkości wrzeciona podłączam na wejście modułu abs
a wyjście modułu ABS podłączam na wejście feedback regulatora PID
Noi teoretycznie to wszystko.
W praktyce, trzeba jeszcze ustawić regulator PID.
Strojenie wymaga wielokrotnych zmian nastaw regulatora, dlatego wpisywanie ich w pliku hal i każdorazowe uruchomienie od nowa linuxcnc zajmuje sporo czasu.
Stworzyłem sobie zatem panel pyvcp, który pozwoli na zmianę „na żywo” nastaw regulatora.
Jak dodać panel, można poczytać:
http://linuxcnc.org/docs/2.4/html/hal_pyvcp.html
Ja panel mam dodany z kreatora (wyświetlanie prędkości wrzeciona), oraz dodatkowy do Linumeric-LPT V3, więc po prostu go edytuję. Do strojenia i tak trzeba dodać sobie odczyt aktualnej prędkości, więc panel odczytu prędkości i tak będzie potrzebny.
https://linuxcnc.org/docs/devel/html/gui/pyvcp.html
Otwieram plik custompanel.xml w edytorze tekstu i dodaję 2 Spinbox-y do wprowadzania nastaw:
oraz w pliku pyvcp_options.hal dodajemy połączenia:
W ten sposób po uruchomieniu LinuxCNC, pojawi się panel w którym można na żywo wprowadzać nastawy regulatora i po ich dobraniu, wprowadzić je na sztywno do pliku hal, a panel usunąć.

Jeśli ktoś ma ambicję, może poustawiać nieco więcej:
http://linuxcnc.org/docs/html/man/man9/pid.9.html
Dokumentacja LinuxCNC jest obszerna i wiele wyjaśnia, jednak raczej nikt, kto buduje maszynę CNC, nie poświęci wielu godzin na jej przestudiowanie. A nawet gdyby, to pewne zagadnienia nie są łatwe do „ogarnięcia” ot tak po przeczytaniu. Czasami to nawet nie wiadomo czego szukać i pod jakim hasłem.
Lista osób, które można zaliczyć do grona tych, którzy „znają się” na LinuxCNC jest zapewne bardzo krótka i nawet nie można oczekiwać, że każdy kto buduje maszynę, musi się na LinuxCNC „znać” bardziej, niż to niezbędne. Ja dopiero raczkuję, więc pewne kwestie w niniejszym poradniku mogą być nieprecyzyjne, jeśli ktoś coś takiego zauważy, warto od razu to zgłosić.
Potrzeba regulowania prędkością wrzeciona nie jest oczywista w każdej maszynie. Jeśli wrzeciono ma się po prostu kręcić z określoną prędkością i nie ma znaczenia, czy nieco przysiądzie oraz czy rzeczywista prędkości różni się od zadanej , regulator taki nie ma sensu. Ale np. w tokarce CNC uważam, że jest niezbędny, szczególnie, jeśli pracuje się z szerokim zakresem obrotów i potrzeba zachować stałą prędkość nawet przy bardzo niskich obrotach.
Zacząłem szukać jak to skonfigurować, ale tak naprawdę, albo jest mało informacji na ten temat, albo źle szukałem. Szukając pod hasłem „Closed loop spindle control”, w zasadzie jedyny użyteczny materiał jaki znalazłem, to ten:
http://wiki.linuxcnc.org/cgi-bin/wiki.p ... ed_Control
Ale to nie jest tak prosto, że przekopiujesz fragmenty konfiguracji hal i już zadziała w każdej innej.
Dlatego korzystając z tego przykładu zrobiłem to nieco po swojemu.
Ja tworząc konfigurację, przez stepconf wizard, podłączyłem już enkoder do pomiaru prędkości i ustawiłem wyjście LPT do sterowania PWM. Niestety proces konfiguracji u każdego przebiega nieco inaczej i ciężko podać tutaj uniwersalną instrukcję.
Na temat sterowania wrzecionem i podłączenia enkodera można znaleźć wiele informacj.
https://linuxcnc.org/docs/html/examples/spindle.html
dlatego przyjmuję, że enkoder i wyjście pwm jest już skonfigurowane i są odpowiednie zapisy w pliku .hal
Noto zaczynamy.
Do sterowania prędkością wrzeciona potrzebny będzie regulator.
HAL udostępnia różnego rodzaju komponenty, między innymi regulator PID.
Aby użyć regulator, trzeba dodać i skonfigurować komponent PID, w tym celu należy dodać kod do pliku .hal
Kod: Zaznacz cały
# Initialize the PID
loadrt pid num_chan=1
addf pid.0.do-pid-calcs servo-thread
setp pid.0.Pgain 1
setp pid.0.Igain 0
setp pid.0.Dgain 0
setp pid.0.maxoutput 100
setp pid.0.maxerrorI 0
Pgain, Igain i Dgain to nastawy regulatora. Na początek zerujemy nastawy poza nastawą proporcjonalną.
maxoutput to maksymalna wartość wyjścia regulatora. Ustawiamy ją np. na 100, będzie to odpowiadać 100% wypełnienia PWM.
MaxerrorI to maksymalna wartość nacałkowania błędu – parametr istotny, aby nie powodować długotrwałemu całkowaniu błędu, w przypadku gdy napęd nie może osiągnąć prędkości zadanej.
MaxerrorI powinien być regulowany równocześnie z nastawą Igain i powinien wynosić nie więcej niż maxoutput/ Igain
Następnie trzeba ustawić, aby komponent PID włączał się wraz z łączeniem wrzeciona.
A więc do linii, która załącza pwmgen wraz z uruchomieniem wrzeciona:
Kod: Zaznacz cały
#net spindle-on <= spindle.0.on => pwmgen.0.enable
Kod: Zaznacz cały
net spindle-on <= spindle.0.on => pwmgen.0.enable => pid.0.enable
-Prędkość zadaną
-prędkość aktualną
-wyjście regulatora
W celu odnalezienia prędkości zadanej, sprawdziłem w pliku i zweryfikowałem w pomiarze HAL który sygnał temu odpowiada – jest to sygnał spindle.0.speed-out

W moim pliku hal, sygnał spindle.0.speed-out jest już połączony ze zmienną spindle-cmd-rpm
Kod: Zaznacz cały
net spindle-cmd-rpm <= spindle.0.speed-out
Kod: Zaznacz cały
net spindle-cmd-rpm => pwmgen.0.value
Pwmgen to komponent służący do generowania sygnałów pwm i jest on już ustawiony w mojej konfiguracji przez stepconf wizard.
Ponieważ chcemy, aby to regulator PID sterował wartością PWM, trzeba odłączyć sygnał spindle.0.speed-out od sygnału pwmgen.0.value w tym celu trzeba usunąć następujące linie (lub zakomentować)
Kod: Zaznacz cały
net spindle-cmd-rpm <= spindle.0.speed-out
net spindle-cmd-rpm => pwmgen.0.value
Kod: Zaznacz cały
net spindle-cmd-rpm <= spindle.0.speed-out => pid.0.command
Kod: Zaznacz cały
net pwmgen_value pwmgen.0.value <= pid.0.output
Pwmgen ma kilka ustawień istotnych:
Kod: Zaznacz cały
setp pwmgen.0.pwm-freq 100.0
setp pwmgen.0.scale 100.0
setp pwmgen.0.offset 0.0
Pozostało jeszcze podłączyć prędkość aktualną wrzeciona (czyli sprzężenie zwrotne tego regulatora) na wejście feedback regulatora PID.
Należy pamiętać, aby na wejście regulatora podawać rzeczywistą wartość prędkości a nie jakieś uśrednienia.
Ponieważ LinuxCNC steruje wartością prędkości bez znaku (zadajemy wartość prędkości oraz kierunek), pomiar prędkości wrzeciona musi być także bez znaku.
Odszukałem sygnał, który odpowiada aktualnej prędkości wrzeciona
encoder.0.velocity-rpm
jednak jest to sygnał prędkości ze znakiem.
Aby uzyskać wartość bezwzględna prędkości, trzeba użyć moduł abs
W mojej konfiguracji jest już ładowanie jednej „instancji” modułu abs
Kod: Zaznacz cały
loadrt abs count=1
Kod: Zaznacz cały
loadrt abs count=2
addf abs.1 servo-thread
Kod: Zaznacz cały
net pid_feedback_rpm_ABS encoder.0.velocity-rpm => abs.1.in
Kod: Zaznacz cały
net pid_feedback pid.0.feedback <= abs.1.out
W praktyce, trzeba jeszcze ustawić regulator PID.
Strojenie wymaga wielokrotnych zmian nastaw regulatora, dlatego wpisywanie ich w pliku hal i każdorazowe uruchomienie od nowa linuxcnc zajmuje sporo czasu.
Stworzyłem sobie zatem panel pyvcp, który pozwoli na zmianę „na żywo” nastaw regulatora.
Jak dodać panel, można poczytać:
http://linuxcnc.org/docs/2.4/html/hal_pyvcp.html
Ja panel mam dodany z kreatora (wyświetlanie prędkości wrzeciona), oraz dodatkowy do Linumeric-LPT V3, więc po prostu go edytuję. Do strojenia i tak trzeba dodać sobie odczyt aktualnej prędkości, więc panel odczytu prędkości i tak będzie potrzebny.
https://linuxcnc.org/docs/devel/html/gui/pyvcp.html
Otwieram plik custompanel.xml w edytorze tekstu i dodaję 2 Spinbox-y do wprowadzania nastaw:
Kod: Zaznacz cały
<vbox>
<relief>RIDGE</relief>
<bd>6</bd>
<hbox>
<label>
<text>"Spindle PID:"</text>
<font>("Helvetica",20)</font>
</label>
</hbox>
<hbox>
<label>
<text>"P:"</text>
<font>("Helvetica",16)</font>
</label>
<spinbox>
<halpin>"pid-P"</halpin>
<min_>0</min_>
<max_>100</max_>
<initval>0</initval>
<resolution>0.001</resolution>
<format>"3.3f"</format>
<font>("Arial",18)</font>
</spinbox>
</hbox>
<hbox>
<label>
<text>"I:"</text>
<font>("Helvetica",16)</font>
</label>
<spinbox>
<halpin>"pid-I"</halpin>
<min_>0</min_>
<max_>100</max_>
<initval>0</initval>
<resolution>0.001</resolution>
<format>"3.3f"</format>
<font>("Arial",18)</font>
</spinbox>
</hbox>
<hbox>
<label>
<text>"maxI:"</text>
<font>("Helvetica",16)</font>
</label>
<spinbox>
<halpin>"pid-maxerrorI"</halpin>
<min_>0</min_>
<max_>10000</max_>
<initval>0</initval>
<resolution>0.001</resolution>
<format>"3.3f"</format>
<font>("Arial",18)</font>
</spinbox>
</hbox>
</vbox>
Kod: Zaznacz cały
net pid-0-Pgain => pid.0.Pgain
net pid-0-Igain => pid.0.Igain
net pid-0-maxerrorI => pid.0.maxerrorI
net pid-0-Pgain => pyvcp.pid-P
net pid-0-Igain => pyvcp.pid-I
net pid-0-maxerrorI => pyvcp.pid-maxerrorI

Jeśli ktoś ma ambicję, może poustawiać nieco więcej:
http://linuxcnc.org/docs/html/man/man9/pid.9.html