众所周知,Python作为一门面向对象的新兴开发语言,具有非常完善的基础代码库,更注重实用,同时代码可读极强,编写完程序即可直接运行,被越来越多的人广泛将它用于机器视觉和自动化控制。
今天正运动技术与大家分享一下运动控制卡应用开发教程之Python。
一、ECI2828硬件介绍
ECI2828系列运动控制卡支持多达16轴直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴和机械手指令等;采用优化的网络通讯协议可以实现实时的运动控制。
ECI2828系列运动运动控制卡支持以太网,232 通讯接口和电脑相连,接收电脑的指令运行,可以通过EtherCAT总线和CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。
ECI2828系列运动控制卡的应用程序可以使用 VC、VB、VS、C++以及C#等软件来开发,程序运行时需要动态库 zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试,方便观察。
二、Python语言开发流程
Python语言的使用环境
-
操作系统环境:win7_64x
-
Python开发运行环境:PyCharm2019.2
-
Python解释器版本:Python 3.7.4(32bit)
1、新建项目。
打开Pycharm软件进行操作,点击Create New Project新建项目。
2、设置Python项目存放路径。
选择Python项目→选择Python项目将存放的路径→创建Python项目。
3、新建Python文件。
在Python项目中新建Python文件,右键CratPython文件夹,选择“New→PythonFile”,创建新的Python 文件。
4、将Python动态库复制到Python项目中。
5、模块导入并加载动态链接库。
首先把Python中的两个模块导入(platform和ctypes模块),其中ctypes模块提供和C语言兼容的数据类型,能够很方便地调用动态链接库中输出的C接口函数。
import platform
import ctypes
import os
#运行环境判断
systype = platform.system()
if systype == 'Windows':
if platform.architecture()[0] == '64bit':
zauxdll = ctypes.WinDLL('./zauxdll64.dll')
print('Windows x64')
else:
zauxdll = ctypes.WinDLL('./zauxdll.dll')
print('Windows x86')
elif systype == 'Darwin':
zmcdll = ctypes.CDLL('./zmotion.dylib')
print("macOS")
elif systype == 'Linux':
zmcdll = ctypes.CDLL('./libzmotion.so')
print("Linux")
else:
print("Not Supported!!")
6、通过加载导入的动态库链接库,调用ZMotion PC函数手册中的函数。
1)使用操作。
首先根据控制器连接方式用连接函数连接控制器,输出控制器句柄,利用控制器的句柄我们就可以对库函数进行操作。
即“打开PC函数手册→搜索想要的函数功能→查看函数说明→通过刚才加载的动态链接库返回的zauxdll对象进行调用”。
2)通过ip连接函数接口返回的控制器句柄handle,对控制器的句柄handle操作。
#####控制器连接#####
def connect(self, ip, console=[]):
if self.handle.value is not None:
self.disconnect()
ip_bytes = ip.encode('utf-8')
p_ip = ctypes.c_char_p(ip_bytes)
print("Connecting to", ip, "...")
ret = zauxdll.ZAux_OpenEth(p_ip, ctypes.pointer(self.handle))
msg = "Connected"
if ret == 0:
msg = ip + " Connected"
self.sys_ip = ip
self.is_connected = True
else:
msg = "Connection Failed, Error " + str(ret)
self.is_connected = False
console.append(msg)
console.append(self.sys_info)
return ret
# 断开连接
def disconnect(self):
ret = zauxdll.ZAux_Close(self.handle)
self.is_connected = False
return ret
3)我们会提供EtherCAT总线初始化的basic代码,可以通过指令ZAux_BasDown()将总线初始化的basic代码下载到控制器中,从而实现EtherCAT总线轴的初始化。
********************ECAT总线初始化****************
global CONST BUS_TYPE = 0 '总线类型。
global CONST MAX_AXISNUM = 16 '最大轴数
global CONST Bus_Slot = 0 '槽位号0
global CONST Bus_AxisStart = 0 '总线轴起始轴号
global Bus_InitStatus '总线初始化完成状态
Bus_InitStatus = -1
global Bus_TotalAxisnum '检查扫描的总轴数
delay(3000) '延时3S等待驱动器上电
Ecat_Init()
end
global sub Ecat_Init()
'初始化还原轴类型
for i=0 to MAX_AXISNUM - 1
AXIS_ENABLE(i) = 0
ATYPE(i)=0
next
'扫描总线
Bus_InitStatus = -1
Bus_TotalAxisnum = 0
SLOT_STOP(Bus_Slot)
DELAY(200)
SLOT_SCAN(Bus_Slot)
'如果扫描成功
if return then
?"总线扫描成功","连接设备数:"NODE_COUNT(Bus_Slot)
?"开始映射轴号"
'遍历总线下所有从站节点
for i=0 to NODE_COUNT(Bus_Slot)-1
'判断当前节点是否有电机
if NODE_AXIS_COUNT(Bus_Slot,i) <>0 then
for j=0 to NODE_AXIS_COUNT(Bus_Slot,i)-1
'映射轴号
AXIS_ADDRESS(Bus_AxisStart+i)=Bus_TotalAxisnum+1
'设置控制模式 65-位置 66-速度 67-转矩
ATYPE(Bus_AxisStart+i)=65
'设置PROFILE功能
DRIVE_PROFILE(Bus_AxisStart+i)= 4
'每轴单独分组
DISABLE_GROUP(Bus_AxisStart+i)
'映射驱动器上的IO起始地址
DRIVE_IO(Bus_AxisStart+i) = 128 + (Bus_AxisStart+i)*16
'总轴数+1
Bus_TotalAxisnum=Bus_TotalAxisnum+1
next
endif
next
?"轴号映射完成","连接总轴数:"Bus_TotalAxisnum
WA 2000
'总线开启
SLOT_START(Bus_Slot)
if return then
?"总线开启成功"
?"开始清除驱动器错误(根据驱动器数据字典设置)"
for i= Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1
DRIVE_CONTROLWORD(i)=128 '根据驱动器数据字典
wa 100
DRIVE_CONTROLWORD(i)=6
wa 100
DRIVE_CONTROLWORD(i)=15
wa 100
next
?"驱动器错误清除完成"
wa 100
?"清除控制器错误"
DATUM(0)
DRIVE_CLEAR(0)
?"控制器错误清除完成"
wa 100
?"轴使能准备"
for i= Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1
base(i)
AXIS_ENABLE=1
next
'使能总开关
WDOG=1
Bus_InitStatus = 1
?"轴使能完成"
else
?"总线开启失败"
Bus_InitStatus = 0
endif
else
?"总线扫描失败"
Bus_InitStatus = 0
endif
end sub
4)轴参数设置。
#####轴参数设置####
# 设置轴类型
def set_atype(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_SetAtype(self.handle, iaxis, iValue)
if ret == 0:
print("Set Axis (", iaxis, ") Atype:", iValue)
else:
print("Set Axis (", iaxis, ") Atype fail!error:",ret)
return ret
# 设置脉冲当量
def set_units(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_SetUnits(self.handle, iaxis, ctypes.c_float(iValue))
if ret == 0:
print("Set Axis (", iaxis, ") Units:", iValue)
else:
print("Set Axis (", iaxis, ") Units fail!error:",ret)
return ret
# 设置轴加速度
def set_accel(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_SetAccel(self.handle, iaxis, ctypes.c_float(iValue))
if ret == 0:
print("Set Axis (", iaxis, ") Accel:", iValue)
else:
print("Set Accel (", iaxis, ") Accel fail!")
return ret
# 设置轴减速度
def set_decel(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_SetDecel(self.handle, iaxis, ctypes.c_float(iValue))
if ret == 0:
print("Set Axis (", iaxis, ") Decel:", iValue)
else:
print("Set Axis (", iaxis, ") Decel fail!error:",ret)
return ret
# 设置轴运行速度
def set_speed(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_SetAccel(self.handle, iaxis, ctypes.c_float(iValue))
if ret == 0:
print("Set Axis (", iaxis, ") Speed:", iValue)
else:
print("Set Axis (", iaxis, ") Speed fail!error:",ret)
return ret
5)轴参数读取。
####################轴参数读取##################################
# 读取轴脉冲当量
def get_untis(self, iaxis):
iValue = (ctypes.c_float)()
ret = zauxdll.ZAux_Direct_GetUnits(self.handle, iaxis, ctypes.byref(iValue))
if ret == 0:
print("Get Axis (", iaxis, ") Units:", iValue.value)
else:
print("Get Axis (", iaxis, ") Units fail! error:",ret)
return ret
# 读取轴加速度
def get_accel(self, iaxis):
iValue = (ctypes.c_float)()
ret = zauxdll.ZAux_Direct_GetAccel(self.handle, iaxis, ctypes.byref(iValue))
if ret == 0:
print("Get Axis (", iaxis, ") Accel:", iValue.value)
else:
print("Get Axis (", iaxis, ") Accel fail! error:",ret)
return ret
# 读取轴减速度
def get_decel(self, iaxis):
iValue = (ctypes.c_float)()
ret = zauxdll.ZAux_Direct_GetDecel(self.handle, iaxis, ctypes.byref(iValue))
if ret == 0:
print("Get Axis (", iaxis, ") Decel:", iValue.value)
else:
print("Get Axis (", iaxis, ") Decel fail! error:",ret)
return ret
# 读取轴运行速度
def get_speed(self, iaxis):
iValue = (ctypes.c_float)()
ret = zauxdll.ZAux_Direct_GetSpeed(self.handle, iaxis, ctypes.byref(iValue))
if ret == 0:
print("Get Axis (", iaxis, ") Speed:", iValue.value)
else:
print("Get Axis (", iaxis, ") Speed fail! error:",ret)
return ret
6)单轴运动。
# 直线运动
def move(self, iaxis, iValue):
ret = zauxdll.ZAux_Direct_Single_Move(self.handle, iaxis, ctypes.c_float(iValue))
if ret == 0:
print("Axis (", iaxis, ") Move:", iValue)
else:
print("Axis (", iaxis, ") Move Fail! error:",ret)
return ret
# 持续运动
def vmove(self, iaxis, idir):
ret = zauxdll.ZAux_Direct_Single_Vmove(self.handle, iaxis, idir)
if ret == 0:
print("axis (", iaxis, ")Vmoving!")
else:
print("Vmoving fail! error:",ret)
return ret
7)运行程序,输出结果。
######################功能使用####################
zaux = ZMCWrapper()
# 连接控制器ip 默认192.168.0.11
zaux.connect("192.168.0.11")
# 加载EtherCat总线初始化bas文件
filename =os.getcwd()+"\ECAT_INIT.bas"
zaux.BasDown(filename,1)
# 设置轴0参数
zaux.set_units(0, 100)
zaux.set_accel(0, 1000)
zaux.set_decel(0, 1000)
zaux.set_speed(0, 1000)
# 获取轴0参数
zaux.get_untis(0)
zaux.get_accel(0)
zaux.get_decel(0)
zaux.get_speed(0)
# 单轴运动
zaux.move(0,100) # 轴0直线运动移动100位置
本次,正运动技术EtherCAT运动控制卡开发教程之python,就分享到这里。更多精彩内容请关注“正运动小助手”公众号。
本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。