創想三維K1 SE 列印機(五):安裝Moonraker, nginx和Fluidd

早期的3D列印機採用8位元或32位元的微控板,執行Marlin(「槍魚」的英文)韌體,沒有作業系統,像我在2016年購入,基於Prusa i3系列的開源列印機,即是一例(開發板是8位元的Arduino Mega 2560相容板)。

Marlin韌體的主要功能是將切片軟體(如:CuraOrca Slicer)產生的G-Code(控制指令)轉換成具體的硬體動作,例如,移動列印頭座標、控制擠出機、加熱噴頭與熱床等,也是目前最廣泛使用的3D列印機韌體之一。以「槍魚」命名,因為牠是海洋中泳速最快的魚類之一,藉此象徵速度和敏捷,比之前的“Grbl”韌體計算更快速、操控更流暢;Grbl韌體普遍用在Arduino開源CNC加工機,像入門級小型3018 Pro

下圖右代表3D列印機主控板。

Klipper韌體架構示意圖

在中高階、高速列印、DIY和改機用戶群體中,Klipper韌體(或廠商的客製化版本)是普遍的選擇。Klipper也是開源專案,用Python和C語言寫成,而執行Klipper的3D列印機控制板通常有兩個(或更多)處理器,或者一個單板電腦,加上微控制器子板。

Klipper的Python程式在Linux單板電腦執行,負責解析G-Code指令、處理複雜的機械運動模型(如:CoreXY架構),確保馬達運動平滑、減少震動、提升模型細節精度…等。C語言程式則是在微控器執行,負責驅動馬達等週邊,這種分工方式突破了Marlin的算力限制。

在K1 SE列印機安裝Moonraker、nginx和Fluidd

創想三維K1系列3D列印機的控制軟體(Creality OS)是基於Klipper的客製化版本。3D列印機的Linux系統內建HTTP伺服器、網頁介面和API服務(如:透過WebSocket存取列印機的狀態)。上一篇文章提到,用瀏覽器連結3D列印機的IP位址,即可開啟它的網頁介面,讓沒有安裝列印軟體的設備也能遠端操控它。

但是,創想三維並沒有公開API,如果你打算用自製網頁或ESP32開發板操控它,只能自行探索。

另一個辦法是取得K1 SE列印機root權限後,安裝開源Moonraker,替代既有的API服務,並選擇性地安裝與之搭配的Fluidd網頁前端介面。題外話,”Moonraker”和007「太空城」電影同名,但原作者Arksine (Eric) 並未說明兩者命名是否相關。

因為Moonraker有詳盡的文件說明3D列印機的各項控制功能,以及感測器的API名稱和格式,所以本文示範用它取得列印機的狀態。以ssh連線進入K1 SE列印機之後,進入如下的第三方程式安裝畫面(參閱「取得root權限、安裝第三方USB攝影機驅動程式」貼文),選擇1和2(或3),安裝Moonraker, nginx網頁伺服器和Fluidd(或Mainsail)網頁介面。

第三方軟體安裝畫面

Moonraker是用Python語言開發而成的,所以在安裝過程,你會在終端機看到它自動安裝了Python 3.8。安裝完畢後,K1 SE便有兩套網頁操控介面和API服務,但位於底層,實際操控硬體的Klipper仍是原廠的那一個。

Moonraker架構

K1 SE列印機同時執行了兩個網站伺服器和兩個API服務,雖然稱不上從從容容,但可說游刃有餘。若要減輕列印機主控板的負擔,可把Moonraker, nginx和Fluidd安裝在其他設備,例如,Raspberry Pi(樹莓派)、香橙派(Orange Pi)甚至Android手機。

用瀏覽器連結K1 SE列印機IP位址的7125埠,可看到如下的畫面,代表Moonraker已經啟用。Moonraker沒有使用者操控介面,你可以自己編寫網頁或ESP32程式透過它操控3D列印機。

Moonraker網頁

最方便的是用Fluidd網頁介面操作,連結K1 SE列印機IP位址的4408埠,可看到如下的Fluidd畫面,它會在背地裡連到Moonraker,提供比原廠更多設定選項。

fluidd網頁畫面

用Python程式取得3D列印機狀態資訊

上一篇貼文示範使用HTML網頁讀取K1 SE列印機的即時狀態,既然Moonraker是用Python寫成的,那前端我們也就用Python試試吧!

根據Moonraker線上文件的“Get Klippy host information(取得Klipper主機資訊)”單元,以GET方法向3D列印機傳送“/printer/info”請求:

GET /printer/info

或者在WebSocket連線中,傳送底下的訊息給它:

{
    "jsonrpc": "2.0",
    "method": "printer.info",
    "id": 5445
}

即可取得如下的JSON格式回應內容:

{
    "state": "ready",
    "state_message": "Printer is ready",
    "hostname": "pi-debugger",
    "klipper_path": "/home/pi/klipper",
    "python_path": "/home/pi/klipper/venv/bin/python",
    "process_id": 275124,
    "user_id": 1000,
    "group_id": 1000,
    "log_file": "/home/pi/printer_data/logs/klippy.log",
    "config_file": "/home/pi/printer_data/config/printer.cfg",
    "software_version": "v0.12.0-85-gd785b396",
    "cpu_info": "4 core ?"
}fv

實際的JSON回應是不易閱讀的長字串,Python的標準函式庫有個pprint(意指”pretty print”,美化輸出)函式,可以自動格式化輸出訊息,以執行上述GET方法為例,Python程式碼如下:

from pprint import pprint  # 美化輸出的函式
import requests as req     # 「連線請求」物件

PRINTER_IP = "192.168.1.204"  # K1SE的IP位址
# 取得3D列印機的資訊
resp = req.get(f"http://{PRINTER_IP}:7125/printer/info")
info = resp.json()         # 把JSON資料轉成字典(dict)
pprint(info)               # 美化輸出JSON格式字串

實際在電腦上的執行結果:

取得3D列印機的資訊

向列印機發出“/printer/objects/query”請求,並附加指定物件名稱的查詢字串,即可取得該物件的狀態。例如,噴嘴頭的溫度值位於printer物件的extruder(擠出機)裡的“temperature”參數,底下的Python程式:

from pprint import pprint  # 美化輸出的函式
import requests as req     # 「連線請求」物件

PRINTER_IP = "192.168.1.204"  # K1SE的IP位址
# 請求「擠出機」物件資訊
resp = req.get(f"http://{PRINTER_IP}:7125/printer/objects/query?extruder")
temp = resp.json()
pprint(temp)    # 美化輸出JSON格式字串

傳回的” temperature”參數顯示噴嘴頭的溫度是23.36°C。

取得列印機的參數

僅取出“'temperature'”欄位資料的敘述:

temp = resp.json()['result']['status']['extruder']['temperature']
print(f"噴嘴溫度:{temp}°C")

實際執行結果:

取得噴嘴溫度

底下是取得噴嘴溫度、熱床溫度和列印進度資訊的例子:

import requests as req

PRINTER_IP = "192.168.1.204"   # 3d列印機的IP地址
# 請求不同的物件資料,用&符號連接。
req_data = "extruder&heater_bed&print_stats&virtual_sdcard"

def get_printer_data():
    try:
        # 向Moonraker API發送請求
        url = f"http://{PRINTER_IP}:7125/printer/objects/query?{req_data}"
        resp = req.get(url, timeout=5)          # 設定5秒超時
        data = resp.json()['result']['status']  # 解析JSON回應
        
        hotend = data['extruder']['temperature']    # 噴嘴溫度
        bed = data['heater_bed']['temperature']     # 熱床溫度
        state = data['print_stats']['state']        # 狀態
        progress = data['virtual_sdcard']['progress'] * 100  # 列印進度百分比
        
        print(f"當前狀態:{state.capitalize()}")
        print(f"噴嘴溫度:{hotend:.1f}°C")
        print(f"熱床溫度:{bed:.1f}°C")
        print(f"列印進度:{progress:.1f}%")
    except Exception as e:
        print(f"連不上Moonraker:{e}")

if __name__ == "__main__":
    get_printer_data()

執行結果:

取得3D列印機的資訊

Posts created 529

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top