pythonで3Dプリンター制御してみた


緒言

自宅の3DプリンターはPCレスで動かせるのはいいが、操作がダイヤルを回す+押すで非常にめんどい。

f:id:AKA1022:20200722003302j:plain
操作盤(右下のつまみを回して操作)

どうやらうちの3DプリンターはFT232系の規格でPCとシリアル通信できるっぽい。
キー入力で動かせれば比較的楽に操作できそうなのでやってみた。
f:id:AKA1022:20200722003153j:plain
システム図(操作の作が査になってる...)

(プリンター標準のスライサがCuraでCuraからプリンターを操作する機能があるので、多分多くのプリンターが同じ通信)

環境

プリンター:CR-10
PC:windows10
python3.6.5をAnaconda上で起動

コード

とりあえず、キー入力からエクストルーダの移動ができるようにした。
後、レベリングする時四隅に移動させるのが面倒なので、それ用のコードも書いた。

import serial #serial
import time #wait
from msvcrt import getch #key input
from itertools import cycle 

#gcode
checktemp=b"M105"
autohome=b"G28"
moveX=b"G0 X "
moveY="G0 Y ".encode()
moveZ="G0 Z ".encode()
setAbsolute="G90".encode()
setRelative="G91".encode()

#functions

#gcodeを送り、返信を表示
#okは無視
def sendcommand_waitless(command):
    comport.write(command)#commandを送る。commandはバイナリ文字列
    comport.write(b"\n")
    print("send: "+command.decode())
    time.sleep(0.5)
    print("return: "+comport.readline().decode())#返答表示

#gcodeを送り、返信を表示
#okが帰るまでwait秒待つ。
#wait秒以内に戻らなければ、-1、そうでなければ、0を返す。
def sendcommand_wait(command, wait):
    comport.write(command)
    comport.write(b"\n")
    print("send: "+command.decode())
    echo=0
    count=0
    while not ( (echo == b"ok\n") or (count >wait)):
        echo=comport.read(3)
        print("wait "+command.decode()+" "+str(count)+"/"+str(wait))
        time.sleep(1)
        count=count+1
    else:
        if echo == b"ok\n":
            print("finished")
            return 0
        else:
            print("troubled")
            return -1

#open comport
comport = serial.Serial('COM4', baudrate=115200, parity=serial.PARITY_NONE, timeout=0.1)
#相手の再起動待ち
time.sleep(5)
#念のためバッファクリア
comport.reset_input_buffer()

#温度確認
sendcommand_waitless(checktemp)

#ホームポジションに移動
sendcommand_wait(autohome,10)

#エクストルーダ移動モード

#相対座標モードへ移行
sendcommand_waitless(setRelative)
while True:
    print("move Extruder")
    print("Q:up W:+y E:down")
    print("A:-x S:-y D:+x")
    print("Esc: Escape this mode")
    key = ord(getch())
    print(key)
    if key == 27:
        break
    elif key == 97:#a 
        sendcommand_waitless(moveX+b"-5")
    elif key ==100:#d ->
        sendcommand_waitless(moveX+b"5")
    elif key ==119:#w 
        sendcommand_waitless(moveY+b"5")
    elif key ==115:#s
        sendcommand_waitless(moveY+b"-5")
    elif key ==113:#q 
        sendcommand_waitless(moveZ+b"5")
    elif key ==101:#e
        sendcommand_waitless(moveZ+b"-5")
sendcommand_waitless(setAbsolute)


corner=cycle([
    [10, 10],
    [280, 10],
    [280, 280],
    [10, 280]
])

#leveling mode
#四隅をスペースキーが押されるごとに移動する。
while True:
    print("Leveling Mode")
    print("Space: move next corner")
    print("Esc: Escape this mode")
    key = ord(getch())
    print(key)
    if key == 27:
        break
    elif key == 32:#space
        tmp=next(corner)
        sendcommand_waitless(b"G0 Z5")
        sendcommand_waitless(b"G0 X"+ str(tmp[0]).encode())
        sendcommand_waitless(b"G0 Y"+ str(tmp[1]).encode())
        sendcommand_waitless(b"G0 Z0")

comport.close()

#print(comport.readline())

結果

動いた

展望

使いずらいのでなんかいい感じにまとめたい
タイマーで決まった時間に出力開始させたらいろいろ楽