HIWIN 與 Python TCP 通訊的簡單範例

目標

實做一個可以使用python控制HIWIN手臂的簡單程式,並探討後續的運用

Python 端建立 TCP server,HIWIN 透過 COPEN 主動連線。雙方以 ASCII 文字傳送命令,數值使用大括號包住。

以下使用 Group 1 控制 Cartesian 相對位移,Group 2 移動到已教導點位。

這套流程一次只處理一筆命令。Python 送出命令後等待回覆;HIWIN 收到三個數值,依照 Group 執行對應動作,再用 CWRITE 傳回結果。收到回覆後,Python 才讓使用者輸入下一筆命令,因此執行順序容易觀察,也適合先理解兩端如何交換資料。

通訊方向

Python TCP server(等待連線)
        ↑
        │ TCP/IP
        │
HIWIN HRB client(COPEN 主動連線)

兩端必須使用同一個 port。下例使用 5000,HIWIN 程式中的 IP 要改成執行 Python 的電腦或 Raspberry Pi 位址。

Python 是 server,只負責開啟通訊埠並等待連線;HIWIN 是 client,執行 COPEN 時主動連到 Python。若兩邊都設成等待連線,或兩邊都試圖連向對方,連線就不會成立。

一次命令會依序經過下列步驟:

  1. Python 以 sendall() 送出 {CMD_GROUP,CMD_AXIS,CMD_AMOUNT}
  2. HRB 的 CREAD 將三個數值放入對應的 REAL 變數。
  3. HRB 根據 CMD_GROUPCMD_AXIS 選擇動作。
  4. 動作指令執行完畢後,HRB 以 CWRITE 傳回 ACK
  5. Python 的 recv() 收到回覆,結束這一輪。

Python TCP server

import socket

HOST = "0.0.0.0"
PORT = 5000


def send_command(client, command):
    client.sendall(command.encode("ascii"))
    reply = client.recv(1024).decode("ascii")
    print("HIWIN reply:", reply)


with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind((HOST, PORT))
    server.listen(1)

    print(f"Waiting on {HOST}:{PORT}")
    client, address = server.accept()

    with client:
        print("HIWIN connected:", address)

        while True:
            command = input("Command, or q to quit: ").strip()

            if command.lower() == "q":
                break

            if not (command.startswith("{") and command.endswith("}")):
                print("Use format: {group,parameter,value}")
                continue

            send_command(client, command)

HOST = "0.0.0.0" 表示 Python 接受本機所有網路介面的連線;HIWIN 的 COPEN 則必須填寫 Python 主機在區域網路中的實際位址,例如 192.168.0.10

bind() 將 socket 綁定到 5000listen(1) 開始等待連線,accept() 則停在原地,直到 HIWIN 成功連入。連線建立後,client 才是實際收送資料的 socket;server 仍是監聽 socket。

send_command() 使用 sendall(),確保 Python 會持續送到這批位元組全部交給作業系統。接著呼叫 recv() 等待 HIWIN 回覆,所以畫面停在這一行不一定是 Python 當機,也可能是手臂仍在移動、HRB 尚未執行到 CWRITE,或控制器已因警報停止程式。

輸入檢查只確認命令前後有大括號,沒有檢查欄位數量及數值範圍。輸入內容仍應符合下方表格,否則 HRB 可能把缺少的欄位讀成 0,或回覆 ACK = -1

執行後,等 HIWIN 連上來,再直接輸入命令:

{1,1,10}  → X +10 mm
{1,2,-5}  → Y -5 mm
{1,3,2}   → Z +2 mm
{2,1,0}   → 移動到 P1
{2,2,0}   → 移動到 P2

第三欄在 Group 2 沒有用途,但仍保留 0,讓封包固定維持三個數值。

正值與負值代表座標增減方向。例如 {1,1,10} 是在目前 X 座標加上 10 mm,不等於畫面上固定向右移動;實際方向仍取決於運動指令使用的 Tool、Base 與手臂姿態。

HIWIN HRB

INT PYTHON
REAL CMD_GROUP, CMD_AXIS, CMD_AMOUNT
REAL ACK
E6POINT TARGET

; Replace this IP with the Python server IP.
PYTHON = COPEN(ETH, 192, 168, 0, 10, 5000)

IF PYTHON > -1 THEN
    LOOP
        CREAD(PYTHON, CMD_GROUP, CMD_AXIS, CMD_AMOUNT)
        ACK = -1

        ; Group 1: relative Cartesian movement.
        IF CMD_GROUP == 1 THEN
            TARGET = GETPOINT

            IF CMD_AXIS == 1 THEN
                TARGET.X = TARGET.X + CMD_AMOUNT
                ACK = 0
            ENDIF

            IF CMD_AXIS == 2 THEN
                TARGET.Y = TARGET.Y + CMD_AMOUNT
                ACK = 0
            ENDIF

            IF CMD_AXIS == 3 THEN
                TARGET.Z = TARGET.Z + CMD_AMOUNT
                ACK = 0
            ENDIF

            IF ACK == 0 THEN
                LIN TARGET FINE=2 Vel=100mm/s Acc=20% TOOL[0] BASE[0]
            ENDIF
        ENDIF

        ; Group 2: move to a taught point.
        IF CMD_GROUP == 2 THEN
            IF CMD_AXIS == 1 THEN
                PTP P1 FINE=2 Vel=10% Acc=20% TOOL[0] BASE[0]
                ACK = 0
            ENDIF

            IF CMD_AXIS == 2 THEN
                PTP P2 FINE=2 Vel=10% Acc=20% TOOL[0] BASE[0]
                ACK = 0
            ENDIF
        ENDIF

        CWRITE(PYTHON, ACK)
    ENDLOOP
ENDIF

PYTHON 儲存 COPEN 傳回的通訊 handle。回傳值大於 -1 才代表通道已開啟,因此所有 CREADCWRITE 與運動流程都放在 IF PYTHON > -1 裡。若連線失敗,這份程式不會進入主迴圈。

CREAD(PYTHON, CMD_GROUP, CMD_AXIS, CMD_AMOUNT) 會等待 Python 傳入資料。三個接收變數使用 REAL,並依封包中的順序取得數值。這也是封包固定保留三欄的原因:欄位意義不會隨 Group 改變,讀程式時比較不容易把資料放錯位置。

每輪開始先把 ACK 設成 -1。只有命令進入範例允許的分支後,程式才將它改成 0。未知 Group 或未知軸號不會沿用上一輪的成功結果。

ACK = 0 表示命令已進入已知分支,而且 HRB 已執行到動作之後的 CWRITEACK = -1 表示 Group 或參數不在範例範圍內。CWRITE 會替數值加上大括號,因此 Python 收到的內容會是 {0...}{-1...},小數位數依控制器通訊格式而定。

ACK 只描述這份 HRB 的程式流程,不能當成控制器狀態碼。它沒有回報目前座標、警報內容、急停狀態,也沒有核對 Python 送出的原始命令。需要可靠的命令同步時,應另外設計命令 ID、逾時及重送規則。

封包欄位

{CMD_GROUP,CMD_AXIS,CMD_AMOUNT}
Group 用途 CMD_AXIS CMD_AMOUNT
1 Cartesian 相對移動 1=X、2=Y、3=Z 位移量,單位 mm
2 移動到教導點 1=P1、2=P2 固定填 0

Group 1 先用 GETPOINT 取得目前位置,只修改 X、Y 或 Z,再用 LIN 前往新位置。Group 2 使用 PTP 前往 P1 或 P2,路徑不保證是直線。

Group 1 為何能形成相對位移

LIN 接收的是絕對目標點,但 TARGET 每次都從當下位置建立。假設目前 X 是 300 mm,收到 {1,1,10} 後,程式會算出 TARGET.X = 300 + 10 = 310 mm,再以 LIN TARGET 移動到 310 mm。目標本身是絕對座標,產生的效果則是從當下位置沿 X 增加 10 mm。

TARGET = GETPOINT 會一併取得 X、Y、Z、A、B、C 與各軸資訊。程式只改其中一個 Cartesian 欄位,其餘姿態資料沿用當下值,可以避免只建立 X、Y、Z 而遺漏末端姿態。這個計算仍以運動時選用的 Tool 與 Base 為前提;現場若不是 TOOL[0] BASE[0],必須同步修改範例設定。

Group 2 與 Group 1 的差別

Group 2 不計算目前位置,而是直接執行 PTP P1PTP P2。P1、P2 是教導器內已儲存的絕對點位。PTP 會讓各關節協調抵達目標,TCP 經過的路徑不保證是直線,因此點位附近即使沒有障礙物,兩點之間的空間仍要確認。

兩種速度單位也不同:範例中的 LIN Vel=100mm/s 是末端直線速度;PTP Vel=10% 是點到點運動的百分比速度。兩者不能直接當成相同數值比較。

建議測試順序

  1. 先確認 Python 主機與 HIWIN 位於可互通的區域網路,IP 與 port 沒有填反。
  2. 先啟動 Python,看到 Waiting on 0.0.0.0:5000 後,再啟動 HRB。
  3. Python 顯示 HIWIN connected 後,先送 {9,0,0}。這筆命令不會進入運動分支,預期收到失敗 ACK,可先確認雙向通訊。
  4. 在 T1、低速及可立即停止的條件下,用 Group 1 測試很小的位移,先確認正負方向。
  5. 確認 P1、P2、Tool、Base 與路徑後,才測試 Group 2。

常見狀況

現象 先檢查的地方
Python 一直停在 accept() HRB 是否已執行 COPEN、IP 與 port 是否一致、防火牆是否允許連入
HRB 停在 CREAD Python 是否已連線並送出含大括號的命令;CREAD 沒有資料時會等待
Python 停在 recv() HRB 是否仍在移動、是否發生警報、程式是否已走到 CWRITE
收到失敗 ACK CMD_GROUPCMD_AXIS 是否落在表格定義的範圍
移動方向與預期不同 Tool、Base、目前姿態,以及正負方向的判讀基準
多次收送後回覆黏在一起 TCP 沒有訊息邊界,正式程式需建立完整的封包緩衝與解析規則

指令版本與來源

指令 用途 手冊位置 文件列出的適用版本
COPEN 開啟 Ethernet TCP/IP 通訊 PDF 186–188/手冊 184–186 HRSS 2.0.1 以上
CREAD 接收外部設備傳入的數值 PDF 190–192/手冊 188–190 HRSS 2.0.1 以上
CWRITE 將數值回傳外部設備 PDF 192–194/手冊 190–192 HRSS 2.0.1 以上
GETPOINT 取得目前 Cartesian 與關節資訊 PDF 162–163/手冊 160–161 HRSS 3.2.1 以上
LIN 沿直線移動到絕對目標點 PDF 71–73/手冊 69–71 HRSS 2.0.1 以上
PTP 以點到點方式移動到目標點 PDF 67–69/手冊 65–67 HRSS 2.0.1 以上

控制器版本若低於表格要求,應先查該版本手冊,不能只靠範例是否成功匯入來判斷支援程度。

使用限制

  • 執行 Group 2 前,P1、P2 必須已完成教導,Tool 與 Base 也要符合點位使用的座標設定。
  • TOOL[0] BASE[0] 應改成設備實際使用的 Tool 與 Base 編號。
  • 第一次運動測試應使用 T1、低速與小位移,確認方向後再逐步增加距離。
  • TCP 是連續位元組串流,單次 recv() 不保證剛好取得一筆完整回覆。長時間執行時需要封包緩衝、逾時及重複命令處理。
  • CREAD 沒有資料時會持續等待。需要停止或重新連線功能時,應另行加入資料查詢、離線處理與 CCLOSE 流程。