|
- using Advantech.Motion;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Security.Cryptography;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Timers;
- namespace AssistClient.Device
- {
- public class AxisDev : IDisposable
- {
- public enum AxisStateType
- {
- [Description("轴状态")]
- AxisState = 0,
- [Description("轴运动状态")]
- AxisMotionState = 1,
- [Description("轴IO状态")]
- AxisIOState = 2,
- }
-
- public Action<int, AxisStateType, uint> axisStateEvent;
- public enum AxisPosType
- {
- [Description("命令位置")]
- CmdPos = 0,
- [Description("反馈位置")]
- ActualPos = 1,
- }
- public Action<int, AxisPosType, double> axisPosEvent;
- /// <summary> 使用
- /// 轴状态(AxisState 0-14) 单一值,无需按位取
- /// STA_AxDisable -- 轴被禁用,用户可打开并激活
- /// STA_AxReady ---- 轴已准备就绪,等待新的命令 *
- /// STA_Stopping ---- 轴停止
- /// STA_AxErrorStop --- 出现错误,轴停止
- /// STA_AxHoming ---- 轴正在执行返回原点运动
- /// STA_AxPtpMotion ---- 轴正在执行PTP 运动
- /// STA_AxContiMotion ---- 轴正在执行连续运动
- /// STA_AxSyncMotion --- 轴在一个群组中,群组正在执行插补运动;或轴是一个从轴,正在执行Ecam/E-gear/Gantry 运动。
- /// STA_AX_EXT_JOG -- 轴由外部信号控制。当外部信号激活时,轴将执行JOG 模式运动。
- /// STA_AX_EXT_MPG --- 轴由外部信号控制。当外部信号激活时,轴将执行MPG 模式运动
- /// </summary>
- //public Action<int, int> axisStateEvent;
-
- /// <summary>
- /// 轴运动状态 使用
- /// 位 说明
- /// Stop ---- 停止
- /// WaitERC---- 等待ERC 完成
- /// InFA ---- 处于特定速度中 = FA
- /// InFL ---- 处于低速中 = FL
- /// InACC ---- 加速中
- /// InFH ---- 处于最大速度中 = FH
- /// InDEC ---- 减速中
- /// WaitINP---- 到位等待
- /// </summary>
- //public Action<int, int> axisMotionStateEvent;
- /// <summary>
- /// 轴IO状态 (Ax_Motion_IO) 使用
- /// RDY---- RDY 针脚输入
- /// ALM ---- 报警信号输入 *
- /// LMT+ ---- 限位开关+ *
- /// LMT- ---- 限位开关- *
- /// ORG---- 原始开关 *
- /// DIR ---- DIR 输出
- /// EMG ---- 紧急信号输入
- /// EZ ---- 编码器 Z 信号
- /// INP ---- 到位信号输入
- /// SVON ---- 伺服开启(OUT6) *
- /// ALRM ---- 报警复位输出状态
- /// SLMT+ ---- 软件限位+
- /// SLMT- ---- 软件限位-
- /// CMP----- 比较信号(OUT5)
- /// </summary>
- //public Action<int, bool, bool, bool, bool> axisIOStateEvent;
-
- public Action<WarningEnum, string> WarningEvent;
-
- /// <summary>
- /// 设备列表(多张PCI板卡)
- /// </summary>
- public List<DEV_LIST> DevList { get; private set; }
- /// <summary>
- /// 设备数量
- /// </summary>
- //private uint deviceCount = 0;
- /// <summary>
- /// 设备号,用于打开设备(非索引)
- /// </summary>
- public uint DeviceNum { get; private set; } = 0;
-
- /// <summary>
- /// 设备句柄
- /// </summary>
- private IntPtr m_DeviceHandle = IntPtr.Zero;
- /// <summary>
- /// 轴数量
- /// </summary>
- private uint m_ulAxisCount = 0;
- private IntPtr[] m_Axishand = new IntPtr[0];
- public double[] CmdPos { get; private set; } = new double[32];//轴命令位置
- public double[] ActualPos { get; private set; } = new double[32];//轴实际(反馈)位置
-
- public UInt16[] AxState { get; private set; } = new UInt16[32];//轴状态
- public UInt32[] IOStatus { get; private set; } = new UInt32[32];//轴IO状态
- public uint[] AxMotionState { get; private set; } = new uint[32];//轴运动状态
-
- private uint[] AxEnableEvtArray = new uint[32];
- private uint[] GpEnableEvt = new uint[32];
- /// <summary>
- /// 组
- /// </summary>
- //private IntPtr m_GpHand = IntPtr.Zero;
-
- /// <summary>
- /// 断电后设备必需复位
- /// </summary>
- public bool IsReset { private set; get; }=false;
- public bool IsDebug = false;
- /// <summary>
- /// 是否打开设备成功
- /// </summary>
- public bool IsInit { get; private set; } = false;
- Thread checkEventThread;
- private System.Timers.Timer timer = new System.Timers.Timer();
-
- /// <summary>
- /// 获取设备列表
- /// </summary>
- /// <returns></returns>
- /// <exception cref="Exception"></exception>
- //public static List<DEV_LIST> getDevList()
- //{
- // DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
- // uint deviceCount = 0;
- // int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
- // if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
- // throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);
-
- // return curAvailableDevs.ToList().Take((int)deviceCount).ToList();
- //}
- public AxisDev()
- {
- //初始化
- DEV_LIST[] curAvailableDevs = new DEV_LIST[Motion.MAX_DEVICES];
- uint deviceCount = 0;
- int Result = Motion.mAcm_GetAvailableDevs(curAvailableDevs, Motion.MAX_DEVICES, ref deviceCount);
- if (Result != (int)ErrorCode.SUCCESS || curAvailableDevs.Length < 1)
- throw new Exception("Get Device Numbers Failed With Error Code: [0x" + Convert.ToString(Result, 16) + "] DevCount=" + curAvailableDevs.Length);
- DevList = curAvailableDevs.ToList().Take((int)deviceCount).ToList();
- }
- public void Dispose()
- {
- stop();
- }
-
- /// <summary>
- /// 打开设备
- /// </summary>
- /// <exception cref="Exception"></exception>
- public bool start(int[] AxisPulseOutMode,bool debug=false)
- {
- if (DevList == null || DevList.Count < 1)
- {
- WarningEvent?.Invoke(WarningEnum.High, "Axis设备为空!");
- return false;
- }
-
- DeviceNum = DevList[0].DeviceNum;
- return start(DevList[0].DeviceNum, AxisPulseOutMode, debug);
- }
- int[] AxisPulseOutMode=new int[4];
- public bool start(uint DeviceNum,int[] AxisPulseOutMode, bool debug = false)
- {
- try
- {
- if (IsInit) return true;
- bALM = bEMG = bLMTP = bLMTN = false;
-
- //打开设备
- uint uResult = Motion.mAcm_DevOpen(DeviceNum, ref m_DeviceHandle);
- if (uResult != (int)ErrorCode.SUCCESS)
- throw new Exception("Open Device Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
-
- IsDebug = debug;
- IsReset = false;
- //读取轴数量
- uResult = Motion.mAcm_GetU32Property(m_DeviceHandle, (uint)PropertyID.FT_DevAxesCount, ref m_ulAxisCount);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("Get Axis Number Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
- m_Axishand = new IntPtr[m_ulAxisCount];
-
- //打开轴
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- //打开每个轴并获得每个轴句柄
- uResult = Motion.mAcm_AxOpen(m_DeviceHandle, (UInt16)i, ref m_Axishand[i]);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("Open Axis Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
-
- //先读取每个轴状态
- this.refreshAxisState(i);
-
- //判断与打开电源使能,1: On
- if ((IOStatus[i] & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) == 0)
- {
- uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 1);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
- }
- }
- //根据加载的文件设置设备的所有配置(需在打开每个轴 mAcm_AxSetSvOn 后设置)
- string cfgPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\Axis_" + DeviceNum + ".cfg";
- if (File.Exists(cfgPath))
- {
- uResult = Motion.mAcm_DevLoadConfig(m_DeviceHandle, cfgPath);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("Load Config Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
- }
-
- Thread.Sleep(500);
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- //先读取每个轴状态(进行报警)
- this.refreshAxisState(i);
- //每个轴的初始属性(reset 命令位置和实际(反馈)位置)
- //double cmdPosition = new double();
- //cmdPosition = 0;
- //为指定的轴设置命令位置
- //Motion.mAcm_AxSetCmdPosition(m_Axishand[i], cmdPosition);
- //为指定的轴设置实际(反馈)位置
- //Motion.mAcm_AxSetActualPosition(m_Axishand[i], cmdPosition);
-
- //set Axis PulseOutMode
- if (!setPulseOutMode(i, (AxisPulseOutMode)AxisPulseOutMode[i]))
- throw new Exception($"Axis{i} 设置脉冲模式失败!");
-
- this.AxisPulseOutMode = AxisPulseOutMode;
- //Event
- AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_MOTION_DONE; //运动完成(减速直至停止)
- //AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_START; //轴加速到运行速度时
- //AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_VH_END;//轴运行速度结束时,开始减速
- AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_HOME_DONE;
- AxEnableEvtArray[i] |= (uint)EventType.EVT_AX_ERROR;
-
- //初次获取轴的运动I/O状态。
- this.refreshAxisState(i);
- }
-
-
-
- uResult = Motion.mAcm_EnableMotionEvent(m_DeviceHandle, AxEnableEvtArray, GpEnableEvt, m_ulAxisCount, 3);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("EnableMotionEvent Filed With Error Code[0x" + Convert.ToString(uResult, 16) + "]");
-
- IsInit = true;
- timer.Elapsed += Timer_Elapsed;
- timer.Interval = 100;
- timer.Start();
-
- //用户应该创建一个新的线程来检查事件状态,例如:CheckEvtThread()函数
- checkEventThread = new Thread(new ThreadStart(checkEvtThread));
- checkEventThread.Start();
- return true;
- }
- catch (Exception ex)
- {
- WarningEvent?.Invoke(WarningEnum.High, ex.Message);
- stop();
- return false;
- }
- }
-
- /// <summary>
- /// 关闭设备
- /// </summary>
- /// <exception cref="Exception"></exception>
- public bool stop()
- {
- try
- {
- if (!IsInit) return false;
-
- uint i;
- for (i = 0; i < m_ulAxisCount; i++)
- {
- if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
- {
- WarningEvent?.Invoke(WarningEnum.Low, i + "轴处于ErrorStop状态,已重置!");
- //重置轴的状态。如果轴处于ErrorStop状态,则调用此函数后状态将更改为Ready
- Motion.mAcm_AxResetError(m_Axishand[i]);
- }
- // 命令轴减速停止(缓停)
- Motion.mAcm_AxStopDec(m_Axishand[i]);
-
- //sleep? 关闭电源使能,1: On
- uint uResult = Motion.mAcm_AxSetSvOn(m_Axishand[i], 0);
- if (uResult != (uint)ErrorCode.SUCCESS)
- throw new Exception("Servo On Failed With Error Code: [0x" + Convert.ToString(uResult, 16) + "]");
- }
- //删除组中的所有轴并关闭组句柄
- //Motion.mAcm_GpClose(ref m_GpHand);
- //m_GpHand = IntPtr.Zero;
-
- for (i = 0; i < m_ulAxisCount; i++)
- {
- //Close Axes
- Motion.mAcm_AxClose(ref m_Axishand[i]);
- }
-
- timer.Elapsed -= Timer_Elapsed;
- m_ulAxisCount = 0;
- //Close Device
- Motion.mAcm_DevClose(ref m_DeviceHandle);
- m_DeviceHandle = IntPtr.Zero;
- IsInit = false;
- timer.Stop();
- return true;
- }
- catch (Exception e)
- {
- return false;
- }
- }
- /// <summary>
- /// 轴事件
- /// </summary>
- private void checkEvtThread()
- {
- uint Result;
- UInt32[] AxEvtStatusArray = new UInt32[32];
- UInt32[] GpEvtStatusArray = new UInt32[32];
- UInt32 i;
- while (IsInit)
- {
- //如果你想获得轴或组的事件状态,你应该通过调用 Motion.mAcm_EnableMotionEvent 来启用这些事件
- //AxEvtStatusArray[n],返回每个轴的中断事件状态,n 表示运动设备的轴个数
- //GpEnableEvtArrayy[n]:返回每个群组的中断事件状态
- //AxArrayElements U32 IN AxEvtStatusArray 中元素个数
- //GpArrayElements U32 IN GpEvtStatusArray 中元素个数
- //Millisecond U32 IN 设定每次Check 事件时的等待时间
- Result = Motion.mAcm_CheckMotionEvent(m_DeviceHandle, AxEvtStatusArray, GpEvtStatusArray, m_ulAxisCount, 0, 1000);//3,10
- if (Result == (uint)ErrorCode.SUCCESS)
- {
- for (i = 0; i < m_ulAxisCount; i++)
- {
- if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_MOTION_DONE) > 0)
- {
- this.refreshAxisState((int)i);//更新AXIS状态
- }
- if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_START) > 0)
- {
- this.refreshAxisState((int)i);//更新AXIS状态
- }
- if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_VH_END) > 0)
- {
- this.refreshAxisState((int)i);//更新AXIS状态
- }
- if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_HOME_DONE) > 0)
- {
- this.refreshAxisState((int)i);//更新AXIS状态
- WarningEvent?.Invoke(WarningEnum.Normal, $"轴{i}回原点完成;当前命令位置:{CmdPos[i]},反馈位置:{ActualPos[i]}.");
- //回原点后反馈位置未归0则置0 //重置后会自动重新更新状态
- if (CmdPos[i] != 0) this.resetCmdPosition((int)i);
- if (ActualPos[i] != 0) this.resetActualPosition((int)i);
- }
- if ((AxEvtStatusArray[i] & (uint)EventType.EVT_AX_ERROR) > 0)
- {
- this.refreshAxisState((int)i);//更新AXIS状态
- }
-
- }
- //if (m_GpHand != IntPtr.Zero)
- //{
- // if (textBoxGpID.Text != "")
- // {
- // if ((GpEvtStatusArray[0] & ((uint)EventType.EVT_GP1_MOTION_DONE << Convert.ToByte(textBoxGpID.Text))) > 0)
- // {
- // m_GpDoneEvtCnt++;
- // }
- // if ((GpEvtStatusArray[1] & ((uint)EventType.EVT_GP1_VH_START << Convert.ToByte(textBoxGpID.Text))) > 0)
- // {
- // m_GpVHStartCnt++;
- // }
- // if ((GpEvtStatusArray[2] & ((uint)EventType.EVT_GP1_VH_END << Convert.ToByte(textBoxGpID.Text))) > 0)
- // {
- // m_GpVHEndCnt++;
- // }
- // }
- //}
- }
- }
- }
-
- public bool isReady(int axisIndex = -1)
- {
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxGetState(m_Axishand[i], ref AxState[i]);
- if (AxState[i] != (uint)AxisState.STA_AX_READY)
- {
- if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
- {
- var errCode = Motion.mAcm_GetLastError(m_Axishand[i]);
- if (errCode != 0)
- {
- StringBuilder sb = new StringBuilder(512);
- if (!Motion.mAcm_GetErrorMessage(errCode, sb, 511))
- sb = new StringBuilder("未知错误!");
- string errStr = $"轴{i}运行错误,错误码({errCode},错误信息:{sb.ToString().Trim()})";
- WarningEvent?.Invoke(WarningEnum.High, errStr);
- throw new Exception(errStr);
- }
- else
- {
- throw new Exception($"轴{i}运行错误,当前状态:{((AxisState)AxState[i]).ToString()}");
- }
- }
- return false;
- }
-
- }
- }
-
- return true;
- }
- public bool isError(int axisIndex = -1)
- {
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxGetState(m_Axishand[i], ref AxState[i]);
- if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
- return true;
-
- //
- if ((IOStatus[i] & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0
- || (IOStatus[i] & (uint)Ax_Motion_IO.AX_MOTION_IO_EMG) > 0
- || (IOStatus[i] & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0
- || (IOStatus[i] & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0)
- return true;
- }
- }
-
- return false;
- }
- /// <summary>
- /// 缓停,jog时也可用
- /// </summary>
- public void stopDec(int axisIndex = -1)
- {
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxStopDec(m_Axishand[i]);
- }
- }
- }
- /// <summary>
- /// 急停
- /// </summary>
- public void stopNow(int axisIndex = -1)
- {
- if (!IsInit) return;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxStopEmg(m_Axishand[i]);
- }
- }
- }
-
- public void resetAxisState(int axisIndex=-1)
- {
- if (!IsInit) return;
-
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- if (AxState[i] == (uint)AxisState.STA_AX_ERROR_STOP)
- {
- //重置轴的状态。如果轴处于ErrorStop状态,则调用此函数后状态将更改为Ready
- bALM = bEMG = bLMTP = bLMTN = false;
- Motion.mAcm_AxResetError(m_Axishand[i]);
- refreshAxisState(i);
- }
- // 命令轴减速停止(缓停)
- Motion.mAcm_AxStopDec(m_Axishand[i]);
- }
- }
-
- }
- /// <summary>
- /// 指定的轴设置命令位置
- /// </summary>
- public void resetCmdPosition(int axisIndex = -1, double position = 0)
- {
- if (!IsInit) return;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxSetCmdPosition(m_Axishand[i], position);
- this.refreshAxisState(i);
- }
- }
- }
- /// <summary>
- /// 指定的轴设置实际(反馈)位置
- /// </summary>
- public void resetActualPosition(int axisIndex=-1, double position = 0)
- {
- if (!IsInit) return;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- Motion.mAcm_AxSetActualPosition(m_Axishand[i], position);
- this.refreshAxisState(i);
- }
- }
- }
- /// <summary>
- /// 获取速度 [vellow,velhigh,acc,dec,Jerk]
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <returns></returns>
- public double[] getAxisVelParam(int axisIndex)
- {
- double[] value=new double[5];
- Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelLow, ref value[0]);
- Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxVelHigh, ref value[1]);
- Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxAcc, ref value[2]);
- Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxDec, ref value[3]);
- Motion.mAcm_GetF64Property(m_Axishand[axisIndex], (uint)PropertyID.PAR_AxJerk, ref value[4]);//0-T/S 型曲线
- return value;
- }
- /// <summary>
- /// 速度设置 注:运动的过程中可变速度,加速度和减速度需使用AxChangeVelEx方法
- /// </summary>
- /// <param name="velLow">起始速度</param>
- /// <param name="high">运行速度</param>
- /// <param name="acc">加速度</param>
- /// <param name="dec">减速度</param>
- /// <param name="axisIndex"></param>
- /// <param name="isJogOrHome">true 不行,回HOME也是false</param>
- public void setAxisVelParam(double velLow, double high = 0, double acc = 0, double dec = 0, int axisIndex = -1,bool isJogOrHome=false)
- {
- uint result;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (i == axisIndex || axisIndex == -1)
- {
- if (!isJogOrHome)
- {
- if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
- continue;
- if (velLow > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelLow, toPulse(velLow, Config.Axis_MM2PulseNum[i]));
- if (high > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxVelHigh, toPulse(high, Config.Axis_MM2PulseNum[i]));
- if (acc > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxAcc, toPulse(acc, Config.Axis_MM2PulseNum[i]));
- if (dec > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxDec, toPulse(dec, Config.Axis_MM2PulseNum[i]));
- result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.PAR_AxJerk, 0);//0-T/S 型曲线
- }
- else
- {
- if ((AxisState)AxState[i] != AxisState.STA_AX_EXT_JOG)
- continue;
- if (velLow > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.CFG_AxJogVelLow, toPulse(velLow, Config.Axis_MM2PulseNum[i]));
- if (high > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.CFG_AxJogVelHigh, toPulse(high, Config.Axis_MM2PulseNum[i]));
- if (acc > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.CFG_AxJogAcc, toPulse(acc, Config.Axis_MM2PulseNum[i]));
- if (dec > 0) result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.CFG_AxJogDec, toPulse(dec, Config.Axis_MM2PulseNum[i]));
- result = Motion.mAcm_SetF64Property(m_Axishand[i], (uint)PropertyID.CFG_AxJogJerk, 0);//0-T/S 型曲线
- }
- }
- }
- }
-
- /// <summary>
- /// 回HOME
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <param name="homeMode">16种回HOME模式(0-15)</param>
- /// <param name="dir">0-正向 1-负向</param>
- /// <exception cref="Exception"></exception>
- public void home(int axisIndex = -1, uint homeMode = 11, uint dir = 1)
- {
- if (!IsInit) return;
-
- //研华运动控制卡共提供两个函数执行回Home: Acm_AxHome 和Acm_AxMoveHome
- //调用Acm_AxHome 执行回Home 时,通过PAR_AxVelLow、PAR_AxVelHigh、PAR_AxAcc、 PAR_AxDec、PAR_AxJerk 设置初速度,运行速度、加速度、减速度、速度曲线类型。
- //调用Acm_AxMoveHome 执行回Home 时,通过PAR_AxHomeVelLow、PAR_AxHomeVelHigh、 PAR_AxHomeAcc、PAR_AxHomeDec、PAR_AxHomeJerk 设置初速度,运行速度、加速度、 减速度、速度曲线类型。
- uint result;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (isSkip(axisIndex)) continue;
- if (i == axisIndex || axisIndex == -1)
- {
- if ((AxisState)AxState[i] != AxisState.STA_AX_READY)
- continue;
-
- if (!setPulseOutMode(i, (AxisPulseOutMode)AxisPulseOutMode[i]))
- throw new Exception($"Axis{i} 设置脉冲模式失败!");
-
- //单独设置GO HOME 速度参数??
-
- //
- result = Motion.mAcm_AxHome(m_Axishand[i], homeMode, dir);
- if (result != (uint)ErrorCode.SUCCESS)
- throw new Exception("AxHome Failed With Error Code: [0x" + Convert.ToString(result, 16) + "]");
- }
- }
-
- //复位
- //if (axisIndex == -1 && !IsDebug && !IsReset)
- // IsReset = true;
- if (!IsDebug && !IsReset)
- IsReset = true;
- }
- /// <summary>
- /// 点到点运动
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <param name="pos">PPU位置,方向为正负值</param>
- /// <param name="moveMode"></param>
- public bool move_ptp(int axisIndex, double pos, AxMoveMode moveMode)
- {
- if (isSkip(axisIndex)) return true;
- if (!IsInit) return false;
- if (isError(axisIndex)) return false;
-
- pos = toPulse(pos, Config.Axis_MM2PulseNum[axisIndex]);
-
- uint result;
- if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
- return false;
-
- if (!setPulseOutMode(axisIndex, (AxisPulseOutMode)AxisPulseOutMode[axisIndex]))
- {
- WarningEvent?.Invoke(WarningEnum.High, $"Axis{axisIndex} 设置脉冲模式失败!");
- return false;
- }
-
- //--
- if (moveMode==AxMoveMode.MODE1_Abs) //Start single axis's absolute position motion.
- result = Motion.mAcm_AxMoveAbs(m_Axishand[axisIndex], pos);
- else //Start single axis's relative position motion
- result = Motion.mAcm_AxMoveRel(m_Axishand[axisIndex], pos);
- if (result != (uint)ErrorCode.SUCCESS)
- {
- WarningEvent?.Invoke(WarningEnum.High, "PTP Move Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
- return false;
- }
- return true;
- }
- /// <summary>
- /// 判断是否正在动动
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <returns></returns>
- public bool isMoveing(int axisIndex = -1)
- {
- if (!IsInit) return false;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (i == axisIndex || axisIndex == -1)
- {
- AxisState state = (AxisState)AxState[i];
- if (state == AxisState.STA_AX_PTP_MOT || state == AxisState.STA_AX_HOMING || state == AxisState.STA_AX_CONTI_MOT)
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 设置脉冲模式
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <param name="outMode"></param>
- /// <returns></returns>
- private bool setPulseOutMode(int axisIndex, AxisPulseOutMode outMode)
- {
- uint refOutMode = 0;
- //先获取再判断
- uint result = Motion.mAcm_GetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxPulseOutMode, ref refOutMode);// 获取输出模式
- if (result != (uint)ErrorCode.SUCCESS)
- {
- WarningEvent?.Invoke(WarningEnum.High, $"Get Axis{axisIndex} Failed With Error Code: [0x" + Convert.ToString(result, 16) + "]");
- return false;
- }
- if ((uint)outMode != refOutMode)
- {
- //设置脉冲模式
- result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxPulseOutMode, (uint)outMode);
- if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265
- {
- WarningEvent?.Invoke(WarningEnum.High, "Set Property-CFG_AxExtPulseNum Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
- return false;
- }
- }
-
- return true;
- }
- #region JOG
- public void openJogMode(int axisIndex)
- {
- if (!IsInit) return;
- if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_READY)
- return;
-
- if (!setPulseOutMode(axisIndex, (AxisPulseOutMode)AxisPulseOutMode[axisIndex]))
- throw new Exception($"Axis{axisIndex} 设置脉冲模式失败!");
-
- uint result;
- //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode 2: MPG Mode
- result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 0);
- result = Motion.mAcm_AxSetExtDrive(m_Axishand[axisIndex], 1);
- if (result != (uint)ErrorCode.SUCCESS)
- throw new Exception("Start external driver Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
-
- //设置外部驱动器的输入引脚
- //0 轴 0(默认值) 仅支持 0
- //1 轴 1(不支持)
- //2 轴 2(不支持)
- //3 轴 3(不支持)
- result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtMasterSrc, 0);
- if (result != (uint)ErrorCode.SUCCESS)
- throw new Exception("Set Property-AxExtMasterSrc Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
-
- //当启用外部驱动时。此属性允许通过数字输入通道选择驱动轴
- result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtSelEnable, 1);
- if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265
- throw new Exception("Set Property-AxExtSelEnable Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
-
- //理论脉冲数
- result = Motion.mAcm_SetU32Property(m_Axishand[axisIndex], (uint)PropertyID.CFG_AxExtPulseNum, 1000);
- if (result != (uint)ErrorCode.SUCCESS && result != (uint)ErrorCode.PropertyIDNotSupport)//Added for Supporting PCI1245 and PCI1265
- throw new Exception("Set Property-CFG_AxExtPulseNum Failed With Error Code[0x" + Convert.ToString(result, 16) + "]");
-
- //外部设置
- //setAxisVelParam(velLow, high, acc, dec, axisIndex, true);
- this.refreshAxisState(axisIndex);
- }
- public void closeJogMode(int axisIndex = -1)
- {
- if (!IsInit) return;
-
- uint result;
- for (int i = 0; i < m_ulAxisCount; i++)
- {
- if (i == axisIndex || axisIndex == -1)
- {
- if ((AxisState)AxState[i] == AxisState.STA_AX_EXT_JOG)
- {
- //启用/禁用外置硬盘模式.0: Disabled (stop command) 1: JOG Mode 2: MPG Mode
- result = Motion.mAcm_AxSetExtDrive(m_Axishand[i], 0);
- //命令轴减速停止
- result = Motion.mAcm_AxStopDec(m_Axishand[i]);
- this.refreshAxisState(i);
- }
- }
- }
- }
- /// <summary>
- /// jog运行 0:正向,1:负向
- /// </summary>
- /// <param name="axisIndex"></param>
- /// <param name="dic">0:正向,1:负向</param>
- public void jog(int axisIndex, ushort dic)
- {
- if (isSkip(axisIndex)) return;
- if (isError(axisIndex)) return;
- if ((AxisState)AxState[axisIndex] != AxisState.STA_AX_EXT_JOG) return;
- //Jog 运动的方向,0:正向,1:负向
- Motion.mAcm_AxJog(m_Axishand[axisIndex], dic);
- }
-
- #endregion
-
- #region Private
- private bool isSkip(int axisIndex)
- {
- if (axisIndex == 0 && Config.SkipAxis0) return true;
- if (axisIndex == 1 && Config.SkipAxis1) return true;
- if (axisIndex == 2 && Config.SkipAxis2) return true;
- if (axisIndex == 3 && Config.SkipAxis3) return true;
- return false;
- }
- private void Timer_Elapsed(object sender, ElapsedEventArgs e)
- {
- if (!IsInit) return;
-
- for (int i = 0; i < m_ulAxisCount; i++)
- refreshAxisState(i);
- }
- private bool bALM, bEMG, bLMTP, bLMTN;
- private void refreshAxisState(int axisIndex)
- {
- //uint result;
- //获取指定轴的当前命令位置
- if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetCmdPosition(m_Axishand[axisIndex], ref CmdPos[axisIndex]))
- axisPosEvent?.Invoke(axisIndex, AxisPosType.CmdPos, tomm(CmdPos[axisIndex], Config.Axis_MM2PulseNum[axisIndex]));
- //获取指定轴的当前实际(反馈)位置
- if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetActualPosition(m_Axishand[axisIndex], ref ActualPos[axisIndex]))
- axisPosEvent?.Invoke(axisIndex, AxisPosType.ActualPos, tomm(ActualPos[axisIndex], Config.Axis_MM2PulseNum[axisIndex]) );
-
- //获取Axis的当前状态
- if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetState(m_Axishand[axisIndex], ref AxState[axisIndex]))
- axisStateEvent?.Invoke(axisIndex, AxisStateType.AxisState, AxState[axisIndex]);
- //log?.Invoke(WarningEnum.Normal, $"({AxisIndex}轴)AxisState = {((AxisState)AxState[AxisIndex]).ToString()}");
-
- //获取轴的运动I/O状态。
- if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionIO(m_Axishand[axisIndex], ref IOStatus[axisIndex]))
- {
- bool isStopNow = false;
- if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0) //ALM报警状态 需IO close (流程上必需在报警清除后先复位)
- {
- if (!isStopNow)
- {
- isStopNow = true;
- stopNow();//ALM报警需急停
- }
- if (!bALM)
- {
- bALM = true;
- WarningEvent?.Invoke(WarningEnum.High, $"Axis{axisIndex} ALM报警!!!");
- }
- }
- if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_EMG) > 0) //EMG急停状态 需重置 state (流程上必需在报警清除后先复位)
- {
- if (!isStopNow)
- {
- isStopNow = true;
- stopNow();//EMG状态需急停
- }
- if (!bEMG)
- {
- bEMG = true;
- WarningEvent?.Invoke(WarningEnum.High, $"Axis{axisIndex} 触发EMG急停!!!");
- }
- }
- //右极限 true->false (流程上必需在报警清除后先复位)
- if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0 && ((AxisState)AxState[axisIndex]) != AxisState.STA_AX_HOMING)
- {
- if (!isStopNow)
- {
- isStopNow = true;
- stopNow();//右极限状态需急停
- }
- if (!bLMTP)
- {
- bLMTP = true;
- WarningEvent?.Invoke(WarningEnum.High, $"Axis{axisIndex} 触发右极限LMTP!!!");
- }
- }
- //左极限 true->false (流程上必需在报警清除后先复位)
- if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0 && ((AxisState)AxState[axisIndex]) != AxisState.STA_AX_HOMING)
- {
- if (!isStopNow)
- {
- isStopNow = true;
- stopNow();//左极限状态需急停
- }
- if (!bLMTN)
- {
- bLMTN = true;
- WarningEvent?.Invoke(WarningEnum.High, $"Axis{axisIndex} 触发左极限LMTN!!!");
- }
- }
- ////ORG 回原点
- //if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0)
- //{
- // WarningEvent?.Invoke(WarningEnum.Normal, $"Axis{axisIndex} 触发ORG信号!");
- //}
- ////EZ 回原点
- //if ((IOStatus[axisIndex] & (uint)Ax_Motion_IO.AX_MOTION_IO_EZ) > 0)
- //{
- // WarningEvent?.Invoke(WarningEnum.Normal, $"Axis{axisIndex} 触发EZ信号!");
- //}
-
- axisStateEvent?.Invoke(axisIndex, AxisStateType.AxisIOState, IOStatus[axisIndex]);
- //log?.Invoke(WarningEnum.Normal, $"({AxisIndex}轴)AxisMotionIO = {((Ax_Motion_IO)IOStatus[AxisIndex]).ToString()}");
- //checkMotionIOStatus(AxisIndex, IOStatus[AxisIndex]);
- }
-
- //获取Axis的当前运动状态
- if ((uint)ErrorCode.SUCCESS == Motion.mAcm_AxGetMotionStatus(m_Axishand[axisIndex], ref AxMotionState[axisIndex]))
- axisStateEvent?.Invoke(axisIndex, AxisStateType.AxisMotionState, AxMotionState[axisIndex]);
- //log?.Invoke(WarningEnum.Normal, $"({AxisIndex}轴)AxisMotionStatus = {AxMotionState[AxisIndex].ToString()}");
- }
-
- //private void checkMotionIOStatus(int axisIndex, uint IOStatus)
- //{
- // if ((IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0)//报警信号输出
- // log?.Invoke(2, $"轴{axisIndex} 发出告警!!");
-
- // bool ALM = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0;
- // bool ORG = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0;//ORG
- // bool EL_R = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0;//右极限
- // bool EL_L = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0;//-EL 左
- // bool SVON = (IOStatus & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0;
- //}
-
- private string getErrInfo(uint errorCode)
- {
- StringBuilder ErrorMsg = new StringBuilder("", 100);
- //Get the error message according to error code returned from API
- Boolean res = Motion.mAcm_GetErrorMessage(errorCode, ErrorMsg, 100);
- if (res) return ErrorMsg.ToString();
- return "获取错误信息失败!";
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="pulseVal"></param>
- /// <param name="mmPulse"></param>
- /// <returns></returns>
- public double tomm(double pulseVal, double pulse)
- {
- return (pulseVal / pulse);
- }
- /// <summary>
- /// mm转脉冲
- /// </summary>
- /// <param name="mm"></param>
- /// <param name="mmPulse">1mm 对应 脉冲数</param>
- /// <returns></returns>
- private double toPulse(double mm, double mmPulse)
- {
- return (mm * mmPulse);
- }
- public double getCmdPos_mm(int axisIndex)
- {
- return tomm(CmdPos[axisIndex], Config.Axis_MM2PulseNum[axisIndex]);
- }
- public double getActualPos_mm(int axisIndex)
- {
- return tomm(ActualPos[axisIndex], Config.Axis_MM2PulseNum[axisIndex]);
- }
- #endregion
-
-
-
- }
- }
|