vbs获取程序窗体句柄_研华运动控制卡程序开发编写——板卡初始化
本文主要介绍研华运动控制卡初始化和反初始化的程序编写,由于研华的脉冲型运动控制卡和EtherCAT总线运动控制卡共用同样的API接口,因此该程序适用于脉冲型和EtherCAT总线的板卡初始化程序编写,本文的编程以C#为例。
1. 准备工作
1)为了方便,此次我们以虚拟卡代替实体卡进行编程,可以参考“
研华运动控制卡虚拟轴卡安装”一文进行虚拟卡安装,建议安装两张以上虚拟卡。
2)新建一个C#的项目工程,可以参考“
研华运动控制卡C#项目开发”一文进行创建项目工程。
2. 板卡初始化流程
1)Acm_GetAvailableDevs 获取工控机中有用的运动控制卡信息,调用这个函数主要是获得板卡个数和每个板卡对应的DeviceNum。
函数原型:U32 Acm_GetAvailableDevs(DEVLIST *DeviceList, U32 MaxEntries,PU32 OutEntries)
DeviceList是指针指向返回可用设备信息列表,在C#表现就是返回可用设备的一维数组。
MaxEntries是指需要获取的最大设备个数,比如填10,就是最多可以获得10个板卡设备
OutEntries是指向实际返回的设备个数的指针,即工控机目前有的板卡设备个数
DEVLIST 为自定义结构体,定义如下:
typedef struct tagPT_DEVLIST
{
DWORD dwDeviceNum; // Acm_DevOpen 所需要的设备号
char szDeviceName[50]; // 设备名
SHORT nNumOfSubdevices; // 用于AMONET板卡,对于Common Motion板卡
// 该值为0
} DEVLIST, *LPDEVLIST;
因此调用Acm_GetAvailableDevs()函数主要是获取板卡的DeviceNum和设备个数。
2)Acm_DevOpen 打开板卡设备,并获取对应设备的句柄。
函数原型:U32 Acm_DevOpen (U32 DeviceNumber, PHAND DeviceHandle)
DeviceNumber打开设备需要用到的设备编号即DeviceNum,获取DeviceNum有三种方式:(1)从Acm_GetAvailableDevs中的DeviceList中获取到对应板卡的DeviceNum。(2)用Acm_GetDevNum 给定板卡类型和BoardID值也可以获得对应板卡的DeviceNum。(3)直接从Common Motion Utility中直接获得板卡的DeviceNum,如下图。
3)通过设备句柄读取设备的轴数特性FT_DevAxesCount,可以获得对应设备所具有的轴数,方便打开轴时直接用获得的轴数,循环打开所有轴。
Acm_GetU32Property(DeviceHandle, FT_DevAxesCount, ref AxesCount)
4)Acm_AxOpen 根据Acm_DevOpen 获得的设备句柄,打开板卡设备指定轴,并获得轴对应的句柄
函数原型:U32 Acm_AxOpen (HAND DeviceHandle, U16 PhyAxis, PHAND
AxisHandle)
5)Acm_DevLoadConfig 加载板卡的配置参数文件,切记加载配置参数时必须所有轴都打开,才能加载配置参数,不然会报错。
板卡的配置参数文件是用Common Motion Utility设置好各个轴的参数,然后保存出来的,如下图保存。
6)Acm_AxGetState 获取轴当前的状态,若轴当前的状态是ErrorStop则需要调用Acm_AxResetError函数进行清除。切记,只有轴的状态是Ready时(即用Acm_AxGetState返回值是1)才能对轴下运动指令(如点到点运动或者回原点运动)。
7)Acm_AxSetSvOn 用来打开或关闭伺服驱动器的使能。伺服电机只有上了使能才能正常运动,没有上使能是不能运动的。因此针对伺服驱动器需要进行打开使能操作,若是脉冲型的步进,可以不进行打开使能的操作。
但是对于EtherCAT总线的驱动器,不管是伺服还是步进都需要进行打开使能才能正常驱动电机运动。
3. 板卡反初始化流程
1)Acm_AxStopDec 让轴做减速停止。反初始化就是要将板卡关闭或者关闭程序,必须保证轴可靠停止才能将程序关闭。
函数原型:U32 Acm_AxStopDec (HAND AxisHandle))
2)Acm_GpRemAxis 将指定轴将轴群移出。为了确保轴群正常关闭,需要将轴从轴群移出。
3)Acm_GpClose 关闭轴群句柄。关闭程序需要将轴群关闭,确保轴句柄注销,不要滞留。
4)Acm_AxClose 关闭已经打开的轴。关闭程序需要将轴关闭,确保轴句柄注销,避免影响下次使用。
5)Acm_DevClose 关闭已经打开板卡设备。关闭程序需要将板卡设备关闭,确保设备句柄注销,避免影响下次开卡。
4. 代码实现板卡初始化和反初始化
1)板卡初始化代码如下:
全局变量
publicconstuint MAX_DEVICES =16; //最多支持16张板卡 protectedDEV_LIST[] mCurAvailableDevs= newDEV_LIST[MAX_DEVICES];//定义获取工控机中板卡列表 IntPtr[]mDeviceHandle = newIntPtr[16];//设备句柄 IntPtr[]mAxisHand = newIntPtr[64]; //轴句柄 uint[]mAxisPerDev = newuint[64];//每个设备的轴数,放到对应的数组中 uint uDeviceCount = 0; //板卡设备的个数 uint mAxisNum = 0;//总的轴数初始化函数
privateuint AdvInitMotionCard()//板卡初始化程序 { Int32 iResult= 0;//定义接收函数调用返回码uint uDeviceNum = 0;//设备的DeviceNum
uint uResult;//定义接收函数调用返回码
uint uRetry = 0;//开卡失败重新开卡次数
bool bRescan = false;//是否进行重新开卡
string mConfigDir =System.IO.Directory.GetCurrentDirectory();//获得工程bin//Debug路径
string mConfigFile = ""; //板卡配置文件名
uDeviceCount = 0;//设备个数
mAxisNum = 0;//先轴总数变量清零
iResult = Motion.mAcm_GetAvailableDevs(mCurAvailableDevs,Motion.MAX_DEVICES, ref uDeviceCount);//获取有用设备列表及个数
if(iResult != (int)ErrorCode.SUCCESS)
{
return (uint)iResult;
}
if(uDeviceCount> 0)//当有设备时才进行开卡
{
for (int i = 0; i //循环打开各个板卡
{
uDeviceNum =mCurAvailableDevs[i].DeviceNum;//从列表中获取板卡对应的设备号
do//为了程序适用EtherCAT板卡,可以在开卡阶段增加报错重新开卡处理,防止由于对DC时间导致开卡不成功
{
uResult = Motion.mAcm_DevOpen(uDeviceNum,ref mDeviceHandle[i]);//打开板卡
if (uResult != (uint)ErrorCode.SUCCESS)
{
uRetry++;
bRescan = true;
if (uRetry > 10)
{
return uResult;
}
else
{
System.Threading.Thread.Sleep(1000);//主要是EtherCAT有可能开卡失败,需要进行延时等待从站就绪
}
}
else
{
bRescan = false;
}
} while (bRescan);
uResult = Motion.mAcm_GetU32Property(mDeviceHandle[i],(uint)PropertyID.FT_DevAxesCount, ref mAxisPerDev[i]);//获取设备的轴数
if (uResult != (uint)ErrorCode.SUCCESS)
{
return uResult;
}
for (int j = (int)mAxisNum; j < mAxisNum + mAxisPerDev[i]; j++)
{
uResult = Motion.mAcm_AxOpen(mDeviceHandle[i], (UInt16)(j - mAxisNum), ref mAxisHand[j]);//打开每个板卡的每个轴
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
mConfigFile = mConfigDir + "\\Card_" +i.ToString() + ".cfg";//要求每张板卡的配置文件名字按顺序保存“Card_*.cfg”格式,*表示每个卡的顺序值,如Card_0.cfg
uResult = Motion.mAcm_DevLoadConfig(mDeviceHandle[i],mConfigFile);//每个设备加载配置参数
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
mAxisNum = mAxisNum +mAxisPerDev[i];//获取总的轴数
}
UInt16 uAxState = 0;//用于存放轴状态的变量
for(int k = 0; k < mAxisNum; k++)
{
uResult = Motion.mAcm_AxGetState(mAxisHand[k],ref uAxState);//获取每个轴的状态
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
else
{
if(uAxState == (UInt16)AxisState.STA_AX_ERROR_STOP)//若轴报"ErrorStop",则进行错误清除
{
uResult = Motion.mAcm_AxResetError(mAxisHand[k]);//对轴报"ErrorStop"的状态,进行错误清除
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
}
}
}
else
{
MessageBox.Show("获取有用板卡数等于0,请检查!", "AdvMotionContriol", MessageBoxButtons.OK, MessageBoxIcon.Error);
return0xFFFFFFFF;
}
return (uint)ErrorCode.SUCCESS;//运行没错误,则返回0,表示初始化成功
}
反初始化函数
privateuintAdvUnInitMotionCard()//板卡反初始化程序
{
uint uResult;//定义接收函数调用返回码
UInt16 uAxState = 0;//用于存放轴状态的变量
for (int i = 0; i
{
uResult = Motion.mAcm_AxGetState(mAxisHand[i], ref uAxState);//获取每个轴的状态
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
else
{
if (uAxState == (UInt16)AxisState.STA_AX_ERROR_STOP)//若轴报"ErrorStop",则进行错误清除
{
uResult = Motion.mAcm_AxResetError(mAxisHand[i]);//对轴报"ErrorStop"的状态,进行错误清除
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
}
uResult = Motion.mAcm_AxStopDec(mAxisHand[i]);//轴做减速停止
if(uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
for (int j = 0; j
{
uResult = Motion.mAcm_AxClose(ref mAxisHand[j]);//关闭每个轴
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
for (int k = 0; k < uDeviceCount; k++)
{
uResult = Motion.mAcm_DevClose(ref mDeviceHandle[k]);//关闭每个板卡设备
if (uResult != (UInt32)Advantech.Motion.ErrorCode.SUCCESS)
{
return uResult;
}
}
return (uint)ErrorCode.SUCCESS;//运行没错误,则返回0,表示初始化成功
}