The value of Zmotion is to bring customers more success!
本节主要讲解如何通过C#编写程序调试ZMC432CL-V2的脉冲闭环功能。
一、ZMC432CL-V2产品简介
ZMC432CL-V2高性能多轴运动控制器是一款兼容EtherCAT总线和脉冲型的独立式运动控制器,具备高速实时反馈功能,支持脉冲全闭环控制,能够实现高精度、高响应速度的运动控制。高精度定位,有效消除机械传动误差,满足高精密加工场景应用要求。
1.ZMC432CL-V2硬件功能
ZMC432CL-V2产品介绍视频点击→步进控制的光栅尺全闭环解决方案:32轴EtherCAT总线运动控制器ZMC432CL-V2。
更多关于ZMC432CL-V2详情介绍点击→步进控制的光栅尺全闭环解决方案:32轴EtherCAT总线运动控制器ZMC432CL-V2。
二、C#语言如何调用ZMotion的动态库进行项目开发
(一)新建WinForm项目并添加函数库
3.找到厂家提供的光盘资料里面的C#函数库,路径如下。
三、PC函数介绍
2.控制器/卡接口之链接控制器,获取链接句柄。
3.万能指令之在线命令。
四、C#编写例程调试ZMC432CL-V2的脉冲闭环功能
1.通过在线命令封装脉冲闭环功能对应的上位机接口。
/// <summary> /// 设置轴的比例增益 /// </summary> /// <param name="handle">连接句柄</param> /// <param name="iaxis">轴号</param> /// <param name="fValue">比例增益P的值</param> /// <returns>错误码</returns> public int ZAux_Direct_SetPGain(IntPtr handle, int iaxis, float fValue) { String cmdbuff; //定义命令字符串 //判断轴数是否超标 StringBuilder cmdbuffAck = new StringBuilder(1024); if (iaxis > MAX_AXIS_AUX) { return ERR_AUX_PARAERR; } //生成命令,根据Basic指令的用法格式去拼接命令字符串 cmdbuff = string.Format("P_Gain({0}) = {1}", iaxis, fValue); //调用命令执行函数 return zmcaux.ZAux_DirectCommand(handle, cmdbuff, cmdbuffAck, 2048); }
(3)查询Basic对应指令的使用说明,封装一个获取轴比例增益的上位机接口。
/// <summary> /// 获取轴的比例增益 /// </summary> /// <param name="handle">连接句柄</param> /// <param name="iaxis">轴号</param> /// <param name="fValue">获取的轴比例增益P的值</param> /// <returns>错误码</returns> public int ZAux_Direct_GetPGain(IntPtr handle, int iaxis, ref float fValue) { String cmdbuff; //定义命令字符串 StringBuilder cmdbuffAck = new StringBuilder(1024); //定义接受返回的结果字符串 //判断轴数是否超标 if (iaxis > MAX_AXIS_AUX) { return ERR_AUX_PARAERR; } //生成命令 ?类似于C的printf指令,用于打印,打印出来的字符串通过cmdbuffAck去接收 cmdbuff = string.Format("?P_Gain({0}) ", iaxis); //调用命令执行函数 int iresult = zmcaux.ZAux_Execute(handle, cmdbuff, cmdbuffAck, 2048); if (ERR_OK != iresult) { return iresult; } //解析返回的字符串 if (cmdbuffAck.Length == 0) { return ERR_NOACK; } else { fValue = float.Parse(cmdbuffAck.ToString()); } return ERR_OK; }
(4)封装好的脉冲闭环功能相关的上位机接口。
(2)【连接】按钮如何连接控制器。
int Err = 0; //接口返回的错误码 int LinkMode = 2; //FastOpen接口连接类型的介绍 1-COM 2-ETH 4-PCI 5-LOCAL Err = zmcaux.ZAux_FastOpen(LinkMode, Buffer, 2000, out g_handle); if (Err == 0) { // 修改按钮文字 LinkStatus.Text = "链接状态:OK"; // 修改按钮背景色 LinkStatus.BackColor = Color.FromArgb(192, 255, 192); //相关参数初始化 AxisParaSet(); //进行PID参数的初始化 PidParaSet(); //打开定时器 Timer.Start(); } else { // 修改按钮文字 LinkStatus.Text = "链接状态:Ng"; // 修改按钮背景色 LinkStatus.BackColor = Color.FromArgb(255, 192, 192); //关闭定时器 Timer.Stop(); }
//将上位机设置的PID参数更新到控制器 private int PidParaSet() { float TempFloat = 0; float TempDpos = 0, TempMpos = 0; bool TempInt = false; MyFullClosedLoop CloseLoop = new MyFullClosedLoop(); String CompareStr = "闭环已开"; String TempStr = IsClosedLoop.Text; //打开全闭环去控制轴运动 if (TempStr == CompareStr) { //获取轴位置,如果DPOS和MPOS相差太大不能打开脉冲闭环,保证安全 zmcaux.ZAux_Direct_GetDpos(g_handle, int.Parse(AxisId.Text), ref TempDpos); zmcaux.ZAux_Direct_GetMpos(g_handle, int.Parse(AxisId.Text), ref TempMpos); if ((TempDpos - TempMpos) > 4 || (TempDpos - TempMpos < -4)) { Console.WriteLine("规划位置和反馈位置相差太大,无法启动闭环功能!!!!"); return -1; } //更新比例增益 CloseLoop.ZAux_Direct_SetPGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaP.Text)); //更新积分增益 CloseLoop.ZAux_Direct_SetIGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaI.Text)); //更新微分增益 CloseLoop.ZAux_Direct_SetDGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaD.Text)); //更新速度前馈增益 CloseLoop.ZAux_Direct_SetVffGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaVF.Text)); //更新加速度前馈增益 CloseLoop.ZAux_Direct_SetAffGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaAF.Text)); //更新速度增益 CloseLoop.ZAux_Direct_SetOvGain(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaOV.Text)); //注意:在打开servo之前打开encoder_servo后要完成一次atype由0变为4的切换,否则会报axis:0 config not support Servo. //1、先打开axis_enable 和 encoder_servo zmcaux.ZAux_Direct_SetAxisEnable(g_handle, int.Parse(AxisId.Text), 1); CloseLoop.ZAux_Direct_SetEncoderServo(g_handle, int.Parse(AxisId.Text), 1); Thread.Sleep(20); CloseLoop.ZAux_Direct_GetEncoderServo(g_handle, int.Parse(AxisId.Text), ref TempInt); if (TempInt) { //2、完成一次Atype由0变为4的切换 zmcaux.ZAux_Direct_SetAtype(g_handle, int.Parse(AxisId.Text), 0); Thread.Sleep(20); zmcaux.ZAux_Direct_SetAtype(g_handle, int.Parse(AxisId.Text), 4); //3、打开Servo CloseLoop.ZAux_Direct_SetServo(g_handle, int.Parse(AxisId.Text), 1); Thread.Sleep(10); CloseLoop.ZAux_Direct_GetServo(g_handle, int.Parse(AxisId.Text), ref TempInt); if (TempInt) { Console.WriteLine("闭环参数配置完成, 轴全闭环功能打开成功。"); } else { Console.WriteLine("轴闭环开关Servo打开失败, 导致脉冲全闭环开启失败!!!"); return -1; } } else { Console.WriteLine("轴编码器闭环EncoderServo打开失败, 导致脉冲全闭环开启失败!!!"); return -1; } } else { //关闭全闭环的功能 //1、关闭EncoderServo CloseLoop.ZAux_Direct_SetEncoderServo(g_handle, int.Parse(AxisId.Text), 0); Thread.Sleep(20); CloseLoop.ZAux_Direct_GetEncoderServo(g_handle, int.Parse(AxisId.Text), ref TempInt); if (TempInt) { Console.WriteLine("轴EncoderServo关闭失败!!!"); return -1; } //2、关闭EncoderServo后需要完成ATYPE的切换,保证完全关闭闭环功能 zmcaux.ZAux_Direct_SetAtype(g_handle, int.Parse(AxisId.Text), 0); Thread.Sleep(10); zmcaux.ZAux_Direct_SetAtype(g_handle, int.Parse(AxisId.Text), 4); //3、关闭Servo CloseLoop.ZAux_Direct_SetServo(g_handle, int.Parse(AxisId.Text), 0); Thread.Sleep(20); CloseLoop.ZAux_Direct_GetServo(g_handle, int.Parse(AxisId.Text), ref TempInt); if (TempInt) { Console.WriteLine("轴Servo关闭失败!!!"); return -1; } } return 0; }
//更新轴参数 private void AxisParaSet() { //设置最大随动误差FE_LIMIT zmcaux.ZAux_Direct_SetFeLimit(g_handle, int.Parse(AxisId.Text), 500); //更新编码器齿轮比 (如果发N个脉冲,实际编码器反馈M个脉冲,编码器齿轮比要设置成 N/M) zmcaux.ZAux_Direct_EncoderRatio(g_handle, int.Parse(AxisId.Text), int.Parse(EncoderRatioMol.Text), int.Parse(EncoderRatioDenom.Text)); //更新脉冲当量,一般脉冲当量设置成机台运动1mm需要的脉冲数 zmcaux.ZAux_Direct_SetUnits(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaUnits.Text)); //全闭环的功能需要把ATYPE设置成4 zmcaux.ZAux_Direct_SetAtype(g_handle, int.Parse(AxisId.Text), 4); //更新速度 zmcaux.ZAux_Direct_SetSpeed(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaSpeed.Text)); //更新加速度、减速度 zmcaux.ZAux_Direct_SetAccel(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaAccel.Text)); zmcaux.ZAux_Direct_SetDecel(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaDecel.Text)); StringBuilder Buff = new StringBuilder(512); //是否启用SS曲线 if (CurveIsSS.Checked) { //启用SS曲线,VP_MODE模式设置成7即可 //上位机旧库没有现成设置VP_MODE的接口,直接在线命令去封装,在线命令是万能接口 string CmdBuff = string.Format("VP_MODE({0}) = 7 ", int.Parse(AxisId.Text)); zmcaux.ZAux_DirectCommand(g_handle, CmdBuff, Buff, 512); } else { //启用S曲线,VP_MODE模式设置成0即可 //上位机旧库没有现成设置VP_MODE的接口,直接在线命令去封装,在线命令是万能接口 string CmdBuff = string.Format("VP_MODE({0}) = 0 ", int.Parse(AxisId.Text)); zmcaux.ZAux_DirectCommand(g_handle, CmdBuff, Buff, 512); //S曲线模式,S曲线时间sramp是有效果的,需要设置一下 zmcaux.ZAux_Direct_SetSramp(g_handle, int.Parse(AxisId.Text), float.Parse(text_ParaSramp.Text)); } }
(5)【手动】按钮如何控制脉冲轴的点动与寸动。
//X-鼠标按下 private void ButtonHangRev_MouseDown(object sender, MouseEventArgs e) { if (IsInchMode.Checked) { //寸动运动 zmcaux.ZAux_Direct_Single_Move(g_handle, int.Parse(AxisId.Text), -1 * float.Parse(InchDis.Text)); } else { //手动运动 zmcaux.ZAux_Direct_Single_Vmove(g_handle, int.Parse(AxisId.Text), -1); } } //X-鼠标松开 private void ButtonHangRev_MouseUp(object sender, MouseEventArgs e) { if (IsInchMode.Checked == false) { //手动运动停止 zmcaux.ZAux_Direct_Single_Cancel(g_handle, int.Parse(AxisId.Text), 2); } } //X+鼠标按下 private void ButtonHangFwd_MouseDown(object sender, MouseEventArgs e) { if (IsInchMode.Checked) { //寸动运动 zmcaux.ZAux_Direct_Single_Move(g_handle, int.Parse(AxisId.Text), 1 * float.Parse(InchDis.Text)); } else { //手动运动 zmcaux.ZAux_Direct_Single_Vmove(g_handle, int.Parse(AxisId.Text), 1); } } //X+鼠标松开 private void ButtonHangFwd_MouseUp(object sender, MouseEventArgs e) { if (IsInchMode.Checked == false) { //手动运动停止 zmcaux.ZAux_Direct_Single_Cancel(g_handle, int.Parse(AxisId.Text), 2); } }
五、通过RTSys的示波器对比开环控制和全闭环控制的情况
1.开环控制情况分析
2.闭环控制情况分析
测试发现:步进驱动器的闭环控制,运动过程中随动误差(规划位置和光栅尺反馈位置的差值)除了启动和停止以外大部分保持在0个脉冲当量左右,相比较开环控制有较大的提升,当运动结束时光栅尺的反馈位置和指令规划位置也是相等的。
六、总结
4.教学视频可点击→“步进的光栅尺全闭环EtherCAT运动控制器ZMC432CL-V2(三):C#编程调试”查看。
更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。
正运动技术专注于运动控制技术研究和通用运动控制软硬件产品的研发,是国家级高新技术企业。正运动技术汇集了来自华为、中兴等公司的优秀人才,在坚持自主创新的同时,积极联合各大高校协同运动控制基础技术的研究,是国内工控领域发展最快的企业之一,也是国内少有、完整掌握运动控制核心技术和实时工控软件平台技术的企业。主要业务有:运动控制卡_运动控制器_EtherCAT运动控制卡_EtherCAT控制器_运动控制系统_视觉控制器__运动控制PLC_运动控制_机器人控制器_视觉定位_XPCIe/XPCI系列运动控制卡等。