在工業自動化與機器人開發中,“如何控制電機” 始終是一個核心話題。傳統的控制方式往往受限于物理接線長度(USB/串口),或者受困于繁瑣的寄存器操作。
今天,我們將展示一套純 Python 解決方案:利用 ZLG 的以太網 CAN 適配器(CANET-2E-U),結合強大的 canopen 開源庫,實現對 PMC006CX 一體化步進驅動器 的遠程、高層級控制。
set_max_speed),極大地降低了開發門檻。Python 的 canopen 庫原生支持 SocketCAN、Kvaser、Vector 等設備,但默認并不支持 ZLG 的 TCP 模式。
為了解決這個問題,我們編寫了 zlgcanadapter.py。這是一個硬件抽象層,它繼承自 can.BusABC。它的作用是欺騙 canopen 庫,讓它以為自己連接的是一個標準的本地 CAN 卡,但實際上所有數據都通過 TCP 網絡流向了 ZLG 適配器
關鍵代碼解析 (zlgcanadapter.py):
# 核心機制:攔截 send 和 recv
class ZLGCanNetBus(can.BusABC):
def __init__(self, ip, port, ...):
# 初始化 ZLG SDK,建立 TCP 連接
self.zcanlib = ZCAN()
self.device_handle = self.zcanlib.OpenDevice(ZCAN_CANETTCP, 0, 0)
# 配置 IP 和 端口...
def send(self, msg, timeout=None):
# 將 python-can 的 Message 對象轉換為 ZLG 的 C 結構體并發送
z_msg = ...
self.zcanlib.Transmit(self.chn_handle, z_msg, 1)
def _recv_internal(self, timeout):
# 從 ZLG SDK 讀取數據,封裝回 python-can 的 Message 對象
rcv_msg = self.zcanlib.Receive(...)
return msg, False
有了這個文件,我們就可以無縫對接 canopen 的高層功能了。
直接操作 SDO(例如 node.sdo[0x6003].raw = 50000)雖然可行,但不夠直觀。我們在 pusican.py 中構建了一個 Canopen_ku 類,將復雜的 CANopen 對象字典地址(Index/SubIndex)映射為人類可讀的函數。
看看封裝前后的對比:
原始方式:
# 想要設置加速度,你需要查閱手冊找到 0x6008
node.sdo[0x6008].raw = 5
封裝后 (pusican.py):
# 直接調用語義化函數
def set_acce_speed(self, node_id, a_speed):
self.node_map[node_id].sdo[0x6008].raw = a_speed
該庫通過檢測 bustype 參數,自動判斷是加載標準的 CAN 接口,還是加載我們自定義的 ZLG 網絡接口:
if self.bustype1 == 'zlgcanet':
# 自動加載我們寫的適配器,解決 connect 報錯問題
zlgcannet_bus = ZLGCanNetBus(ip=ip, port=port)
self.network.bus = zlgcannet_bus
萬事俱備,現在我們來編寫一個主程序 motor_controller.py。假設電機的 Node-ID 為 3,CANET 的 IP 為 192.168.1.200,端口 4001。
我們將演示PP模式(點對點位置控制),讓電機轉動指定的步數。
import time
from pusican import Canopen_ku
def main():
# 1. 連接設備
# 格式:類型, IP:端口, 波特率, [節點ID列表]
print("正在連接 CANET 設備...")
driver = Canopen_ku('zlgcanet', '192.168.1.200:4001', baud1=125000, node_ids=[3])
node_id = 3
# 2. 設置運動參數 (PP模式 - 位置控制)
# 設置工作模式為 4 (PP Mode - Point to Point)
driver.set_work_mode(node_id, 4)
# 設置最大速度
driver.set_pp_speed(node_id, 100000) # 設置最大速度
# 3. 執行運動指令
target_step = 20000 # 目標步數
print(f"開始運動:目標 {target_step} 步")
driver.set_pp_step(node_id, target_step)
driver.set_pp_control_word(node_id, 16)
# 模擬運行一段時間
time.sleep(3)
# 4. 讀取實時狀態
pos = driver.read_motor_position(node_id)
print(f"當前電機位置: {pos}")
# 關閉連接
driver.network.disconnect()
print("連接已斷開")
if __name__ == '__main__':
main()
運行預期結果:
通過引入 ZLGCanNetBus 類,我們成功讓 canopen 庫與ZLG CANET 設備之間連接。配合 pusican.py 的封裝,整套系統具備了以下優勢:
bustype 參數即可,業務代碼無需變動。canopen 庫的 SYNC/PDO 機制擴展即可。附件:
這套方案非常適合實驗室自動化、AGV 小車原型驗證以及遠程設備維護場景。只需一根網線,你的 Python 代碼就能掌控一切動力。