LinuxCNCでジョイスティック代わりにトラックボールを使う

経緯

我が家のNCフライスは,設置場所が想定以上に狭く,Z軸の調整用ハンドルが天井に当たってしまい,場合によっては接触して異音の原因となることがあった.調整用ハンドルを除去すれば問題は解決するが,エンドミルの位置決めなど,目視での軸移動が必要な際に不便であるのは必至であった.
そこで,Z軸調整の代替を目的としたジョイスティックを導入する.調整用ハンドルと同様に360度回転可能で,左右にひねれば上下し,材料にぶつかれば感触がフィードバックする機構があれば良い.しかし,現実的にはぶつかった感触を知るのは難しいので,前者の2つをサポートしてれば良い.
市販されている機器の中では,Kensington社が販売しているトラックボールのスクロールリング機能が,求めている機構と最も近い.幸い,4000円以下の廉価なモデルでもスクロールリングが備わっており,これをジョイスティックとして利用することにした.
XY軸移動用にトラックボールは役に立ちそうだが,一方の軸だけを動かす用途には向いていないだろう.アバウトな位置設定用として上手く利用したい.

f:id:sosoru_m:20170109201945j:plain:w300
▲Z軸当たってる

使用したモデル

Kensington社のOrbitTrackball with Scroll Ring 72337JP
https://d107iaxg6vni3j.cloudfront.net/mbank38730_560_560.jpg
https://www.kensington.com/ja/jp/4493/72337jp/orbit-scroll-ring-trackball
https://www.amazon.co.jp/gp/product/B004QE4JXA/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
購入時は3800円程度.トラックボール・スクロールリングの他,ボタンは2つのみ.
普段使いのマウスとしてはちょっとボタンが少なすぎるかも.LinuxCNCが提供しているDebian環境では特に問題も起きずに認識した.

f:id:sosoru_m:20170113233500p:plain:w300
▲LinuxCNCのShow Hal Configurationで見たトラックボールの状態(loadrt後).トラックボールだと各軸の座標が浮動小数ではない?(参考:Shimalith氏のページでのアナログパッドは浮動小数点を返している)

設定したい機能

トラックボール XY軸移動に対応
スクロールリング Z軸移動に対応
左クリック ジョイスティック有効
右クリック ジョイスティック無効

HAL

LinuxCNCではHALと呼ばれる,ちょっとした設定記述用言語が用意されている.これは,ワイヤードロジックっぽい感じで書かねばならず,C言語というよりかはHDL系の言語に近い.
例えば,クリックでスイッチのON/OFFを切り替える場合,if文で現在と過去のマウスボタンの状態を見てスイッチを変えましょう,というわけにはいかず,まずマウスボタンの現在の状態を2入力and素子で受け取り,その出力をnot素子を通してもう一方のand入力に接続することで過去の状態を取得する.ほとんどデジタル電子回路である.

LinuxCNC側の設定

トラックボールを検出するには,まず

$ less /proc/bus/input/devices

にて,デバイスの名前を確認する.これはhalコードでデバイスを指定するときに必要になる.今回のデバイスは「Eagle」が含まれており,これを利用する.
Xがマウスとして認識した場合には回避する必要があるらしいが,当環境では発生しなかったため,設定は割愛する.(参考:Movement for atomic step(s) by mouse scroll wheel?には書いてある)
次に認識したデバイスを一般ユーザーでも扱えるようにするために,udevの設定を変更する.

$ sudo echo '' >> /etc/udev/rules.d/99-rtai.rules
$ sudo echo 'SUBSYSTEM=="input", MODE="0660", GROUP="plugdev"' >> /etc/udev/rules.d/99-rtai.rules

以上の設定が済めば,halrunコマンドの後に動作を確認する.

$ halrun
halrun : loadusr -W hal_input -KRAL Eagle
halrun :

halrunに何も言われなければOK.
MANを読め,みたいなことを言われたら,上のudevの設定が上手く行っていない可能性あり.その場合,rootで実行すれば成功する.

その他の設定のポイントを以下に示す.

  • 各軸の移動とトラックボール・スクロールリングの移動を対応するには,input.0-rel-?-positionとaxis.?.jog-countsを接続すれば良いが,整数型から浮動小数点型に型変換する必要があるため,conv-floats-32を通して接続する必要がある.
  • ジョイスティックの有効無効を左クリックと右クリックに対応させるにはRS型フリップフロップを用いて対応している.また,jog-enableを切り替えるとトラックボールのボタンが効かなくなる恐れがあるため,jog-scaleを変更し,左クリックが押されるとjogscale=0.1,右クリックが押されるとjogscale=0に設定される.
  • 左クリックはbtn-mouse~を使用する.

halコード

# load remote joystick
loadusr -W hal_input -KRAL Eagle

# define components
loadrt conv_float_s32 count=3
loadrt and2 count=2 
loadrt not count=2
loadrt mux2 count=3

# set clock
addf conv-float-s32.0 servo-thread
addf conv-float-s32.1 servo-thread
addf conv-float-s32.2 servo-thread
addf and2.0 servo-thread
addf and2.1 servo-thread
addf not.0 servo-thread
addf not.1 servo-thread
addf mux2.0 servo-thread
addf mux2.1 servo-thread
addf mux2.2 servo-thread

# setting joystick
setp axis.0.jog-vel-mode 0
setp axis.1.jog-vel-mode 0
setp axis.2.jog-vel-mode 0

setp axis.0.jog-enable 1
setp axis.1.jog-enable 1
setp axis.2.jog-enable 1

# connecting as RS-FF; Q --> muxer.sel
net rsff-sb and2.0.in0 <= input.0.btn-mouse-not
net rsff-rb and2.1.in0 <= input.0.btn-right-not
net rsff-nand-s and2.0.out => not.0.in 
net rsff-nand-r and2.1.out => not.1.in 
net rsff-qb not.1.out => and2.0.in1
net rsff-q not.0.out => and2.1.in1 mux2.0.sel mux2.1.sel mux2.2.sel

# set muxer and connects for changing jog-scale
setp mux2.0.in0 0 
setp mux2.0.in1 0.01 
setp mux2.1.in0 0 
setp mux2.1.in1 0.01 
setp mux2.2.in0 0 
setp mux2.2.in1 0.01 

net x-jog-scale mux2.0.out => axis.0.jog-scale 
net y-jog-scale mux2.1.out => axis.1.jog-scale 
net z-jog-scale mux2.2.out => axis.2.jog-scale 

# connecting moving trackballs with positioning axes, through float casting
net x-float conv-float-s32.0.in <= input.0.rel-y-position
net x-s32 conv-float-s32.0.out => axis.0.jog-counts

net y-float conv-float-s32.1.in <= input.0.rel-x-position
net y-s32 conv-float-s32.1.out => axis.1.jog-counts

net z-float conv-float-s32.2.in <= input.0.rel-wheel-position
net z-s32 conv-float-s32.2.out => axis.2.jog-counts
  • 入力信号をnet文で2回以上使用するとエラーが出る.出力が複数にわたる場合(例えばRS-FFのQ端子)には,スペース区切りで複数指定可能.(参考:Basic HAL)
  • 動作確認後,直感的な動作では無かったため,rel-x-positionとrel-y-positionを入れ替えた.
  • RS-FFのR=S=1は禁止だから,同時に押すとどうなるのか気になるが,ソフトが落ちることは無かった.不定な動作になりそうだが.

動作確認

X軸Y軸の対応が直感的では無かったため修正したが,おおむね期待通り動作した,ジョイスティックだとトップスピードで軸移動するっぽいのが少し不安.
Z軸のスクロールリングは,1周で約80ノッチに相当しており,現在は,0.8mm/周で運用している.感覚的な不具合があれば追記したい.
f:id:sosoru_m:20170113234115p:plain:w300
▲適当に動かせば適当に動いてくれる