SHOT-602をPythonで制御 の変更点


#author("2024-06-24T13:26:50+09:00;2024-03-08T10:18:48+09:00","default:masami","masami")
#author("2024-06-24T13:29:49+09:00;2024-03-08T10:18:48+09:00","default:masami","masami")
*シグマ光機のSHOT-602をPythonから制御する(2023/07/07)
#image(https://mkanzaki.sakura.ne.jp/images/SGSP-13ACTx2.png,center,33%)
#contents
**経緯
 シグマ光機の「SHOT-602」はステッピングモータ対応の2軸のステージコントローラです。これはもう製造してないと思います。うちではこれにマイクロメーターにステッピングモーターが付いた形状の「SGSP-13ACT」を接続して使っています。SGSP-13ACTの利点は普通のXYステージで手動マイクロメーターが付いているものを置き換えることができて、手軽に自動制御できるようになります。ただ、マイクロメーターの取り付け位置によってはXYステージの移動する部分とステッピングモーターが干渉するために、移動できる範囲が狭くなることがあります。今使っているタイプのXYステージ(中央精機の中古)では干渉しません(しかし面積をとりますが)。
 以前これらを顕微ラマンの測定システム(WinSpec/32)でマッピングのために使ってました。Visual Studioでプログラムを作成して、SHOT-602の制御とWinSpecの制御をしてました。しかしWinSpecはWindows8以降では使えず、そのため後継ソフトのLightFieldに更新したのですが、前に作ったXYステージ制御用プログラムが使用できません。正確にはXYステージ制御としてはまだ使えるはずですが、ラマン装置との連携部分が使えません。
 LightField自体の使い方にやっと慣れたので、LightFieldを外部から操作してマッピング等を含めたAutomationができるようにしているところです。LightFieldはAutomationのためにPythonで外部から制御できるようになっているので、ステージコントローラもPythonで制御することにしました。これがSHOT-602をPythonで制御することに至った経緯です。
 **インストール
 Windows10 Proの英語版を顕微ラマン装置の制御に使っているので、まずこれにPythonをインストールしました。LightFieldもPythonから制御する必要があるので、LightFieldのPython Automationのマニュアルに沿って、Pythonをインストールしました。1つ注意はPythonが使えるようにするにはLightFieldをインストールする際にAdd-InsとAutomation SDKもインストールする必要がありますが、私はここで躓きました。Add-Ins等をインストールしたつもりでしたが、Pythonのサンプルコードなどがありません。色々とインストール時のオプションを試して、何とかAdd-InsとSDKが正しくインストールされました。SDKが正しくインストールされるとデスクトップにAdd-inへのショートカットができているはずです。出来てない時は何か問題があるようです。また、Pythonの.NETのパッケージもインストールする必要があります(これもマニュアルに説明があります)。
 この時点ではどうも環境変数でPythonやpipの場所が設定されてないようでした。Windowsのターミナルからpipが認識されません。使えるようにするためには環境変数を設定する必要がありました。それでpipが使えるようになったので、PySerialを> pip install pyserialでインストールしました。Macで普段Pythonを使っているので、
Windowsではちょっと勝手が違って戸惑います。
**SHOT-602との通信テスト
 SHOT-602はシリアル通信(RS-232C)を使っていますが、現在のPCだとRS-232C端子はもうありませんが、シリアルーUSB変換ケーブルを使うことでUSB端子で使えるようになります。使えるようにするにはこの変換器で使っているICのドライバーをインストールする必要があります(Windowsが自動でインストールしてくれる場合もあります)。また、コントロールパネルのデバイスをチェックして、このシリアルーUSBケーブルを抜き差しすることで、コントロールパネルのデバイスのどれが対応しているか分かるはずです。そのデバイスの詳細を見るとCOM*に対応しているか分かります。この*の番号部分をメモしておきます。うちの場合COM3でした。
 Macの場合はSerial-USB変換器をMacに繋いでおいて、terminalで
 ls /dev/cu.usbserial-*
を実行すると、cu.usbserial-*というのが出てくるので、usbserial-*の部分をコピーしておいて、後で出てくるコードのserial.Serialのところペーストします。
 ser = serial.Serial("/dev/cu.usbserial-FTF05D9I",19200) # mac
 SHOT-602のマニュアルではハイパーターミナルで通信をテストすることになってますが、それが付属していたのはWindows XPまでで、今のWindows10にはありません。今回はTeraTermを使ってSHOT-602と通信できるかチェックしました。SHOT-602はインターフェース仕様が8 bit, no parity, 1 stop bit, ハード制御なしになります。通信速度はSHOT-602本体にあるDIPスイッチで設定できます。私は以前19200で使っていたので、それを選びました。SHOT-602では19200が最速です。また、命令を送るときにはCR+LFが最後に必要です。TeraTermでそれらを設定するとSHOT-602と通信ができました。
**Pythonで制御
 Pythonでシリアルデバイスを制御する時はライブラリのPySerialが便利です。これはpipでインストールする必要があります。以下はSHOT-602の命令の中のMとGコマンドだけ使った例です。Mコマンドは指定したパルス数だけモータを回す設定を行います。SGSP-13ACTは1パルスで0.5 micron移動します。ステージ1を+方向に2000パルス移動させるには
 M:1+P2000
 G
とします。Mコマンドだけでは実際には移動しないので、次にGコマンドを送ります。Gコマンドは駆動命令で、Gの1文字だけ送るとMコマンドで設定した移動が始まります。
 なお、これらのコマンドを送る前にencodeしておく必要があります。MとGコマンド1組送るだけの例を以下に示します。
 最初の行でserialをインポートして、3行目で通信条件を設定しています。COM3の部分は必要に応じて変えてください。これを実行するとステージの片方が1 mm移動しました。他のコマンドにはジョグ、原点復帰、速度設定、停止、モータホールド/フリーなどのコマンドがあります。
 import serial
 crlf = “\r\n”
 ser = serial.Serial(“COM3”,19200)
 txt = “M:1+P2000” + crlf
 go = “G” + crlf
 ser.write(txt.encode('utf-8'))
 ser.write(go.encode('utf-8'))
 ser.close()
 次に矢印キーを使って、XY軸を移動させる簡単なプログラムを作成しました。1回押した時の移動ステップをv,c,m,fキーで変更できるようにしています。qキーを入力すると停止します。キー入力はmsvcrtのgetchを使って検出しています。普通のキーだと数字が1個返ってきます。例えばqキーだと113が返ってきます。矢印キーの場合はまず224が返ってきて、さらにその後にもう1つ数字が返ってきます。なので224が返ってきた場合は、もう一度getchで読み込んで、その数値で矢印の向きを判定しています。これでSHOT-602が自由に制御できるようになりました。パルス数を数えて、現在位置を表示したり色々とできると思います。次はLightFieldをPythonで制御する部分を少し勉強して、両者を合わせる予定です。

 import serial
 from msvcrt import getch
 
 ser = serial.Serial("COM3",19200)
 
 step = 10 # initial step 
 crlf = "\r\n"
 txt1 = "M:2-P"
 txt2 = "M:2+P"
 txt3 = "M:1-P"
 txt4 = "M:1+P"
 go = "G\r\n"
 print("XY stage driver")
 print("q for quit")
 print("v for very corse: 500 micron")
 print("c for corse: 50 micron")
 print("m for middle: 5 micron")
 print("f for fine: 0.5 micron")
 
 while True:
     key = ord(getch())
     #print(key)
     if key == 113: # q for quit
         break;
     if key == 118: # v for very corse
         step = 1000
     if key == 99: # c for corse
         step = 100
     if key == 102: # f for fine
         step = 1
     if key == 109: # m for middle
         step = 10
     #print(key)
     if key == 224:
         key = ord(getch())
         if key == 72: # Up arrow
             txt = txt1 + str(step) + crlf
             ser.write(txt.encode("utf-8"))
             ser.write(go.encode("utf-8"))
         elif key == 75: # Left arrow
             txt = txt3 + str(step) + crlf
             ser.write(txt.encode("utf-8"))
             ser.write(go.encode("utf-8"))
         elif key == 77: # Right arrow
             txt = txt4 + str(step) + crlf
             ser.write(txt.encode("utf-8"))
             ser.write(go.encode("utf-8"))
         elif key == 80: # Down arrow
             txt = txt2 + str(step) + crlf
             ser.write(txt.encode("utf-8"))
             ser.write(go.encode("utf-8"))
 ser.close()

 その後、TKinterというライブラリーで制御をGUI化しています。これはMac上での例。ボタンをクリックすると設定した移動ステップだけ移動します。移動ステップはコンボボックスから変更できます。さらに、Windows PCにコピーして、同様に動作することを確認しました。
#image(https://mkanzaki.sakura.ne.jp/images/XYstage_tkinter.png,center,33%)
**PAT-001の制御
 SHOT-602の兄弟分?で1軸ステージコントローラのPAT-001というのもあり、これは2台持ってます。そちらもSHOT-602とほぼ同じで動きます。コマンドも基本同じなのですが、もちろん1軸しかないので、M:1+Pは動作しますが、M:2+Pはダメです。
 SHOT-602の兄弟分?で1軸ステージコントローラのPAT-001というのもあり、これは2台持ってます。同様にSGSP-13ACTを接続して使っています。これもSHOT-602とほぼ同じ要領で動きます。コマンドも基本同じなのですが、もちろん1軸しかないので、M:1+Pは動作しますが、M:2+Pはダメです。