基类
namespace MotionCardDll
{
public abstract class IMotionCard
{
public Int32 m_Mode;
public Int32 m_BoardId;//Card 号
public Int32 m_Card_name;
public Int32 m_StartAxisID;
public Int32 m_TotalAxisNum;
//
// Axis[] m_Axis; //1张卡可能4轴,可能8轴
// Input[] m_Input; //1张卡16个输入
// Output[] m_Output; //1张卡16个输出
// Trig[] m_Trig; //1张卡最多4个触发
// BufferMove[] m_BufferMove; //1张卡最多2个点表运动
//
public IMotionCard()
{
m_Mode = 0;
m_BoardId = -1;
m_Card_name = -1;
m_StartAxisID = -1;
m_TotalAxisNum = -1;
}
public IMotionCard(Int32 Mode, Int32 BoardId, Int32 Card_Name, Int32 StartAxisID, Int32 TotalAxisNum)
{
m_Mode = Mode;
m_BoardId = BoardId;
m_Card_name = Card_Name;
m_StartAxisID = StartAxisID;
m_TotalAxisNum = TotalAxisNum;
}
/// <summary>
/// 初始化运动控制卡PCI_20408C,PCI_8258
/// </summary>
/// <param name="Mode">连接模式:0自动,1自动</param>
/// <param name="BoardId">板卡ID:0,1,2,3,4,。。。。。</param>
/// <param name="Card_Name">板卡名称:204,208,8254,8258</param>
/// <param name="StartAxisID">起始轴号</param>
/// <param name="TotalAxisNum">全部轴数量</param>
/// <param name="strPath">文件路径</param>
/// <returns></returns>
public abstract bool MotionCardInitial(string strPath);
/// <summary>
/// 初始化运动控制卡EMX100
/// </summary>
/// <returns></returns>
public abstract bool EMXInitial();
}
public abstract class IAxis
{
public Int32 m_AxisID = -1;
public string m_strName = "";
public double m_Scale = 10; //轴比例系数:??Pulse/mm
//需要保存的数据
public double m_AccTime = 0.01; //加速度时间
public double m_DecTime = 0.01; //减速度时间
public double m_AutoRunSpeed = 1.0; //自动运行速度 mm/s
public double m_ManualRunSpeed = 1.0; //手动运行速度 mm/s
public double m_JogSpeed = 1.0; //点动速度 mm/s
public double m_WaitPosMm = 0.0;
public double m_NegSoftLimit; //软负极限
public double m_PosSoftLimit; //软正极限
//。。。。
public double m_VS = 0.0; //启动速度mm/s
public double m_VE = 0.0; //停止速度mm/s
public double m_MaxSpeed = 2000; //最大速度 mm/s
public double m_MaxJogSpeed = 500; //Jog最大速度mm/s
public double m_NowPosMm = 0.0; //轴 当前位置
public double m_TarPosMm = 0.0; //轴 目标位置
public double m_AllowDeviation = 0.005; //允许偏差
public bool m_bInTarPos = false; //标志位:在目标位置
public bool m_bInWaitPos = false; //标志位:在等待位置
public int m_AlmNo = -1; //报警代码
public int m_EncoderMode = 0; //解码模式
public uint m_HomeMode;//回零方式
public uint m_HomeDir;//回零方向
//Motion Status
public bool CSP = false; //0指令停止 command stopped
public bool VM = false; //1处于最大速度 In maximum velocity
public bool ACC = false; //2加速中 In acceleration
public bool DEC = false; //3减速中 In deceleration
public bool DIR = false; //4方向 Move direction. 1:Positive direction, 0:Negative direction
public bool MDN = false; //5运动停止 Motion done, 0: In motion, 1: Motion done ( It could be abnormal stop)
public bool HMV = false; //6回零中 In homing
public bool PTB = false; //11点表运动中
public bool JOG = false; //15 点动中 in jogging
public bool ASTP = false; //16 停止信号 0:Stop normally, 1: abnormal stop, When axis in motion, this bit will be clear.
Motion IO Status
public bool ALM = false; //0报警
public bool PEL = false; //1硬件正限位异常 0:未碰到 1:碰到极限
public bool NEL = false; //2硬件软限位异常
public bool ORG = false; //3硬件原点
public bool EMG = false; //4急停信号
public bool EZ = false; //5 Z向信号
public bool INP = false; //6到位信号
public bool SVON = false; //7使能 0:Disable 1:Enable
public bool SPEL = false; //11软正限位
public bool SMEL = false; //12软负限位
//Axistatus swj
public bool StopStatus = false;
public bool InPosition = false;
//定义常量
public const int SOn = 1;
public const int SOff = 0;
public IAxis()
{
}
public IAxis(int nAxisID)
{
m_AxisID = nAxisID;
m_MaxSpeed = 2000;
m_MaxJogSpeed = 200;
m_VS = 0.0;
m_VE = 0.0;
}
/// <summary>
/// 设置参数到板卡
/// </summary>
/// <param name="AccTime"></param>
/// <param name="DecTime"></param>
/// <param name="RunSpeed"></param>
/// <param name="JogSpeed"></param>
/// <param name="JogDirection"></param>
public abstract bool SetParaToCard();
public abstract bool GetParaFromCard();
//移动到目标位置(自动运行中使用)
public abstract bool MoveToTarPos();
//绝对运动:基于自动速度
public abstract bool MoveAbsPosBaseAuto(double TargetPosMm);
//相对运动:基于自动速度
public abstract bool MoveRelPosBaseAuto(double Distance);
//绝对运动:基于手动速度
public abstract bool MoveAbsPosBaseManual(double TargetPosMm);
//相对运动:基于手动速度
public abstract bool MoveRelPosBaseManual(double Distance);
// 设置轴当前位置
public abstract bool SetPosition(double PosMm);
// 获取轴当前位置
public abstract double GetCurrentPos();
public abstract double GetTargetPos();
/// <summary>
/// 停止
/// </summary>
/// <returns></returns>
public abstract bool StopMove();
/// <summary>
/// 急停
/// </summary>
/// <returns></returns>
public abstract bool EMGStop();
/// <summary>
/// 伺服 使能
/// </summary>
/// <returns></returns>
public abstract bool ServoOn();
/// <summary>
/// 伺服 掉使能
/// </summary>
/// <returns></returns>
public abstract bool ServoOff();
/// <summary>
/// 回零
/// </summary>
/// <returns></returns>
public abstract bool HomeMove();
/// <summary>
/// 获取轴的IO状态
/// </summary>
/// <returns></returns>
public abstract bool GetIOStatus();
/// <summary>
/// 获取轴的当前运行状态
/// </summary>
/// <returns></returns>
public abstract bool GetStatus();
public abstract bool DisableSoftLimit();
public abstract bool EnableSoftLimit();
public abstract bool ResetError();//清除报警
public abstract bool ReadPara(string strpath);
public abstract bool WritePara(string strpath);
}
public abstract class IInput
{
public int m_nChanel = -1;
public IInput()
{
}
public abstract int ReadInput();
}
public abstract class IOutput
{
protected int m_BoardId = -1;
public int m_nChanel = -1;
//定义常量
public const int OutputOn = 1;
public const int OutputOff = 0;
public IOutput()
{
}
public abstract bool WriteOutputOn();
public abstract bool WriteOutputOff();
public abstract int ReadOutput();
}
public abstract class ITrig
{
public int m_nChanel = -1; //通道号
public ITrig()
{
}
//手动触发
public abstract void ManualTriger();
public abstract void EnableTrigger();
public abstract void DisableTrigger();
/// <summary>
/// 使能比较触发
/// </summary>
public abstract void EnableCmpTrigger();
/// <summary>
/// 失能:线性比较、表格比较
/// </summary>
/// <param name="CmpSource"></param>
public abstract void DisableCmpTrigger();
/// <summary>
///
/// </summary>
/// <param name="CMP_Source">比较源</param>
/// <param name="TCMP_DIR">表格比较方向</param>
/// <param name="TRG_SRC_inBit">触发源参数</param>
public abstract void SetCmpTriggerPara(Int32 CMP_Source, Int32 TCMP_DIR, Int32 TRG_SRC_inBit);
public abstract bool SetTrigerTable(Int32 TCmpCh, Int32[] PosArray, Int32 Size);
public abstract bool SetTrigerLine(Int32 LCmpCh, Int32 StartPoint, Int32 RepeatTimes, Int32 Interval);
/// <summary>
/// 获取触发次数
/// </summary>
/// <param name="trgCnt"></param>
/// <returns></returns>
public abstract int GetTrigerCnt(ref Int32 trgCnt);
/// <summary>
/// 复位触发计数
/// </summary>
/// <param name="boardID">卡号</param>
/// <param name="ch">触发输出通道</param>
/// <returns></returns>
public abstract int ResetTrigerCnt();
}
public abstract class IBufferMove
{
public Int32 m_BufID = -1;
public IBufferMove()
{
}
//点表运动参数设置
/// <summary>
/// 点表运动参数设置
/// </summary>
/// <param name="BoardID">轴号</param>
/// <param name="BufID">两组点表BufferID</param>
/// <param name="dimension">几维插补最多六轴</param>
/// <param name="PosArr">压入点表的点数</param>
/// <param name="Ve">结束速度</param>
/// <param name="Vm">最大速度</param>
/// <param name="Acc">加速度</param>
/// <param name="Dec">减速度</param>
/// <returns></returns>
public abstract bool MotionSetMoveBuf(Int32 dimension, ref Int32[] PosArr, Int32 Ve, Int32 Vm, Int32 Acc, Int32 Dec, bool IsOutput, Int32 doChannel, Int32 doOn);
// 点表使能
/// <summary>
/// 贴合点表参数设置
/// </summary>
/// <param name="dimension"></param>
/// <param name="axisArr"></param>
/// <param name="Vs"></param>
/// <param name="Sfactor"></param>
/// <returns></returns>
public abstract bool MotionEnbleBuffer(Int32 dimension, ref Int32[] AxisArr, Int32 Vs, double Sfactor);
//点表运动开始
/// <summary>
///点表运动开始
/// </summary>
/// <param name="BufID">两组点表buffid</param>
/// <returns></returns>
public abstract bool MotionBufMoveStart();
//获取点表状态
/// <summary>
/// 获取点表状态
/// </summary>
/// <param name="BoardID">卡号</param>
/// <param name="BufID">两组点表buffid</param>
/// <param name="status">点表运动状态</param>
/// <param name="usgSpace">点表buff已用的空间buffer</param>
/// <returns></returns>
public abstract bool MotionBufWorkDone(ref Int32 status, ref Int32 usgSpace);
//停止点表运动
/// <summary>
/// 停止点表运动
/// </summary>
/// <param name="BoardID">卡号</param>
/// <param name="BufID">两组点表运动Buffid</param>
/// <returns></returns>
public abstract bool MotionBufMoveStop();
//重置BufferMove
public abstract bool ResetBuf();
//已知圆心和角度进行点表参设设置
/// <summary>
/// 已知圆心和角度进行点表参设设置
/// </summary>
/// <param name="BoardID"></param>
/// <param name="BufID"></param>
/// <param name="Angle"></param>
/// <param name="CenterY"></param>
/// <param name="CenterX"></param>
/// <param name="PosArr"></param>
/// <param name="Ve"></param>
/// <param name="Vm"></param>
/// <param name="Acc"></param>
/// <param name="Dec"></param>
/// <param name="IsOutput"></param>
/// <param name="doChannel"></param>
/// <param name="doOn"></param>
/// <returns></returns>
public abstract bool Arc2MotionSetMoveBuf(ref Int32[] AxisArr, double IAngle, double CenterY, double CenterX, ref Int32[] PosArr, Int32 Ve, Int32 Vm, Int32 Acc, Int32 Dec, bool IsOutput, Int32 doChannel, Int32 doOn);
//已知圆心和终止点,圆弧插补
/// <summary>
/// 已知圆心和终止点,圆弧插补
/// </summary>
/// <param name="IAngle"></param>
/// <param name="CenterY"></param>
/// <param name="CenterX"></param>
/// <param name="EndX"></param>
/// <param name="EndY"></param>
/// <param name="Dir"></param>
/// <param name="PosArr"></param>
/// <param name="Ve"></param>
/// <param name="Vm"></param>
/// <param name="Acc"></param>
/// <param name="Dec"></param>
/// <param name="IsOutput"></param>
/// <param name="doChannel"></param>
/// <param name="doOn"></param>
/// <returns></returns>
/// ref Int32[] PosArr
public abstract bool A2CEMotionSetMoveBuf(ref Int32[] AxisArr, double CenterY, double CenterX, ref Int32[] PosArr, Int32 Dir, Int32 Ve, Int32 Vm, Int32 Acc, Int32 Dec, bool IsOutput, Int32 doChannel, Int32 doOn);
//点胶点表运动功能并进行相关参数设置
/// <summary>
/// 点胶点表运动功能并进行相关参数设置
/// </summary>
/// <param name="BoardID">卡号</param>
/// <param name="BufID">两组点表buffId</param>
/// <param name="dimension">几维插补</param>
/// <param name="axisArr">点的数组</param>
/// <param name="Vs">点表运动的起始速度</param>
/// <param name="Sfactor">S速度因子</param>
/// <param name="BlendDist">混合距离</param>
/// <returns></returns>
public abstract int DispenseMotionSetEnbleBuffer(Int32 dimension, ref Int32[] axisArr, Int32 Vs, double Sfactor, double BlendDist);
}
}
凌华卡实现
namespace MotionCardDll.ADLink
{
//AMP200 系列板卡
public enum CardName
{
PCI_8392 = 00,
PCI_825x = 01,
PCI_8154 = 02,
PCI_785X = 03,
PCI_8158 = 04,
PCI_7856 = 05,
ISA_DPAC1000 = 06,
ISA_DPAC3000 = 07,
PCI_8144 = 08,
PCI_8258 = 09, //8258
PCI_8102 = 10,
PCI_V8258 = 11,
PCI_V8254 = 12,
PCI_8158A = 13,
PCI_20408C = 14, //204.208
PCI_8353 = 15,
PCI_8392F = 16,
PCI_C154 = 17,
PCI_C154_PLUS = 18,
PCI_8353_RTX = 19,
PCIe_8338 = 20,
PCIe_8154 = 21,
PCIE_8158 = 22,
ENET_EMX100 = 23,
PCIe_8334 = 24,
PCIe_8332 = 25,
PCIe_8331 = 26,
PCIE_7856 = 27
}
public class Card : IMotionCard
{
//
//public Axis[] m_Axis; //1张卡可能4轴,可能8轴
//public Input[] m_Input; //1张卡16个输入
//public Output[] m_Output; //1张卡16个输出
//public Trig[] m_Trig; //1张卡最多4个触发
//public BufferMove[] m_BufferMove; //1张卡最多2个点表运动
//
public Card()
: base()
{
}
public Card(Int32 Mode, Int32 BoardId, Int32 Card_Name, Int32 StartAxisID, Int32 TotalAxisNum)
: base(Mode, BoardId, Card_Name, StartAxisID, TotalAxisNum)
{
}
/// <summary>
/// 初始化运动控制卡PCI_20408C,PCI_8258
/// </summary>
/// <param name="Mode">连接模式:0自动,1自动</param>
/// <param name="BoardId">板卡ID:0,1,2,3,4,。。。。。</param>
/// <param name="Card_Name">板卡名称:204,208,8254,8258</param>
/// <param name="StartAxisID">起始轴号</param>
/// <param name="TotalAxisNum">全部轴数量</param>
/// <param name="strPath">文件路径</param>
/// <returns></returns>
public override bool MotionCardInitial(string strPath)
{
Int32 l_boardID_InBits = 0;
Int32 l_card_name = 0;
Int32 l_StartAxisID = 0;
Int32 l_TotalAxisNum = 0;
try
{
//板卡初始化
Int32 ret = APS168.APS_initial(ref l_boardID_InBits, m_Mode);
if (ret != 0)
{
return false;
}
//判断m_BoardId
ret = (l_boardID_InBits >> m_BoardId) & 1;
if (ret == 0)
{
return false;
}
//判断 卡名称 PCI_20408C,PCI_8258
ret = APS168.APS_get_card_name(m_BoardId, ref l_card_name);
if (m_Card_name != l_card_name)
{
return false;
}
//判断 起始轴号
ret = APS168.APS_get_first_axisId(m_BoardId, ref l_StartAxisID, ref l_TotalAxisNum);
if (m_StartAxisID != l_StartAxisID || m_TotalAxisNum != l_TotalAxisNum)
{
return false;
}
//读取配置文件
ret = APS168.APS_load_param_from_file(strPath);
if (ret != 0)
{
return false;
}
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 关闭卡
/// </summary>
/// <returns></returns>
public static bool MotionClose()
{
int ret = -1;
try
{
ret = APS168.APS_close();
}
catch
{
}
return ret == 0;
}
/// <summary>
/// 初始化运动控制卡EMX100
/// </summary>
/// <returns></returns>
public override bool EMXInitial()
{
Int32 emx_online = 0;
Int32 option = 0;
try
{
Int32 ret = APS168.APS_register_emx(emx_online, option);
}
catch (Exception e)
{
}
return true;
}
}
public class Axis : IAxis
{
private static Card m_MotionCard = new Card();
public Axis()
: base()
{
}
public Axis(int nAxisID)
: base(nAxisID)
{
}
public Axis(Card MotionCard, int nAxisID, string strName, double dScale, double dAllowDeviation,double dMaxSpeed)
{
m_MotionCard = MotionCard;
m_AxisID = nAxisID;
m_strName = strName;
m_Scale = dScale;
m_AllowDeviation = dAllowDeviation;
m_MaxSpeed = dMaxSpeed;
m_MaxJogSpeed = 200;
m_VS = 0.0;
m_VE = 0.0;
}
/// <summary>
/// 设置参数到板卡
/// </summary>
/// <param name="AccTime"></param>
/// <param name="DecTime"></param>
/// <param name="RunSpeed"></param>
/// <param name="JogSpeed"></param>
/// <param name="JogDirection"></param>
public override bool SetParaToCard()
{
try
{
double Acc = 0, Dec = 0, Vs = 0, MaxSpeed = 0, VE = 0, MaxJog = 0;
Acc = 1000 * m_Scale / m_AccTime; //1000代表1000mm/s
Dec = 1000 * m_Scale / m_AccTime;
Vs = 0.0;
MaxSpeed = m_MaxSpeed * m_Scale;
VE = 0.0;
MaxJog = 0;
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_ACC, Acc);
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_DEC, Dec);
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VS, Vs);
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VM, MaxSpeed);
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VE, VE);
APS168.APS_set_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_JG_VM, MaxJog);
return true;
}
catch
{
return false;
}
}
public override bool GetParaFromCard()
{
try
{
double Acc = 0, Dec = 0, Vs = 0, MaxSpeed = 0, VE = 0, MaxJog = 0;
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_ACC, ref Acc);
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_DEC, ref Dec);
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VS, ref Vs);
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VM, ref MaxSpeed);
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_VE, ref VE);
APS168.APS_get_axis_param_f(m_AxisID, (Int32)APS_Define.PRA_JG_VM, ref MaxJog);
m_AccTime = Acc / (1000 * m_Scale);
m_DecTime = Dec / (1000 * m_Scale);
m_VS = Vs;
m_MaxSpeed = MaxSpeed / m_Scale;
m_VE = VE;
m_MaxJogSpeed = MaxJog / m_Scale;
return true;
}
catch
{
return false;
}
}
//移动到目标位置(自动运行中使用)
public override bool MoveToTarPos()
{
try
{
APS168.APS_absolute_move(m_AxisID, (Int32)(m_TarPosMm * m_Scale), (Int32)(m_AutoRunSpeed * m_Scale));
return true;
}
catch
{
return false;
}
}
public override bool ResetError()
{
return true;
}
//绝对运动:基于自动速度
public override bool MoveAbsPosBaseAuto(double TargetPosMm)
{
try
{
m_TarPosMm = TargetPosMm;
//调试测量凌华运动命令所用时间
int a, b, c;
a = DateTime.Now.Millisecond;
APS168.APS_absolute_move(m_AxisID, (Int32)(TargetPosMm * m_Scale), (Int32)(m_AutoRunSpeed * m_Scale));
//调试测量凌华运动命令所用时间
b = DateTime.Now.Millisecond;
c = b - a;
int d = 4;
return true;
}
catch
{
return false;
}
}
//相对运动:基于自动速度
public override bool MoveRelPosBaseAuto(double Distance)
{
try
{
APS168.APS_relative_move(m_AxisID, (Int32)(Distance * m_Scale), (Int32)(m_AutoRunSpeed * m_Scale));
return true;
}
catch
{
return false;
}
}
//绝对运动:基于手动速度
public override bool MoveAbsPosBaseManual(double TargetPosMm)
{
try
{
m_TarPosMm = TargetPosMm;
APS168.APS_absolute_move(m_AxisID, (Int32)(TargetPosMm * m_Scale), (Int32)(m_ManualRunSpeed * m_Scale));
return true;
}
catch
{
return false;
}
}
//相对运动:基于手动速度
public override bool MoveRelPosBaseManual(double Distance)
{
try
{
APS168.APS_relative_move(m_AxisID, (Int32)(Distance * m_Scale), (Int32)(m_ManualRunSpeed * m_Scale));
return true;
}
catch
{
return false;
}
}
// 设置轴当前位置
public override bool SetPosition(double PosMm)
{
int ret = -1;
double PosPulse = 0;
try
{
PosPulse = PosMm * m_Scale;
ret = APS168.APS_set_position(m_AxisID, (Int32)PosPulse); //设置轴当前位置
}
catch
{
}
return ret == 0;
}
// 获取轴当前位置
public override double GetCurrentPos()
{
int ret = -1;
int PosPulse = 0;
try
{
ret = APS168.APS_get_position(m_AxisID, ref PosPulse); //获取轴当前位置
m_NowPosMm = PosPulse / m_Scale;
if (Math.Abs(m_NowPosMm - m_TarPosMm) <= m_AllowDeviation)
{
m_bInTarPos = true;
}
else
{
m_bInTarPos = false;
}
if (Math.Abs(m_NowPosMm - m_WaitPosMm) <= m_AllowDeviation)
{
m_bInWaitPos =