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