EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(二):EtherCAT总线初始化

XPCIE1032H功能简介

XPCIE1032H是一款基于PCI Express的EtherCAT总线运动控制卡,可选6-64轴运动控制,支持多路高速数字输入输出,可轻松实现多轴同步控制和高速数据传输。

XPCIE1032H集成了强大的运动控制功能,结合MotionRT7运动控制实时软核,解决了高速高精应用中,PC Windows开发的非实时痛点,指令交互速度比传统的PCI/PCIe快10倍。

在这里插入图片描述

XPCIE1032H支持PWM,PSO功能,板载16进16出通用IO口,其中输出口全部为高速输出口,可配置为4路PWM输出口或者16路高速PSO硬件比较输出口。输入口含有8路高速输入口,可配置为4路高速色标锁存或两路编码器输入。

XPCIE1032H搭配MotionRT7实时内核,使用本地LOCAL接口连接,通过高速的核内交互,可以做到更快速的指令交互,单条指令与多条指令一次性交互时间可以达到3-5us左右。

在这里插入图片描述

➜XPCIE1032H与MotionRT7实时内核的配合具有以下优势:

在这里插入图片描述
1.支持多种上位机语言开发,所有系列产品均可调用同一套API函数库;

2.借助核内交互,可以快速调用运动指令,响应时间快至微秒级,比传统PCI/PCIe快10倍;

3.解决传统PCI/PCIe运动控制卡在Windows环境下控制系统的非实时性问题;

4.支持一维/二维/三维PSO(高速硬件位置比较输出),适用于视觉飞拍、精密点胶和激光能量控制等应用;

5.提供高速输入接口,便于实现位置锁存;

6.支持EtherCAT总线和脉冲输出混合联动、混合插补。

在这里插入图片描述
➜使用XPCIE1032H和MotionRT7进行项目开发时,通常需要进行以下步骤:

1.安装驱动程序,识别XPCIE1032H;

2.打开并执行文件“MotionRT710.exe”,配置参数和运行运动控制实时内核;

3.使用ZDevelop软件连接到控制器,进行参数监控。连接时请使用PCI/LOCAL方式,并确保ZDevelop软件版本在3.10以上;

4.完成控制程序开发,通过LOCAL链接方式连接到运动控制卡,实现实时运动控制。

在这里插入图片描述
➜与传统PCI/PCIe卡和PLC的测试数据结果对比:

在这里插入图片描述

我们可以从测试对比结果看出,XPCIE1032H运动控制卡配合实时运动控制内核MotionRT7,在LOCAL链接(核内交互)的方式下,指令交互的效率是非常稳定,当测试数量从1w增加到10w时,单条指令交互时间与多条指令交互时间波动不大,非常适用于高速高精的应用。

XPCIE1032H卡安装

  • 关闭计算机电源。
  • 打开计算机机箱,选择一条空闲的XPCIE卡槽,用螺丝刀卸下相应的挡板条。
  • 将运动控制卡插入该槽,拧紧挡板条上的固定螺丝。

XPCIE1032H驱动安装与建立连接参考往期文章EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(一):驱动安装与建立连接。

一、新建C#项目(VS2022)

在这里插入图片描述

到正运动技术官网的下载中心选择需要的平台库文件。
在这里插入图片描述

解压下载的安装包找到 “Zmcaux.cs” , “zauxdll.dll” , “zmotion.dll” 放入到项目文件中。

1、“Zmcaux.cs”放在项目根目录文件中,与bin目录同级。

在这里插入图片描述

2、“zauxdll.dll”,“zmotion.dll”放在bin -> Debug。

在这里插入图片描述

用vs打开新建的项目文件,在右边的解决方案资源管理器中点击显示所有,选中项目,右键“添加”->“现有项”,选中zmcaux.cs文件添加进在项目中。

在这里插入图片描述
在这里插入图片描述

双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入using cszmcaux,并声明控制器句柄g_handle。

在这里插入图片描述

二、相关PC函数介绍

相关PC函数介绍详情可参考“ZMotion PC函数库编程手册 V2.1.1”。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

其他基本轴参数指令:

在这里插入图片描述

在form设计界面找到需要用到的控件拖拽到窗体中进行UI界面设计,设计效果图如下。

在这里插入图片描述

三、相关程序以及设计思路

1、通过LOCAL链接方式,按钮控件的的click事件触发链接控制卡。

private void Local_Connect_Button_Click(object sender, EventArgs e)
{
    if (g_handle == (IntPtr)0)
    {
        Local_DisConnect_Button_Click(sender, e);
    }
    zmcaux.ZAux_FastOpen(5, "local", 1000, out g_handle);
    if (g_handle != (IntPtr)0)
    {
        this.Text = "已链接";
        timer1.Enabled = true;
        Local_Connect_Button.BackColor = Color.Green;
        MessageBox.Show("链接成功");
    }
    else
    {
        MessageBox.Show("链接失败,请选择正确的LOCAL!");
    }
}

2、选择总线初始化的bas脚本文件下载到控制器rom里面掉电保存。

提前在zdevelop软件根据需求修改总线初始化的basic程序,映射轴,节点IO等初始化内容。

这里以节点0(汇川驱动器-0轴)、节点1(EIO16084)的1-4轴映射为总线轴为例,将节点之间通过ETHERCAT口连接起来。如下图:

在这里插入图片描述

相关初始化basic程序(其中红色为指令,可以到正运动官网查阅其使用场景以及方法)。

相关配置如下:

'ECAT总线初始化
GLOBAL CONST BUS_TYPE = 0         '总线类型。可用于上位机区分当前总线类型
GLOBAL CONST Bus_Slot  = 0        '槽位号0(单总线控制器缺省0)
GLOBAL CONST PUL_AxisStart   = 0    '本地脉冲轴起始轴号
GLOBAL CONST PUL_AxisNum   = 0    '本地脉冲轴轴数量
GLOBAL CONST Bus_AxisStart   = 0      '总线轴起始轴号
GLOBAL CONST Bus_NodeNum   = 1      '总线配置节点数量,用于判断实际检测到的从站数量是否一致
GLOBAL MAX_AXISNUM        '最大轴数
MAX_AXISNUM = SYS_ZFEATURE(0)
GLOBAL Bus_InitStatus      '总线初始化完成状态
Bus_InitStatus = -1
GLOBAL Bus_TotalAxisnum    '检查扫描的总轴数
DELAY(3000)        '延时3S等待驱动器上电,不同驱动器自身上电时间不同,具体根据驱动器调整延时
?"总线通讯周期:",SERVO_PERIOD,"us"
Ecat_Init()      '初始化ECAT总线 
END
GLOBAL SUB Ecat_Init()
  local Node_Num,Temp_Axis,Drive_Vender,Drive_Device,Drive_Alias
  RAPIDSTOP(2)
  for i = 0 to SYS_ZFEATURE(0) - 1                '初始化还原轴类型          
    AXIS_ENABLE(i) = 0
    ATYPE(i) = 0  
    DELAY(20)
  next
  
  Bus_InitStatus = -1
  Bus_TotalAxisnum = 0  
  SLOT_STOP(Bus_Slot)        
  DELAY(200)
  SLOT_SCAN(Bus_Slot)                      '扫描总线
  if return then 
    ?"总线扫描成功","连接从站设备数:"NODE_COUNT(Bus_Slot)
    if NODE_COUNT(Bus_Slot) <> Bus_NodeNum then    '判断总线检测数量是否为实际接线数量
      ?""  
      ?"扫描节点数量与程序配置数量不一致!" ,"配置数量:"Bus_NodeNum,"检测数量:"NODE_COUNT(Bus_Slot)
      Bus_InitStatus = 0    '初始化失败。报警提示
    endif   
    
    '"开始映射轴号"
    for Node_Num = 0 to NODE_COUNT(Bus_Slot)-1            '遍历扫描到的所有从站节点
      Drive_Vender = NODE_INFO(Bus_Slot,Node_Num,0)        '读取驱动器厂商
      Drive_Device = NODE_INFO(Bus_Slot,Node_Num,1)        '读取设备编号
      Drive_Alias = NODE_INFO(Bus_Slot,Node_Num,3)          '读取设备拨码ID
      
      if NODE_AXIS_COUNT(Bus_Slot,Node_Num) <> 0 then      '判断当前节点是否有电机
        for j=0 to NODE_AXIS_COUNT(Bus_Slot,Node_Num)-1    '根据节点带的电机数量循环配置轴参数(针对一拖多驱动器)
        
          Temp_Axis = Bus_AxisStart + Bus_TotalAxisnum    '轴号按NODE顺序分配
          BASE(Temp_Axis)
          AXIS_ADDRESS = Bus_TotalAxisnum+1          '映射轴号
          ATYPE = 65                      '设置控制模式 65-位置 66-速度 67-转矩 
          DRIVE_PROFILE = 18
          Sub_SetDriverIo(Temp_Axis,Drive_Vender,48 + 48*Temp_Axis)    '映射驱动器IO  IO映射到控制器IO32-以后每个驱动器间隔32DISABLE_GROUP(Temp_Axis)              '每轴单独分组
          Bus_TotalAxisnum = Bus_TotalAxisnum+1          '总轴数+1
        next
      endif
    next
    
    ?"轴号映射完成","连接总轴数:"Bus_TotalAxisnum
    
    WA 200
    SLOT_START(Bus_Slot)        '启动总线
    if return then 
      
      WDOG = 1              '使能总开关
      for i = Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1 
        BASE(i)
        DELAY 50        
        AXIS_ENABLE = 1
      next
      Bus_InitStatus  = 1
      ?"轴使能完成"
      
      ?"总线开启成功"      
    else
      ?"总线开启失败"
      Bus_InitStatus = 0
    endif
  else
    ?"总线扫描失败"
    Bus_InitStatus = 0
  endif
ENDSUB
'总线驱动IO映射
'iAxis - 轴号 iVender - 驱动器类型  i_IoNum - 输入输出起始编号
GLOBAL SUB Sub_SetDriverIo(iAxis,iVender,i_IoNum) 
DRIVE_IO(Iaxis) = i_IoNum
FWD_IN(Iaxis) = i_IoNum
REV_IN(Iaxis) = i_IoNum + 1              
DATUM_IN(Iaxis) = i_IoNum + 2      
INVERT_IN(i_IoNum,ON)          
INVERT_IN(i_IoNum + 1,ON)
INVERT_IN(i_IoNum + 2,ON) 
ENDSUB

利用按钮的click事件,浏览选择编辑好的bas文件下载掉电保存,并弹出反馈下载是否成功的提示。

private void BasFileDownLoad_Btn_Click(object sender, EventArgs e)
{
    if (g_handle == (IntPtr)0)
    {
        MessageBox.Show("未链接到控制器!", "提示");
    }
    else
    {
        int tmpret = 0;
        string strFilePath;
        OpenFileDialog openFileDialog1 = new OpenFileDialog();
        openFileDialog1.InitialDirectory = "\\";
        openFileDialog1.Filter = "配置文件(*.bas)|*.bas";
        openFileDialog1.RestoreDirectory = true;
        openFileDialog1.FilterIndex = 1;
        if (openFileDialog1.ShowDialog() == DialogResult.OK)            
        {
            //打开配置文件
            strFilePath = openFileDialog1.FileName;
            //下载到ROM
            tmpret = zmcaux.ZAux_BasDown(g_handle, strFilePath, 1);        
            if (tmpret != 0)
            {
                MessageBox.Show("文件下载失败!", "提示");
            }
            else
            {                       
                MessageBox.Show("文件下载成功!", "提示");
            }
        }
    }
}

3、通过按钮控件的click事件触发初始化。

调用函数库的ZAux_Execute函数(在线命令),通过在线命令调用basic脚本里面的总线初始化函数–Ecat_Init()进行总线初始化。

private void EcatInitStart_Btn_Click(object sender, EventArgs e)
{
    if (g_handle == (IntPtr)0)
    {
        MessageBox.Show("未链接到控制器!", "提示");
    }
    else
    {
        int tmpret;
        //-1可能正在执行初始化
        if ((BasFlag == true) && (InitStatus != -1))        
        {
            InitStatus = -1;
            StringBuilder buffer = new StringBuilder(10240);
            tmpret = zmcaux.ZAux_Execute(g_handle, "RUNTASK 1,Ecat_Init", buffer, 0);        //任务1重新运行BAS中的初始化函数
            if (tmpret != 0)
            {
                MessageBox.Show("总线初始化失败!", "提示");
                return;
            }
            else
            {   
                MessageBox.Show("总线初始化成功!", "提示");
            }
        }
        else
        {
            MessageBox.Show("Bas文件未加载");
            return;
        }
    }
}

4、以汇川驱动器为例,驱动器IO映射的起始地址为DI1,也就是正向超程开关(正硬限位),若要设置负向超程开关,将起始地址加1。

可以通过按钮控件的click事件,触发设置轴的软限位,以及原点、正负硬限位。驱动器IO映射的basic指令是DRIVE_IO。在这里调用在线命令的PC函数去实现驱动器IO映射。

Basic指令说明见下图:

在这里插入图片描述

DRIVE_IO – 驱动器IO:

在这里插入图片描述

通过按钮控件的click事件,配置轴的正负软限位和驱动器IO起始地址(正负硬限位IO映射)。

private void Configure_OK_Button_Click(object sender, EventArgs e)
{
    StringBuilder buffer = new StringBuilder(10240);
    //正向软限位设置
    zmcaux.ZAux_Direct_SetFsLimit(g_handle, MoveAxis, Convert.ToSingle(FSLimit_Value.Text));
    //负向软限位设置
    zmcaux.ZAux_Direct_SetRsLimit(g_handle, MoveAxis, Convert.ToSingle(RSLimit_Value.Text));          
    //驱动器IO起始地址           
    zmcaux.ZAux_Execute(g_handle, "DRIVE_IO(" + MoveAxis.ToString() + ") = " +DriveStart_IO_Value.Value.ToString(), buffer, 0);
    //正硬限位设置
    zmcaux.ZAux_Direct_SetFwdIn(g_handle, MoveAxis, DRIVE_Start_IO);
    zmcaux.ZAux_Direct_SetInvertIn(g_handle, DRIVE_Start_IO, 1);
    //负硬限位设置
    zmcaux.ZAux_Direct_SetRevIn(g_handle, MoveAxis, DRIVE_Start_IO + 1);
    zmcaux.ZAux_Direct_SetInvertIn(g_handle, DRIVE_Start_IO + 1, 1);
    MessageBox.Show("当前轴配置成功!", "提示");
}

5、通过按钮控件的MouseDown(鼠标在组件上方并按下时发生)事件来触发单轴持续运动;MouseUp(鼠标在组件上方并松开时发生)事件来触发单轴运动的停止。模拟手动运动的调试过程。

//正向
private void Fwd_Button_MouseDown(object sender, MouseEventArgs e)
{ 
    zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, 1);
}
private void Fwd_Button_MouseUp(object sender, MouseEventArgs e)
{
    zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2);
}
//负向
private void Rev_Button_MouseDown(object sender, MouseEventArgs e)
{
    zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, -1);
}
private void Rev_Button_MouseUp(object sender, MouseEventArgs e)
{
    zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2);
}

6、通过textbook控件的TextChanged(空间上text属性更改时发生)事件来修改运动过程中轴的基本参数,定时器会获取接收。

//脉冲当量变化
private void Units_Value_TextChanged(object sender, EventArgs e)
{
    zmcaux.ZAux_Direct_SetUnits(g_handle, MoveAxis, Convert.ToSingle(Units_Value.Text));
}
//轴速度变化
private void Speed_Value_TextChanged(object sender, EventArgs e)
{
    zmcaux.ZAux_Direct_SetSpeed(g_handle, MoveAxis, Convert.ToSingle(Speed_Value.Text));
}
//加速度变化
private void Accel_Value_TextChanged(object sender, EventArgs e)
{
    zmcaux.ZAux_Direct_SetAccel(g_handle, MoveAxis, Convert.ToSingle(Accel_Value.Text));
}
//减速度变化
private void Decel_Value_TextChanged(object sender, EventArgs e)
{
    zmcaux.ZAux_Direct_SetDecel(g_handle, MoveAxis, Convert.ToSingle(Decel_Value.Text));
}

7、通过按钮控件,与文本信息比对,触发总线轴的使能切换功能。

private void Enable_Button_Click(object sender, EventArgs e)
{
    if (g_handle == (IntPtr)0)
    {
        MessageBox.Show("未链接到控制器!", "提示");
        return;
    }
    int ret = 0;
    if (Enable_Value.Text == "ON")
    {
        ret = zmcaux.ZAux_Direct_SetAxisEnable(g_handle, MoveAxis, 0);
    }
    else
    {
        ret = zmcaux.ZAux_Direct_SetAxisEnable(g_handle, MoveAxis, 1);
    }
}

8、通过复选框的切换、单选框的选择实现寸动运动调试的功能。

//寸动方向选择
private void MoveDirection_CheckedChanged(object sender, EventArgs e)
{
    if (MoveDirection.Checked == false)
    {
        MoveDirection.Text = "运动方向: 正";
        dir = 1;
    }
    else
    {
        MoveDirection.Text = "运动方向: 负";
        dir = -1;
    }
}
//寸动启动
private void InchStart_Button_Click(object sender, EventArgs e)
{
    if (g_handle == (IntPtr)0)
    {
        MessageBox.Show("未链接到控制器!", "提示");
    }
    else
    {
        //绝对运动
        if (MoveAbs_RadBtn.Checked == true)     
        {
            zmcaux.ZAux_Direct_Single_MoveAbs(g_handle, MoveAxis, dir * Convert.ToSingle(InchDistance_Value.Text));
        }
        //相对运动
        if (MoveOpp_RadBtn.Checked == true)        
        {
            zmcaux.ZAux_Direct_Single_Move(g_handle, MoveAxis, dir * Convert.ToSingle(InchDistance_Value.Text));
        }
    }
}

9、通过定时器的刷新,对轴参数的接收,初始化信息,IO监控等信息进行实时的反馈。

//轴参数更新
private void Update_AxisPara()
{
    int CurAxisAtype = 0;
    int CurAxisIdle = 0;
    int CurAxisStatus = 0;  
    double CurAxisFSLimit = 0;
    double CurAxisRSLimit = 0;
    double CurAxisDpos = 0;
    double CurAxisMpos = 0;
    Axis_Para[0] = Convert.ToSingle(Units_Value.Text);
    Axis_Para[1] = Convert.ToSingle(Speed_Value.Text);
    Axis_Para[2] = Convert.ToSingle(Accel_Value.Text);
    Axis_Para[3] = Convert.ToSingle(Decel_Value.Text);         
    MoveAxis = Convert.ToInt32(AxisNum_Value.Text);
    zmcaux.ZAux_Direct_GetAtype(g_handle, MoveAxis, ref CurAxisAtype);
    zmcaux.ZAux_Direct_GetDpos(g_handle, MoveAxis, ref CurAxisDpos);
    zmcaux.ZAux_Direct_GetMpos(g_handle, MoveAxis, ref CurAxisMpos);
    zmcaux.ZAux_Direct_GetIfIdle(g_handle, MoveAxis, ref CurAxisIdle);
    zmcaux.ZAux_Direct_GetAxisStatus(g_handle, MoveAxis, ref CurAxisStatus);
    zmcaux.ZAux_Direct_GetUnits(g_handle, MoveAxis, ref Axis_Para[0]);
    zmcaux.ZAux_Direct_GetSpeed(g_handle, MoveAxis, ref Axis_Para[1]);
    zmcaux.ZAux_Direct_GetAccel(g_handle, MoveAxis, ref Axis_Para[2]);
    zmcaux.ZAux_Direct_GetDecel(g_handle, MoveAxis, ref Axis_Para[3]);       
    zmcaux.ZAux_Direct_GetFsLimit(g_handle, MoveAxis, ref CurAxisFSLimit);
    zmcaux.ZAux_Direct_GetRsLimit(g_handle, MoveAxis, ref CurAxisRSLimit);
    if (EcatInitFlag == true)   //总线初始化完成后实时显示状态信息
    {
        AxisAtype_Label.Text = "轴 类 型:  " + CurAxisAtype;
        AxisDpos_Label.Text = "DPOS位置:  " + CurAxisDpos;
        AxisMpos_Label.Text = "MPOS位置:  " + CurAxisMpos;
        AxisIdle_Label.Text = "运动状态:  " + CurAxisIdle;
        AxisStatus_Label.Text = "轴 状 态:  " + CurAxisStatus;
    } 
}

10、通过按钮控件的的click事件触发断开链接。

private void Local_DisConnect_Button_Click(object sender, EventArgs e)
{
    timer1.Enabled = false;
    zmcaux.ZAux_Close(g_handle);
    g_handle = (IntPtr)0;
    Local_DisConnect_Button.BackColor = Color.White;
    this.Text = "未连接";
}

四、运行效果

运行主界面如下:
在这里插入图片描述

附录:basic初始化程序通用模板

global CONST BUS_TYPE = 0         '总线类型。用于上位机区分当前模式
global CONST MAX_AXISNUM = 32       '最大轴数
global CONST Bus_Slot  = 0        '槽位号0
global CONST Bus_AxisStart   = 0    '总线轴起始轴号
global Bus_InitStatus      '总线初始化完成状态
Bus_InitStatus = -1
global Bus_TotalAxisnum    '检查扫描的总轴数
delay(3000)        '延时3S等待驱动器上电
'**********************初始化ECAT总线**********************
Ecat_Init()
    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)
        ?"开始映射轴号"
    endif
        
    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    '映射轴号
                ATYPE(Bus_AxisStart+i)=65            '设置控制模式 
                DRIVE_PROFILE(Bus_AxisStart+i)= 4        '设置PROFILE功能
                disable_group(Bus_AxisStart+i)          '每轴单独分组
                DRIVE_IO(Bus_AxisStart+i) = 128 + (Bus_AxisStart+i)*16  
                REV_IN(Bus_AxisStart+i) = 128 + (Bus_AxisStart+i)*16 
                FWD_IN(Bus_AxisStart+i) = 129 + (Bus_AxisStart+i)*16
                DATUM_IN(Bus_AxisStart+i) = 130 + (Bus_AxisStart+i)*16
                INVERT_IN(128 + (Bus_AxisStart+i)*16,ON)
                INVERT_IN(129 + (Bus_AxisStart+i)*16,ON)
                INVERT_IN(130 + (Bus_AxisStart+i)*16,ON)
                Bus_TotalAxisnum=Bus_TotalAxisnum+1          '总轴数+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
    ?"总线扫描失败"
    Bus_InitStatus  = 0
end sub

本次,正运动技术EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(二):EtherCAT总线初始化,就分享到这里。

更多精彩内容请关注“正运动小助手”公众号。

本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/157109.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Isight 2023 新功能介绍

​​Isight是一个仿真分析流程自动化和多学科多目标优化工具&#xff0c;它提供了一个可视化的灵活的仿真流程搭建平台&#xff0c;同时提供与多种主流CAE分析工具的专用接口&#xff0c;利用此工具&#xff0c;用户可以方便的以拖拽的方式可视化的快速建立复杂的仿真分析流程&…

达芬奇DaVinci Resolve Studio 18.6.3 for Mac

DaVinci Resolve Studio 18是一款专业的视频编辑和调色软件&#xff0c;适用于电影、电视节目、广告等各种视觉媒体的制作。它具有完整的后期制作功能&#xff0c;包括剪辑、调色、特效、音频处理等。 以下是DaVinci Resolve Studio 18的主要特点&#xff1a; - 提供了全面的视…

一、认识STM32

目录 一、初识STM32 1.1 STM32的命名规则介绍 1.2 STM32F103ZET6资源配置介绍 二、如何识别芯片管脚 2.1 如何寻找 IO 的功能说明 三、构成最小系统的要素 一、初识STM32 1.1 STM32的命名规则介绍 以 STM32F103ZET6 来讲解下 STM32 的命名方法&#xff1a; &…

SpringBoot 2.x 实战仿B站高性能后端项目

SpringBoot 2.x 实战仿B站高性能后端项目 下栽の地止&#xff1a;请看文章末尾 通常SpringBoot新建项目&#xff0c;默认是集成了Maven&#xff0c;然后所有内容都在一个主模块中。 如果项目架构稍微复杂一点&#xff0c;就需要用到Maven多模块。 本文简单概述一下&#xff0c…

无线振动温度传感器设备的振动监测故障诊断

近年来&#xff0c;随着工业领域技术水平的不断提高&#xff0c;工业设备的管理水平也必须紧随其后&#xff0c;既要保证设备的正常运转&#xff0c;同时也要做好日常的保养维护工作。旋转类设备是一种较为常见的工业设备&#xff0c;随着无线振动温度传感器设备的引入&#xf…

百家网约车平台发布“阳光五条” 多举措加强司机保障

11月17日&#xff0c;免佣联盟百家网约车平台发布“阳光五条”&#xff0c;通过加大免佣力度、实行车费保镖司机版、72小时保护期等措施&#xff0c;加强对网约车司机的权益保障。 近年&#xff0c;交通运输部推动交通运输新业态平台企业落实“阳光行动”等工作&#xff0c;加…

MyCat基础入门

1. MyCat安装 去官网下载安装包&#xff1a; 下载路径&#xff1a; 官方网站&#xff1a;http://www.mycat.org.cn/ github地址https://github.com/MyCATApache 上传到服务器上并解压&#xff1a; 它解压后是一个叫mycat的文件夹 去maycat的bin目录下&#xff0c;执行命令 ./my…

修完这个 Bug 后,MySQL 性能提升了 300%

最近 MySQL 官方在 8.0.35 上修复了一个 bug&#xff1a; 这个 bug 是由 Mark Callaghan 发现的。Mark 早年在 Google MySQL 团队&#xff0c;后来去了 Meta MySQL&#xff0c;也主导了 RocksDB 的开发。 Mark 在 #109595 的 bug report 给出了非常详细的复现步骤 在官方修复后…

电源模块输出过冲如何产生?测试标准及其测试方法是什么?

输出电压过冲是一个常见的电路问题&#xff0c;它是指在电路中的电压超过了规定的范围&#xff0c;严重的话会造成系统不稳定&#xff0c;导致元器件、负载以及设备损坏。那么造成输出电压过冲的原因有哪些呢&#xff1f;电源自动测试系统要怎么测试输出过冲? 输出电压过冲产生…

基于SpringBoot、Vue的电影院管理系统

一、管理端 1.登陆界面 2.影院管理界面 3.电影信息管理页 4.订单信息管理页 二、 用户 1.登录页 2.首页 3.个人中心 4.监控大屏&#xff08;此功能可单加&#xff09; 需要的同学可以私我v哟 jg低廉 包调试安装

人体状态检测YOLOV8 NANO

人体状态检测Y8N&#xff0c;能检测站立、奔跑、跌倒、坐下、蹲下五种状态&#xff0c;采用YOLOV8NANO训练&#xff0c;转换成ONNX&#xff0c;OPENCV DNN调用&#xff0c;支持C/PYTHON/ANDROID开发 人体状态检测Y8N

Visual Components数字化工厂虚拟仿真软件 衡祖仿真

数字孪生、人工智能、工业互联网、边缘计算这些概念在整个产业里非常的火热&#xff0c;但是&#xff0c;如果这些概念没有“模型”作为基础的话&#xff0c;那么这些概念都只能是空中楼阁无法落地。而仿真技术是利用这些模型在计算机中构建一比一的真实场景&#xff0c;使得在…

MessageSourceUtil读取资源文件

在处理返回值提示的时候&#xff0c;需要根据local返回中文或者英文&#xff0c;因此要使用到国际化内容 操作 1&#xff0c;新建资源文件 在src/main/resources源文件夹下创建一个i18n的子目录&#xff0c; 然后创建中文和英文对应properties文件&#xff0c;然后输入自己的…

Hive Lateral View explode列为空时导致数据异常丢失

一、问题描述 日常工作中我们经常会遇到一些非结构化数据&#xff0c;因此常常会将Lateral View 结合explode使用&#xff0c;达到将非结构化数据转化成结构化数据的目的&#xff0c;但是该方法对应explode的内容是有非null限制的&#xff0c;否则就有可能造成数据缺失。 SE…

【机器学习10】循环神经网络

1循环神经网络 RNN通过将神经元串行起来处理序列化的数据。 由于每个神经元能用它的内部变量保存之前输入的序列信息&#xff0c;因此整个序列被浓缩成抽象的表示&#xff0c; 并可以据此进行分类或生成新的序列。 2 循环神经网络的梯度消失或梯度爆炸问题 传统的循环神经网…

websocket学习

写在前面 新公司用到了websocket技术&#xff0c;所以这里学习下。 1&#xff1a;Java原生 1.1&#xff1a;maven <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.5.3</ver…

代码随想录算法训练营第五十七天丨 动态规划part17

647. 回文子串 思路 动态规划 动规五部曲&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 如果大家做了很多这种子序列相关的题目&#xff0c;在定义dp数组的时候 很自然就会想题目求什么&#xff0c;我们就如何定义dp数组。 绝大多数题目确实是…

【java学习—十五】经典例题:生产者/消费者问题(7)

文章目录 1. 题目2. 答案 1. 题目 生产者 (Productor) 将产品交给店员 (Clerk) &#xff0c;而消费者 (Customer)从店员处取走产品&#xff0c;店员一次只能持有固定数量的产品 ( 比如 4 &#xff09;&#xff0c;如果生产者试图生产更多的产品&#xff0c;店员会叫生产者停一下…

特隆美储能PVS ASEAN 2023展览会完美落幕

2023年11月14-16日&#xff0c;特隆美储能参加在印尼雅加达举办的“2023东盟光伏与储能展览会”&#xff08;简称PVS ASEAN 2023&#xff09;。该展会展览面积达20000平米&#xff0c;有超过300家企业参展。 展会旨在推动印度尼西亚以及东南亚地区朝着绿色可持续发展和高能效的…

鉴源论坛 · 观模丨软件单元测试真的有必要吗?(下)

作者 | 包丹珠 上海控安产品总监 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” “软件单元测试真的有必要吗&#xff1f;&#xff08;上&#xff09;”一文中&#xff0c;着重探讨了单元测试的重要性及其正面临的困境&#xff0c…