LinuxCNCでのレーザーラスター加工について、基本的なところは前ページに書きました。今回はインストールです。
ほいほい堂レーザー加工機の構成
インストールに入る前に対象の加工機がどういう構成になっているか、特にレーザー出力のON/OFF制御部分について説明しておきます。 LinuxCNCが稼動するPCとレーザー加工機の間はパラレルポート(プリンターポート)を介して接続しており、回路は下図の通りです。 基板への入力はアンフェノール36pinコネクタで、主に使用している14pinまではPC側のD-Sub25コネクタの1~14pinと1対1で接続されています。
レーザー加工機コントローラー回路図
回路を簡単に説明すると、2pin~7pinはX,Y,Zのモーター制御に割当てています。実際にはZ軸のモーターはありませんが、LinuxCNCの設定上はZ軸がある事にしており、Z-DIR(回転方向信号)をレーザーのON/OFF制御に使います。 10pin~13pinは非常停止信号や各軸のリミットスイッチからの入力です。いづれもGNDとの間をスイッチで繋ぎます。 非常停止スイッチは1個でLinuxCNCとレーザー電源の両方に入力するため、ショットキーダイオードで分離し、更にレーザー電源側にはフォトカプラを介して接続しています(図中P7コネクタ経由)。 14pinはスピンドルON/OFFの出力信号でNCコードのM03/等で制御します。 最終的にレーザー電源に入れるON/OFF信号は、14pinのスピンドル信号と7pinのZ-DIR信号のANDを取った結果をフォトカプラを介して接続しています(図中P1コネクタ経由)。
必要なファイルのダウンロード
Rastering With a Laserの記載に従って必要なファイルをダウンロードするのですが、一部リンクが切れがある様です。最低限必要なのは次のファイルでした。
http://wiki.linuxcnc.org/uploads/graster-example.tgz
https://github.com/jedediah/hacklab-engraver/archive/master.zip
https://github.com/jedediah/graster/archive/master.zip
加工機側の設定
作業を大きく分けるとGrasterのインストールと加工機側の設定に分かれます。 Grasterは画像を加工データに変換するRubyのプログラムです。 ダウンロードしたgraster-example.tgzの中には変換済みの加工データがあるので、まずはこれで動作を試す事として加工機側の設定を先に実施しました。
M101プログラムのインストール
M101プログラムはNCプログラム中のM101コマンドで呼び出される外部プログラムでPythonで書かれています。 このファイルは先にダウンロードしたhacklab-engraver-master内に’M101′(拡張子も何も無いこのままの名前)があります。 外部プログラムファイルはLinuxCNCがNCコードを読みに行く際のデフォルトディレクトリ(特に変更していなければ~linuxcnc/nc_filesになっていると思います)から読み込むのでここにコピーしておきます。 なおこのままでは私の環境(Ubuntu上のLinuxCNC2.5)ではエラーになりました。恐らく古いLinuxCNC用の記載になっていると思われ、下の点を変更しました。 各所にある’emc’はLinuxCNCの古い名称で、これらをすべて’linuxcnc’に変更しています。 また’emc.nmlfile = ini.find(“EMC”,”NML_FILE”)’行は削除しました。ここは今ひとつわからないのですがバージョン2.5では不要になったっぽいです。
diff M101.ORG M101
13c13
< import emc, os, sys, threading, gtk, time, popen2, signal, select
---
> import linuxcnc, os, sys, threading, gtk, time, popen2, signal, select
15,18c15,17
< os.chdir("/home/hacklab/emc2/configs/hacklab-engraver3")
< ini = emc.ini("hacklab-engraver3.ini")
< emc.nmlfile = ini.find("EMC","NML_FILE")
< s = emc.stat()
---
> os.chdir("/home/konchi/linuxcnc/configs/Laser1")
> ini = linuxcnc.ini("Laser1.ini")
> s = linuxcnc.stat()
INIファイルの変更
INIファイルはLinuxCNCの基本的な設定ファイルです。実際のファイルは~linuxcnc/configs/装置名/装置名.iniです。ほいほい堂加工機は装置名をLaser1にしているので~/linuxcnc/configs/Laser1/Laser1.iniとなっています。 このファイルをテキストエディタで開くと[HAL]というセクション行が見つかります。この中に’HALFILE = custom.hal’という行があるのでこの下に’HALFILE = Raster.hal’行を追加します。
[HAL]
HALFILE = Laser1.hal
HALFILE = custom.hal
HALFILE = Raster.hal
HALとは’Hardware Abstraction Layer’の略で、加工機のハードウェア情報が色々と書かれています。ラスターでの動作もここに追記するのですが、基本の’Laser1.hal’ファイルに追記すると読みづらくなるので新たな’Raster.hal’を作成しました。INIファイルに上記行を追加する事で’Raster.hal’が有効になります。 なおダウンロードしたhacklabのhalファイルは基本部分とラスター部分が一つのファイルに書かれています。
xxx.raster.gmaskファイル
話が飛びますが、ここでxxx.raster.gmaskファイルの説明をしておきます。 このファイルは元画像をGrasterプログラムで処理する際、その他のファイルと共に生成されます(xxxの部分は元画像のファイル名です)。 このファイルはNCコードM101実行時にStreamerに読み込まれ、後はNCプログラムと平行して進んでいきます。 StreamerとはLinuxCNCが加工中にリアルタイムで読み出せるメモリーの様な物です。 gmaskファイルの中は下図の様に4つのフィールドがスペースで区切られた形をしています。4つのフィールドは左から、reset,beam,xop,xargで、resetが1だとリセット、beamが1だとレーザーON、xopが1だとX軸は増加方向,0だと減少方向、xargはX軸がこの値に達すると次の行のデータに進むポイントを示します。 下の例では1行目でリセットし、2行目の時にはNCプログラムがX軸を増加方向に移動させていて、X軸が53.365のポイントに達したらgmaskは次の行に進みます。3行目もxargが53.365ですが、この時はX軸が減少方向に進んでいます。ここまでは全てレーザーはOFFです。3行目でXが減少しながら53.365に達したとき、Streamerは4行目の値に進みます。ここではbeamが1なのでレーザーがONとなります。その後X軸は減少方向に進み続け、53.315のポイントに達すると5行目に進み、ここではbeamが0なのでレーザー出力はOFFとなります。これにより53.365から53.315の間レーザーがONで描画した事になります。 この例ではX軸が減少方向に移動する時にのみレーザーを出力する記述になっています。 次項で説明するHALファイルには、Streamerから取り出した内容を元にレーザーのON/OFFをどの様に制御するか、またStreamerに対して次のステップに進める信号をどの様に生成するかを記述しています。
1 0 0 0
0 0 1 53.365
0 0 0 53.365
0 1 0 53.315
0 0 0 52.248
0 1 0 52.146
0 0 1 53.772
0 0 0 53.772
:
Raster.halの作成
ここが一番面倒な部分です。まずHALに書かれる内容の内、ラスター動作に関係しそうな部分を列記します。
- HALには加工機のハード的な動作を記載します。ステッピングモーターに送るパルス関連もここに記載してあります。
- LinuxCNCの中ではリアルタイムの動作が必要な部分があります。本当のハードウェアならANDやORの回路を使うところをHAL内に記載しておくと加工機動作時にリアルタイムに(実際には周期的に)実行します。 これは回路CADで使うネットリストをイメージすると判り易いのかもしれません。
- hacklab-engraver3.halの記載からレーザー出力制御にかかわる部分を抜き出し、下の回路図に直してみました。
- この中で、「axis.0.joint-pos-fb」は現在レーザーヘッドがあるX座標を示します。
- Streamer.0.pin.0~3はStreamerから読み出した値で、0:reset、1:beam、2:xop、3:xargの順に入ります。データ型は0,1,2がbit、3がfloatです。
- Streamer.0.pin.empty:型はbit。これはStreamerの内容が空になると1になります。
- Streamer.0.pin.enable:型はbit。これはStreamerに入力する信号で、次のデータに進めという意味です。
- gmaskファイルのところで説明した様に、レーザーヘッドのX座標が指定したポイントに達する度にStreamerから次のデータを取り出しながらレーザー出力のON/OFFを制御していきます。
- motion.spindle-on:スピンドルON信号で、NCコードのM3,M4,M5等で制御されます。
- motion.digital-out-00:デジタルアウト0信号で、M62,M63で制御します。hacklabの加工機はベクター加工時にはこの信号でレーザーON/OFFを制御する様です。
- axis.2.joint-pos-fb:これはZ軸の位置情報です。hacklabの加工機はZ軸がマイナスの場合にレーザーがONになる動作もできる様です。
- parport.0.pin-01-out:最終的にレーザーをON/OFFする信号です。 この信号がONになる条件は、まずスピンドルONは絶対条件で、ベクター加工用にデジタルアウトが1またはZ軸がマイナスだとON、ラスター加工用にはStreamerが空でなくてStreamer.0.pin.1が1の時にONとなります。
spindle AND digitar0 OR Z<0 OR ( /empty AND beam)
- これらはHALの記述によりソフト的に処理しています。
- ほいほい堂加工機ではスピンドルとZ-DIR(X軸の方向)をハードウェア的にANDしているのでこの部分は何らかの変更が必要となります。
hacklab-engraver3.halのレーザー出力制御部分を回路図に直してみた。
以上の通りほいほい堂の加工機はハード的にスピンドルとZ-DIRのANDでレーザーをONにしているのでHALファイルの変更が必要です。変更後のHALも回路図にしてみました。 変更点は・・・
- 最終的なレーザーON/OFF信号はparport.0.pin-07-outに変更した(パラレルポート7pinはZ-DIRに割当てています)。
- motion.digital-out-00(デジタル0信号)は使用しない。
- axis.2.joint-pos-fb(Z軸位置)の代りにLaser1.hal内の信号’zdir’を用いた。
- スピンドルONとのANDはハード上で実施しているが、HAL内にも残した。
- 以上の設定によりレーザーONの条件は、まずスピンドルONが絶対条件で、ベクター加工の為にZdirが1だと出力ON,ラスター加工の為にStreamerが空ではなくStreamer.0.pin.1が1ならば出力ONとなる。
spindle AND Z-DIR OR ( /empty AND beam)
Raster.hal追加に伴いLaser1.halにも下記の変更を加えています。ベクター加工のみの場合、zdir信号をパラレルポート7pinに出力していましたが、ラスター加工の為にzdirとパラレル7pinの間にRaster.halで記述する回路を挿入する為、この行をコメントアウトしています。 ~Laser1.hal~
diff Laser1.hal.ORG Laser1.hal
26c26
< net zdir => parport.0.pin-07-out
---
> #net zdir => parport.0.pin-07-out # set by Raster.hal
最後にRaster.halを掲載します。 画像を加工機に送るデータに変換するGrasterについては次回の投稿に記載します。 ~Raster.hal~
# Generated by stepconf at Sun Mar 8 21:32:59 2009
# If you make changes to this file, they will be
# overwritten when you run stepconf again
loadrt threads name1=mask-thread period1=1000000
# Boring components that emc makes me load explicitly because it is a cunt
loadrt comp names=comp-mask-lte,comp-discrete-z
loadrt not names=not-mask-ffw,not-mask-not-empty
loadrt xor2 names=xor2-mask-test
loadrt and2 names=and2-mask-forward,and2-laser-mask,and2-laser-final
loadrt or2 names=or2-mask-command-done,or2-mask-not-ffw,or2-mask-read,or2-laser-gcode,or2-laser-fine
###################################################################################
# Raster Mask - stream in laser on/off commands behind AXIS's back
# Input stream format: reset beam xop xarg
# reset: 0=mask command 1=reset (begin mask sequence with "1 0 0 0", every other command starts with 0)
# beam: 0=off 1=on
# xop: X axis comparison operation 0=less-or-equal 1=greater
# xarg: X axis comparison operand
loadrt streamer depth=256 cfg="bbbf"
net mask-reset <= streamer.0.pin.0
net mask-beam <= streamer.0.pin.1
net mask-xop <= streamer.0.pin.2
net mask-xarg <= streamer.0.pin.3
net mask-empty <= streamer.0.empty
net mask-read => streamer.0.enable
# hardware reported X axis position
net motion-xpos-fb <= axis.0.joint-pos-fb
# mask-lte <= motion-xpos-fb < mask-xarg
addf comp-mask-lte mask-thread
net motion-xpos-fb => comp-mask-lte.in0
net mask-xarg => comp-mask-lte.in1
net mask-lte <= comp-mask-lte.out
# mask-test <= mask-xop ^ mask-lte
addf xor2-mask-test mask-thread
net mask-xop => xor2-mask-test.in0
net mask-lte => xor2-mask-test.in1
net mask-test <= xor2-mask-test.out
# if job is running, read only if test is true or reset
# if job is not running, read until reset
# mask-read <= (laser-coarse && (mask-test || mask-reset)) || !(laser-coarse || mask-reset)
addf or2-mask-command-done mask-thread
net mask-test => or2-mask-command-done.in0
net mask-reset => or2-mask-command-done.in1
net mask-command-done <= or2-mask-command-done.out
addf and2-mask-forward mask-thread
#net laser-coarse => and2-mask-forward.in0
net spindle-on => and2-mask-forward.in0
net mask-command-done => and2-mask-forward.in1
net mask-forward <= and2-mask-forward.out
addf or2-mask-not-ffw mask-thread
#net laser-coarse => or2-mask-not-ffw.in0
net spindle-on => or2-mask-not-ffw.in0
net mask-reset => or2-mask-not-ffw.in1
net mask-not-ffw <= or2-mask-not-ffw.out
addf not-mask-ffw mask-thread
net mask-not-ffw => not-mask-ffw.in
net mask-ffw <= not-mask-ffw.out
addf or2-mask-read mask-thread
net mask-forward => or2-mask-read.in0
net mask-ffw => or2-mask-read.in1
net mask-read <= or2-mask-read.out
# laser-mask <= mask-not-empty && mask-beam
addf not-mask-not-empty mask-thread
net mask-empty => not-mask-not-empty.in
net mask-not-empty <= not-mask-not-empty.out
addf and2-laser-mask mask-thread
net mask-beam => and2-laser-mask.in0
net mask-not-empty => and2-laser-mask.in1
net laser-mask <= and2-laser-mask.out
addf streamer.0 mask-thread
# Raster Mask - end
#######################################################################
# coarse laser control, wired to spindle on/off (M3/M5), not realtime
#net laser-coarse <= motion.spindle-on
# fine laser control, wired to digital output 0 (M62 P0/M63 P0), realtime
net laser-gate <= motion.digital-out-00
# legacy laser control, wired to Z < 0, can be used instead of M62/M63
#addf comp-discrete-z servo-thread
#net motion-zpos-fb <= axis.2.joint-pos-fb
#net motion-zpos-fb => comp-discrete-z.in0
#setp comp-discrete-z.in1 0
#net discrete-z <= comp-discrete-z.out
# laser-final <= laser-coarse & (laser-gate | discrete-z | laser-mask)
#addf or2-laser-gcode mask-thread
#net laser-gate => or2-laser-gcode.in0
#net discrete-z => or2-laser-gcode.in1
#net laser-gcode <= or2-laser-gcode.out
addf or2-laser-fine mask-thread
#net laser-gcode => or2-laser-fine.in0
net zdir => or2-laser-fine.in0
net laser-mask => or2-laser-fine.in1
net laser-fine <= or2-laser-fine.out
addf and2-laser-final mask-thread
net laser-fine => and2-laser-final.in0
#net laser-coarse => and2-laser-final.in1
net spindle-on => and2-laser-final.in1
net laser-final <= and2-laser-final.out
# laser-final => hardware
# net laser-final => parport.0.pin-01-out
net laser-final => parport.0.pin-07-out
※「必要なファイルのダウンロード」のところでgrasterのファイルがリンク切れのアドレスとなっていたので修正しました。 2016-02-27