欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Power PMAC 运动控制器 -- 研究说明 1

最编程 2024-05-09 21:30:23
...

Power PMAC运动控制器——学习笔记1

  • 说明
  • 1. 硬件介绍
  • 2. 准备工作
  • 3. PMAC与上位机的连接
  • 4. 创建自己的伺服控制项目
  • 5. 程序下载流程
  • 6. 学习途径
  • 后记

    有很多朋友跟博主一样,拿到PMAC控制器后一脸懵逼,技术只给了几个英文手册,便什么都不管了,咨询问题的时候敷衍了事。为了避免更多朋友像博主一样,决定跟大家分享一下Power PMAC运动控制器的使用经验。


    项目结题,分析原因,我发现我们刚拿到控制器时迷茫的原因有三:

  • 其一,没有任何经验,害怕设备损害的害怕心理;
  • 其二,没有人领进门,即使刚开始的时候技术给提供帮助,在一无所知、大脑一片空白的情况下很快就会忘记技术所给你讲过的内容;
  • 其三,手册的内容太多,且为英文,而多数人英语阅读能力有限

        但是,当你了解到整个开发过程后,再回过头来看,发现手册还是最好的老师

                                                    于2019.08.10修


为了方便大家检索,下面列出学习笔记的目录。

关于 《Power PMAC运动控制器 —— 学习笔记》 系列,目录如下:

  1. Power PMAC运动控制器——学习笔记1,主要介绍了PMAC与IDE环境的连接以及项目的创建
  2. Power PMAC运动控制器——学习笔记2,主要介绍了电机、EtherCAT网络在IDE中的配置以及基本的运动程序编写知识基础
  3. Power PMAC运动控制器——学习笔记3,主要介绍了PMAC中关于坐标系、轴和运动模式的概念,以及运动程序的编写
  4. Power PMAC运动控制器——学习笔记4,主要介绍了正逆运动学在PMAC中的实现
  5. Power PMAC运动控制器——学习笔记5,主要介绍了PLC程序和子程序的编写
  6. Power PMAC运动控制器——学习笔记6,主要介绍了Power PMAC中Modbus通信的实现以及EtherCAT网络的使能
  7. Power PMAC运动控制器——学习笔记7,主要介绍了Power PMAC配置EtherCAT下的力矩控制

说明

       博主由于项目需要开始接触PMAC系列运动控制卡 ,奈何资料太少,能找到的资料由于版本不同的原因导致无法使用,本着开源精神,以此记录整个项目过程中Power PMAC的使用,希望能同各路大神交流分享~

目标:上位机通过Modbus TCP给运动控制卡发送指令实现机械臂的同步控制

1. 硬件介绍

       PMAC全称Programmable Multi-Axis Controller(可编程多轴运动控制器 ),是美国Delta Tau Data System 公司(现已被欧姆龙收购,说到被收购我就不得不吐槽一下,自从被收购以后技术大牛都走了,遇到技术问题只能用户自己瞎摸索,欧姆龙你上点心好嘛 ???? )推出的运动控制器[^1],功能很强大,号称可实现纳米级控制,同步性不错,尤其是插补功能做的非常好,并且支持多厂商的驱动器、光栅尺等。
       本文主要介绍项目中用到的欧姆龙的CK3M型号,模块化的设计深得我心,可实现单元的扩展,而且单元之间的连接无需工具。规格参数如下图所示:


性能参数

       系统基本构成如下图所示:

       更多细节就不多介绍了,详情请参考官网

2. 准备工作

       首先安装PowerPMAC IDE,该IDE环境是基于VS2015开发的,如果你熟悉VS工作环境,那么必然非常容易上手该IDE(如图所示)。


如果你不清楚环境的使用,可以在工具栏的帮助目录下找到PowerPMAC IDE手册,如下所示:

       在熟悉了IDE环境之后(相当于废话哈哈哈哈,直接上手即可),我们直接开干~
需要的手册主要有:软件参考手册、用户使用手册,所有文件已在百度云盘共享(失效请留言)。

3. PMAC与上位机的连接

  • step1 用双绞线电缆建立CK3M与电脑主机的连接,然后给CK3M上电(注意:千万千万千万别接反了,不然稍不留神上万元就没了 ???? )。
  • step2 PMAC默认IP为192.168.0.200,握手成功后我们打开IDE环境,点击:通讯设置->应用,注意要选择设备的IP地址。

    在这里插入图片描述

①连接成功后,IDE的标题栏会显示PMAC的版本信息,且由灰色变为绿色。

在这里插入图片描述

②如果连接失败或者连接没反应,我们可以通过<运行>功能ping一下PMAC,查看是否已经握手成功,如果已经握手成功(如下图所示),上位机会收到CK3M的反馈。
运行:window + R


在这里插入图片描述

那么问题可能出在上位机的IP设置上,找到网络适配器设置,选择与PMAC连接的接口,按下图设置,最后单击确定。(注意:更改适配器的设置可能会导致下次网线连接此口时无法进行网络访问,那时需要恢复设置为【自动获得IP地址】),修改完毕后重复step2。如果仍然连接失败,断开网络再试试。 ????

在这里插入图片描述

4. 创建自己的伺服控制项目

        创建项目的过程跟VS中project的创建几乎无差,在此不再赘述,参见Power PMAC IDE手册P139。项目目录结构如下:


在这里插入图片描述

        为防止在调试过程中由于参数设置不当导致伺服电机或驱动器的损坏,我们可以通过设置虚轴的方式进行模拟调试。
        虚轴设置如下:

//来自官方论坛某大神
// Activate servo algorithms for motors
Motor[1].ServoCtrl=1
Motor[2].ServoCtrl=1
Motor[3].ServoCtrl=1
Motor[4].ServoCtrl=1
Motor[5].ServoCtrl=1
Motor[6].ServoCtrl=1
Motor[7].ServoCtrl=1
Motor[8].ServoCtrl=1

// Write servo output to user shared memory registers
Motor[1].pDac=Sys.Idata[1].a    // Same as EncTable[1].pEnc
Motor[2].pDac=Sys.Idata[2].a    // Same as EncTable[2].pEnc
Motor[3].pDac=Sys.Idata[3].a    // Same as EncTable[3].pEnc
Motor[4].pDac=Sys.Idata[4].a    // Same as EncTable[4].pEnc
Motor[5].pDac=Sys.Idata[5].a    // Same as EncTable[5].pEnc
Motor[6].pDac=Sys.Idata[6].a    // Same as EncTable[6].pEnc
Motor[7].pDac=Sys.Idata[7].a    // Same as EncTable[7].pEnc
Motor[8].pDac=Sys.Idata[8].a    // Same as EncTable[8].pEnc

// Encoder conversion table entry to read and integrate this
EncTable[1].type=1            // 32-bit register read
EncTable[1].pEnc=Sys.idata[1].a    // Same as Motor[1].pDac
EncTable[1].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[1].index1=0            // No shift right of source data
EncTable[1].index2=0            // No shift left of source data
EncTable[1].index3=0            // No accel limiting
EncTable[1].index4=1            // Single integration
EncTable[1].PrevDelta=0        // No bias before integration
EncTable[1].MaxDelta=0        // No velocity limit
EncTable[1].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[2].type=1            // 32-bit register read
EncTable[2].pEnc=Sys.idata[2].a    // Same as Motor[2].pDac
EncTable[2].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[2].index1=0            // No shift right of source data
EncTable[2].index2=0            // No shift left of source data
EncTable[2].index3=0            // No accel limiting
EncTable[2].index4=1            // Single integration
EncTable[2].PrevDelta=0        // No bias before integration
EncTable[2].MaxDelta=0        // No velocity limit
EncTable[2].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[3].type=1            // 32-bit register read
EncTable[3].pEnc=Sys.idata[3].a    // Same as Motor[3].pDac
EncTable[3].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[3].index1=0            // No shift right of source data
EncTable[3].index2=0            // No shift left of source data
EncTable[3].index3=0            // No accel limiting
EncTable[3].index4=1            // Single integration
EncTable[3].PrevDelta=0        // No bias before integration
EncTable[3].MaxDelta=0        // No velocity limit
EncTable[3].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[4].type=1            // 32-bit register read
EncTable[4].pEnc=Sys.idata[4].a    // Same as Motor[4].pDac
EncTable[4].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[4].index1=0            // No shift right of source data
EncTable[4].index2=0            // No shift left of source data
EncTable[4].index3=0            // No accel limiting
EncTable[4].index4=1            // Single integration
EncTable[4].PrevDelta=0        // No bias before integration
EncTable[4].MaxDelta=0        // No velocity limit
EncTable[4].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[5].type=1            // 32-bit register read
EncTable[5].pEnc=Sys.idata[5].a    // Same as Motor[5].pDac
EncTable[5].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[5].index1=0            // No shift right of source data
EncTable[5].index2=0            // No shift left of source data
EncTable[5].index3=0            // No accel limiting
EncTable[5].index4=1            // Single integration
EncTable[5].PrevDelta=0        // No bias before integration
EncTable[5].MaxDelta=0        // No velocity limit
EncTable[5].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[6].type=1            // 32-bit register read
EncTable[6].pEnc=Sys.idata[6].a    // Same as Motor[6].pDac
EncTable[6].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[6].index1=0            // No shift right of source data
EncTable[6].index2=0            // No shift left of source data
EncTable[6].index3=0            // No accel limiting
EncTable[6].index4=1            // Single integration
EncTable[6].PrevDelta=0        // No bias before integration
EncTable[6].MaxDelta=0        // No velocity limit
EncTable[6].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[7].type=1            // 32-bit register read
EncTable[7].pEnc=Sys.idata[7].a    // Same as Motor[7].pDac
EncTable[7].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[7].index1=0            // No shift right of source data
EncTable[7].index2=0            // No shift left of source data
EncTable[7].index3=0            // No accel limiting
EncTable[7].index4=1            // Single integration
EncTable[7].PrevDelta=0        // No bias before integration
EncTable[7].MaxDelta=0        // No velocity limit
EncTable[7].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[8].type=1            // 32-bit register read
EncTable[8].pEnc=Sys.idata[8].a    // Same as Motor[8].pDac
EncTable[8].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[8].index1=0            // No shift right of source data
EncTable[8].index2=0            // No shift left of source data
EncTable[8].index3=0            // No accel limiting
EncTable[8].index4=1            // Single integration
EncTable[8].PrevDelta=0        // No bias before integration
EncTable[8].MaxDelta=0        // No velocity limit
EncTable[8].ScaleFactor=1/65536    // 32 bits -> 16 bits

// Read the encoder conversion table result as feedback
Motor[1].pEnc=EncTable[1].a        // Position loop feedback source
Motor[1].pEnc2=EncTable[1].a    // Velocity loop feedback source
Motor[2].pEnc=EncTable[2].a        // Position loop feedback source
Motor[2].pEnc2=EncTable[2].a    // Velocity loop feedback source
Motor[3].pEnc=EncTable[3].a        // Position loop feedback source
Motor[3].pEnc2=EncTable[3].a    // Velocity loop feedback source
Motor[4].pEnc=EncTable[4].a        // Position loop feedback source
Motor[4].pEnc2=EncTable[4].a    // Velocity loop feedback source
Motor[5].pEnc=EncTable[5].a        // Position loop feedback source
Motor[5].pEnc2=EncTable[5].a    // Velocity loop feedback source
Motor[6].pEnc=EncTable[6].a        // Position loop feedback source
Motor[6].pEnc2=EncTable[6].a    // Velocity loop feedback source
Motor[7].pEnc=EncTable[7].a        // Position loop feedback source
Motor[7].pEnc2=EncTable[7].a    // Velocity loop feedback source
Motor[8].pEnc=EncTable[8].a        // Position loop feedback source
Motor[8].pEnc2=EncTable[8].a    // Velocity loop feedback source


// Disable overtravel limit inputs
// May be needed if there are no physical switches present
Motor[1].pLimits=0
Motor[2].pLimits=0
Motor[3].pLimits=0
Motor[4].pLimits=0
Motor[5].pLimits=0
Motor[6].pLimits=0
Motor[7].pLimits=0
Motor[8].pLimits=0

// Disable amplifier enable output
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpEnable=0
Motor[2].pAmpEnable=0
Motor[3].pAmpEnable=0
Motor[4].pAmpEnable=0
Motor[5].pAmpEnable=0
Motor[6].pAmpEnable=0
Motor[7].pAmpEnable=0
Motor[8].pAmpEnable=0

// Disable amplifier fault input
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpFault=0
Motor[2].pAmpFault=0
Motor[3].pAmpFault=0
Motor[4].pAmpFault=0
Motor[5].pAmpFault=0
Motor[6].pAmpFault=0
Motor[7].pAmpFault=0
Motor[8].pAmpFault=0

// Set derivative gain term in servo loop to zero
// This is a Type 1 servo (single integration); does not need Kd
Motor[1].Servo.Kvfb=0
Motor[2].Servo.Kvfb=0
Motor[3].Servo.Kvfb=0
Motor[4].Servo.Kvfb=0
Motor[5].Servo.Kvfb=0
Motor[6].Servo.Kvfb=0
Motor[7].Servo.Kvfb=0
Motor[8].Servo.Kvfb=0
// Lower proportional gain term from default
Motor[1].Servo.Kp=1
Motor[2].Servo.Kp=1
Motor[3].Servo.Kp=1
Motor[4].Servo.Kp=1
Motor[5].Servo.Kp=1
Motor[6].Servo.Kp=1
Motor[7].Servo.Kp=1
Motor[8].Servo.Kp=1
// Add integral gain to force to zero error
Motor[1].Servo.Ki=0.01
Motor[2].Servo.Ki=0.01
Motor[3].Servo.Ki=0.01
Motor[4].Servo.Ki=0.01
Motor[5].Servo.Ki=0.01
Motor[6].Servo.Ki=0.01
Motor[7].Servo.Ki=0.01
Motor[8].Servo.Ki=0.01
// Set deadband zone to zero
Motor[1].Servo.BreakPosErr=0
Motor[2].Servo.BreakPosErr=0
Motor[3].Servo.BreakPosErr=0
Motor[4].Servo.BreakPosErr=0
Motor[5].Servo.BreakPosErr=0
Motor[6].Servo.BreakPosErr=0
Motor[7].Servo.BreakPosErr=0
Motor[8].Servo.BreakPosErr=0
// Add feedforward to minimize tracking error
Motor[1].Servo.Kvff=1
Motor[1].Servo.Kaff=1
Motor[2].Servo.Kvff=1
Motor