一、運動控制概述
運動控制技術是自動化技術和電氣拖動技術的融合,以工控機、PLC、DSP等為控制器的運動控制技術融合了微電子技術、計算機技術、檢測技術、自動化技術以及伺服控制技術等學科的新成果,在工業生產中起著極為重要的作用。
早期的運動控制技術主要是伴隨著數控技術、機器人技術和工廠自動化技術的發展而發展的。現已廣泛應用于國民經濟的各個行業,且應用形式多種多樣,主要應用領域如下:
1)冶金行業:電弧爐電機控制、軋機軋輥控制、產品定尺控制等。
2)機械行業:機床定位控制、加工軌跡控制、自動化流水線及機械手的控制等。
3)信息行業:磁盤驅動器磁頭的定位控制、打印機的控制等。
4)建筑行業:電梯及電梯群的控制等。
5)其他行業:立體倉庫和立體車庫的控制等。
二、運動控制系統的組成
- 控制器(PLC、運動控制卡、嵌入式系統)
- 驅動器(步進、伺服驅動器)
- 電機(步進電機、伺服電機、直線電機)
- 反饋裝置(編碼器、光柵尺)
例如:在一個簡單移動平臺中,有一個Y軸可以進行送料的工作。主要由正運動的控制卡、匯川的驅動器、匯川的電機構成,當然我們一般會有一個主機,通用做法是一個電腦上編寫有程序來控制板卡。
? ? ? ? 電腦上的軟件下發去某個位置的指令,其中包含速度、位置等;
????????由正運動的控制卡負責將指令轉換成驅動器命令,下發給伺服驅動器;
? ? ? ? 伺服驅動器再將命令轉換成電機需要的電壓和電流,讓電機運轉,電機末端一般安裝有編碼器,伺服驅動器會一直采集編碼器的脈沖信號來修改電壓和電流直到到達目標位置。
三、運動控制算法
- PID控制原理及優化
- 前饋控制與擾動補償
- 軌跡規劃(S曲線、T型速度規劃)
- 多軸同步控制
PID控制(比例-積分-微分控制)??
- ?
?原理?:通過比例項(P)快速響應誤差、積分項(I)消除穩態誤差、微分項(D)抑制振蕩,實現動態平衡。
- ?
?特點?:結構簡單、調試方便、穩定性高,但對非線性系統適應性弱。
- ?
?應用?:工業電機調速、恒溫控制、無人機姿態調整等線性系統
四、運動控制通信協議
- 脈沖方向控制
- 總線協議(EtherCAT、CANopen、Modbus)
以下是運動控制通信協議的全面解析,涵蓋脈沖方向控制和總線協議(EtherCAT、CANopen、Modbus)?? 的核心原理、技術特點及應用場景:
(一)、脈沖方向控制(Pulse-Direction Control)??
脈沖方向控制是伺服/步進電機最基礎的位置控制方式,通過脈沖頻率控制速度、脈沖數量控制位移、方向信號電平控制轉向。
技術原理?
?脈沖信號(PULSE)??:
每個脈沖對應電機固定角位移(步距角)。例如1.8°步進電機需200個脈沖完成一圈旋轉。
?公式?:位移量 = 脈沖數 × 步距角 / 360°
?方向信號(DIR)??:
高電平(+24V)正轉,低電平(0V)反轉,需在脈沖輸出前設定方向。
?差分信號抗干擾?:
采用
PULSE+/PULSE-
和DIR+/DIR-
差分對,提升長距離傳輸穩定性。
?工作模式與配置?
?模式?
?信號邏輯?
?適用場景?
?脈沖+方向?
單路脈沖 + 方向電平(正轉DIR=High,反轉DIR=Low)
低成本小型設備(≤200kHz)
?CW/CCW?
雙路獨立脈沖(CW脈沖=正轉,CCW脈沖=反轉)
高速(>200kHz)或長距離傳輸
?A/B正交脈沖?
兩路相位差90°的脈沖(A超前B=正轉,A滯后B=反轉)
高精度編碼器反饋系統
驅動器需通過參數(如
H05.15
)匹配控制器輸出模式,否則導致方向錯誤或定位偏差。?關鍵參數設置?
?電子齒輪比?:
調節輸入脈沖與實際位移的比例。
?公式?:實際位移 = 輸入脈沖數 ×(電子齒輪分子 / 電子齒輪分母)。
例:設置分子/分母=4/1,則1個脈沖驅動電機轉動4個步距角。
?方向信號延時?:
方向信號需提前脈沖0.5μs以上,避免電機啟動瞬間反向抖動。
(二)、總線協議(EtherCAT、CANopen、Modbus)??
總線協議適用于多軸協同、高實時性場景,替代傳統脈沖控制,解決布線復雜和同步精度問題。
?1. EtherCAT(以太網控制自動化技術)??
?核心機制?:
??"飛讀飛寫"幀處理?:主站幀依次穿越各從站,每個從站實時讀寫數據,單幀完成多設備通信。
?分布式時鐘?:主站同步所有從站時鐘,同步誤差≤±1ns,保障多軸插補精度。
?性能優勢?:
通信周期≤100μs,支持4軸同步控制(如研華控制卡)。
帶寬利用率>90%,遠高于傳統以太網。?
2. CANopen(基于CAN總線的應用層協議)?
?核心機制?:
?對象字典?:標準化參數存儲結構(如0x607C“目標位置”、0x6040“控制字”)。
?NMT網絡管理?:主站控制從站狀態(啟動/停止/復位)。
?性能優勢?:
支持1Mbps速率,最多127個節點,適合分布式控制(如10軸插片機系統)。
抗干擾性強,適用于電磁環境復雜場景。
?3. Modbus(主從式串行通信協議)??
?核心機制?:
?主站輪詢?:主站按地址順序查詢從站數據,響應延遲隨節點數增加。
?寄存器讀寫?:通過功能碼(如03讀保持寄存器、06寫單寄存器)訪問參數。
?性能局限?:
無實時保障,通信周期≥100ms,僅適用非同步控制(如啟停命令、溫度讀取)。
僅支持簡單數據類型(16位整數)。
(三)、協議選型對比?
?維度? | ?脈沖方向控制? | ?EtherCAT? | ?CANopen? | ?Modbus? |
---|---|---|---|---|
?實時性? | 中(依賴脈沖頻率) | ?超高?(≤100μs) | 高(1Mbps速率) | 低(≥100ms) |
?同步精度? | 無多軸同步能力 | ?±1ns? | ±10μs | 不支持 |
?最大軸數? | ≤4軸(受限于PLC脈沖口) | ?≥64軸? | 127節點 | 32節點(RTU模式) |
?布線復雜度? | 高(每軸需2~4芯線) | ?低?(菊花鏈拓撲) | 中(總線型拓撲) | 中(星型/總線拓撲) |
?抗干擾能力? | 弱(需差分信號增強) | ?強?(以太網屏蔽) | 強(CAN差分信號) | 弱(RS485需終端電阻) |
?典型成本? | 低(無需專用網卡) | 高(需專用主站) | 中 | 低 |
五、上位機控制
1、板卡連接
2、初始化參數
3、軸參數設置
4、相對移動
5、絕對移動
6、回原
7、Jog移動
板卡類
/// <summary>/// 板卡抽象基類/// </summary>public abstract class CardBase{/// <summary>/// 卡參數/// </summary>public CardParam cardParam { get; set; }public short CardNo => (short)cardParam.CardNo;/// <summary>/// 坐標系建立成功標志/// </summary>protected bool buildOK = false;/// <summary>/// 卡初始化成功標志/// </summary>private bool online;/// <summary>/// 在線狀態/// </summary>public bool OnLine{get { return online; }set { online = value; }}/// <summary>/// 寫錯誤信息方法/// </summary>public WriteInfo WriteInfo = null;/// <summary>/// 卡基類 有參構造方法/// </summary>/// <param name="cardParam">卡參數</param>public CardBase(CardParam cardParam){this.cardParam = cardParam;WriteInfo = new WriteInfo((str) =>{Console.WriteLine(str);});}/// <summary>/// 設置錯誤信息輸出函數/// </summary>/// <param name="writeInfo">回調函數</param>public void SetWriteInfoCB(WriteInfo writeInfo){this.WriteInfo = writeInfo;for (int i = 0; i < AxisBaseList.Count; i++){AxisBaseList[i].SetWriteInfoCB(writeInfo);}}#region 板卡初始化/// <summary>///板卡初始化/// </summary>/// <returns></returns>public abstract OperationResult Init();/// <summary>///關閉板卡/// </summary>/// <returns></returns>public abstract OperationResult DeInit();/// <summary>/// 讀取板卡固件版本號/// </summary>/// <returns></returns>public abstract string GetCardVersioin();#endregion 板卡初始化#region IO 操作/// <summary>/// 讀取一組連續的輸入/// </summary>/// <param name="startport"></param>/// <param name="endport"></param>/// <param name="data"></param>/// <returns></returns>public abstract bool ReadIoIn(int startport, int endport, ref int data);/// <summary>/// 讀取一個輸入點/// </summary>/// <param name="index"></param>/// <returns></returns>public abstract bool ReadIoInBit(int index);/// <summary>/// 讀取一組連續的輸出/// </summary>/// <param name="startport"></param>/// <param name="endport"></param>/// <param name="data"></param>/// <returns></returns>public abstract bool ReadIoOut(int startport, int endport, ref int data);/// <summary>/// 讀取一個輸出點/// </summary>/// <param name="index"></param>/// <returns></returns>public abstract bool ReadIoOutBit(int index);/// <summary>/// 寫一個IO輸出點/// </summary>/// <param name="index"></param>/// <param name="bit"></param>/// <returns></returns>public abstract bool WriteIoBit(int index, bool bit);/// <summary>/// 寫一組IO輸出數據/// </summary>/// <param name="data"></param>/// <returns></returns>public abstract bool WriteIo(int startport, int endport, int data);///// <summary>///// 讀取數字IO輸入狀態///// </summary>///// <param name="type">0:正限位 | 1:負限位 | 2:驅動報警| 3:原點開關| 4:通用輸入|</param>///// <returns></returns>//public abstract int GetDi(InputIOType type);///// <summary>///// 讀取數字IO輸入狀態///// </summary>///// <param name="type">0:正限位 | 1:負限位 | 2:驅動報警| 3:原點開關| 4:通用輸入|</param>///// <returns></returns>//public abstract bool[] GetInput(InputIOType type);///// <summary>///// 讀取數字IO輸出狀態///// </summary>///// <param name="type">10:驅動器使能 | 11:報警清除 | 12:通用輸出|</param>///// <returns></returns>//public abstract int GetDo(OutputIOType type);///// <summary>///// 讀取輸出狀態 讀取多位///// </summary>///// <param name="type">10:驅動器使能 | 11:報警清除 | 12:通用輸出|</param>///// <returns></returns>//public abstract bool[] GetOutput(OutputIOType type);///// <summary>///// 讀取輸入狀態 讀1位///// </summary>///// <param name="index">索引1-16</param>///// <returns></returns>//public abstract bool GetInputBit(int index);///// <summary>///// 讀取輸出狀態 讀1位///// </summary>///// <param name="index">索引1-16</param>///// <returns></returns>//public abstract bool GetOutputBit(int index);///// <summary>///// 設置輸出狀態 寫1位///// </summary>///// <param name="index">索引</param>///// <param name="state">狀態</param>///// <returns></returns>//public abstract bool SetOutputBit(int index, bool state);///// <summary>///// 設置輸出狀態 寫32位///// </summary>///// <param name="value">值</param>///// <returns></returns>//public abstract bool SetOutput(int value);#endregion IO 操作#region 插補運動/// <summary>/// 以當前位置為起始點進行多軸直線插補最多4軸/// </summary>/// <param name="axisNo">軸號數組最多4軸</param>/// <param name="pos">位置數組</param>/// <param name="vel">速度</param>/// <param name="acc">加速度</param>/// <returns>操作結果</returns>public abstract OperationResult MoveLineXYZAAbs(short[] axisNo, double[] pos, double vel, double acc = 0.2);/// <summary>/// XYC 2D 整圓插補 以起點(終點)位置和圓心位置為輸入參數 畫整圓/// </summary>/// <param name="axisNo">軸號數組</param>/// <param name="pos">圓弧的起點(終點)X 圓弧的圓心X </param>/// <param name="center">圓弧的起點(終點)Y 圓弧的圓心Y</param>/// <param name="vel">速度</param>/// <param name="acc">加速度</param>/// <returns>操作結果</returns>public abstract OperationResult MoveCircular(short[] axisNo, double[] pos, double[] center, double vel, double acc = 0.2);/// <summary>/// XYR 2D圓弧插補 起始點 過度點位置 終點位置為輸入參數 畫半圓/// </summary>/// <param name="axisNo">軸號數組</param>/// <param name="pos">起始 XY坐標</param>/// <param name="pos1">過度點 XY坐標</param>/// <param name="pos2">終點 XY坐標</param>/// <param name="vel">速度</param>/// <param name="acc">加速度</param>/// <returns>操作結果</returns>public abstract OperationResult MoveArc(short[] axisNo, double[] pos, double[] pos1, double[] pos2, double vel, double acc = 0.2);/// <summary>/// 空間圓弧插補/// </summary>/// <param name="axisNo">軸號</param>/// <param name="posX">開始位置</param>/// <param name="posY">經過位置</param>/// <param name="posZ">終點位置</param>/// <param name="vel">速度</param>/// <param name="acc">加速度</param>/// <returns></returns>public abstract OperationResult MoveArcOfSpace(short[] axisNo, double[] posStart, double[] posTransition, double[] posEnd, double vel, double acc = 0.2);/// <summary>///等待插補運動完成/// </summary>/// <returns></returns>public abstract OperationResult WaitInterpolatorXYStop();#endregion 插補運動#region 軸對象操作/// <summary>/// 軸集合/// </summary>public List<AxisBase> AxisBaseList = new List<AxisBase>();/// <summary>/// 獲取板卡所有參數json(卡參數+所有軸參數)/// </summary>public abstract string GetCardAxisParamJson();/// <summary>/// 添加軸對象/// </summary>/// <param name="axisBase"></param>/// <returns></returns>public abstract bool AddAxisObj(AxisParam axisParam);/// <summary>/// 刪除軸對象/// </summary>/// <param name="axisBase"></param>/// <returns></returns>public abstract bool DelAxisObj(AxisParam axisParam);/// <summary>/// 修改軸參數/// </summary>/// <param name="axisParam"></param>/// <returns></returns>public abstract bool ModifyAxisPara(AxisParam axisParam);#endregion 軸對象操作#region 2. 軸控制動作/// <summary>/// 停止板卡中全部軸/// </summary>/// <returns></returns>public abstract bool StopAllAxis();/// <summary>/// 停止軸(正常停止)/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool StopAxis(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.StopAxis();}return false;}/// <summary>///停止軸(急停)/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool StopEmg(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.StopEmg();}return false;}/// <summary>///絕對位置移動/// </summary>/// <param name="nAxisNo">軸號</param>/// <param name="nPos">位置</param>/// <param name="nSpeed">速度</param>/// <param name="accSpeed">加速度</param>/// <returns></returns>public virtual OperationResult AbsMove(int nAxisNo, double nPos, double nSpeed = -1, double accSpeed = -1){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.AbsMove(nPos, nSpeed, accSpeed);}return new OperationResult() { IsSuccess = false, ErrorMsg = "對象為null" };}/// <summary>///相對位置移動/// </summary>/// <param name="nAxisNo"></param>/// <param name="nPos"></param>/// <param name="nSpeed"></param>/// <returns></returns>public virtual OperationResult RelativeMove(int nAxisNo, double nPos, double nSpeed = -1, double accSpeed = -1){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.RelativeMove(nPos, nSpeed, accSpeed);}return new OperationResult() { IsSuccess = false, ErrorMsg = "對象為null" };}/// <summary>///jog運動/// </summary>/// <param name="nAxisNo"></param>/// <param name="bPositive"></param>/// <param name="nSpeed"></param>/// <returns></returns>public virtual OperationResult JogMove(int nAxisNo, bool bPositive, double nSpeed = -1){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.JogMove(bPositive, nSpeed);}return new OperationResult() { IsSuccess = false, ErrorMsg = "對象為null" };}/// <summary>///開啟使能/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool ServoOn(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.ServoOn();}return false;}/// <summary>///斷開使能/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool ServoOff(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.ServoOff();}return false;}/// <summary>///獲取軸的當前位置/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual double GetAixsPos(int nAxisNo){if (!OnLine){throw new Exception("板卡未連接!");}if (AxisBaseList.Count == 0){throw new Exception("沒有可用的軸對象");}var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.GetAixsPos();}return -999999.4;}/// <summary>///位置清零/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool SetPosZero(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.SetPosZero();}return false;}/// <summary>/// 讀取伺服使能狀態/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool IsServoOn(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.IsServoOn();}return false;}/// <summary>///回原點/// </summary>/// <param name="nAxisNo">軸號</param>/// <param name="nParam">回原方向 1:正方向 -1:負方向</param>/// <returns></returns>public virtual OperationResult Home(int nAxisNo, int nParam){if (!OnLine){return new OperationResult() { IsSuccess = false, ErrorMsg = "設備沒有連接!" };}if (AxisBaseList.Count == 0){return new OperationResult() { IsSuccess = false, ErrorMsg = "沒有可用的軸對象" };}var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.Home(nParam);}return new OperationResult() { IsSuccess = false, ErrorMsg = $"沒有找對軸號:{nAxisNo} 對應的軸對象" };}/// <summary>/// 回原點是否正常停止/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual OperationResult IsHomeNormalStop(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.IsHomeNormalStop();}return new OperationResult() { IsSuccess = false, ErrorMsg = "軸對象為null" };}/// <summary>/// 停止回原動作/// </summary>/// <returns></returns>public virtual bool StopHomeAction(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.StopHomeAction();}return false;}/// <summary>/// 清除軸狀態/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual bool ClrSts(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.ClrSts();}return false;}/// <summary>/// 清除所有軸狀態/// </summary>/// <returns></returns>public abstract bool ResetAllAxisStatus();/// <summary>///獲取軸卡運動狀態/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public virtual int GetMotionState(int nAxisNo){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.GetMotionState();}return -1;}/// <summary>/// 檢測是否有軸報警/// </summary>/// <returns></returns>public abstract bool CheckAllAxisAlarm();/// <summary>/// 讀取軸報警/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool IsAlarmFlag(int nAxisNo);/// <summary>/// 讀取軸正限位/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool IsPosLimitFlag(int nAxisNo);/// <summary>/// 讀取軸負限位/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>hpublic abstract bool IsNegLimitFlag(int nAxisNo);/// <summary>/// 讀取軸原點/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool IsHomeFlag(int nAxisNo);/// <summary>/// 獲取回零狀態/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool IsHomeStatus(int nAxisNo);/// <summary>/// 軸停止/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool IsStop(int nAxisNo);#endregion 2. 軸控制動作/// <summary>/// 設置單軸的某一運動參數/// </summary>/// <param name="nAxisNo">軸號</param>/// <param name="nParam">參數:1:加速度 2:減速度 3:起跳速度 4:結束速度(凌華卡) 5:平滑時間(固高卡S曲線) 其它:自定義擴展</param>/// <param name="nData">參數值</param>/// <returns></returns>public virtual bool SetAxisParam(int nAxisNo, AxisMotionParam nParam, int nData){var v = AxisBaseList.Find(c => c.axisParam.AxisNo == nAxisNo);if (v != null){return v.SetAxisParam(nParam, nData);}return false;}}
軸控制類
/// <summary>/// 軸抽象基類/// </summary>public abstract class AxisBase{/// <summary>/// 軸無效值/// </summary>public const double AxisInvalidPos = -999999.4;/// <summary>/// 軸參數/// </summary>public AxisParam axisParam { get; set; }/// <summary>/// 軸號/// </summary>public short AxisNo => (short)axisParam.AxisNo;/// <summary>/// 卡號/// </summary>public short CardNo => (short)axisParam.CardNo;/// <summary>/// 脈沖當量/// </summary>public float Units => (float)(axisParam.Subdivide * 1.0 / axisParam.HelicalPitch);///// <summary>///// 停止回原動作(標志)///// 判斷此標志true 停止進行中的回原動作///// </summary>//protected bool stopHome;/// <summary>/// 構造方法/// </summary>/// <param name="axisParam">軸參數</param>public AxisBase(AxisParam axisParam){this.axisParam = axisParam;WriteInfo = new WriteInfo((str) =>{Console.WriteLine(str);});}/// <summary>/// 寫錯誤信息方法/// </summary>public WriteInfo WriteInfo = null;/// <summary>/// 設置錯誤信息輸出函數/// </summary>/// <param name="writeInfo">回調函數</param>public void SetWriteInfoCB(WriteInfo writeInfo){this.WriteInfo = writeInfo;}// 軸的操作方法 jog move abs 使能#region 2. 軸控制動作/// <summary>/// 停止回原動作/// </summary>/// <returns></returns>public abstract bool StopHomeAction();/// <summary>///軸位置清零/// </summary>/// <returns></returns>public abstract bool SetPosZero();/// <summary>/// 報警清除/// </summary>/// <returns>結果</returns>public abstract bool ClrSts();/// <summary>///開啟使能/// </summary>/// <returns></returns>public abstract bool ServoOn();/// <summary>///斷開使能/// </summary>/// <returns></returns>public abstract bool ServoOff();/// <summary>/// 伺服使能狀態/// </summary>/// <returns> </returns>public abstract bool IsServoOn();/// <summary>/// 絕對位置移動/// </summary>/// <param name="nPos">位置</param>/// <param name="nSpeed">速度 默認為:-1 表示使用軸參數的速度</param>/// <param name="accSpeed">加速度 默認為:-1 表示使用軸參數的加速度</param>/// <returns></returns>public abstract OperationResult AbsMove(double nPos, double nSpeed = -1,double accSpeed=-1);/// <summary>///相對位置移動/// </summary>/// <param name="nPos"></param>/// <param name="nSpeed">速度 默認為:-1 表示使用軸參數的速度</param>/// <returns></returns>public abstract OperationResult RelativeMove(double nPos, double nSpeed = -1,double accSpeed=-1);/// <summary>///jog運動/// </summary>/// <param name="bPositive">方向</param>/// <param name="nSpeed">速度 默認為:-1 表示使用軸參數的速度</param>/// <returns></returns>public abstract OperationResult JogMove(bool bPositive, double nSpeed = -1);/// <summary>///軸正常停止/// </summary>/// <param name="nAxisNo"></param>/// <returns></returns>public abstract bool StopAxis();/// <summary>/// 單軸急停/// </summary>/// <returns></returns>public abstract bool StopEmg();/// <summary>///獲取軸的當前位置/// </summary>/// <returns></returns>public abstract double GetAixsPos();/// <summary>/// 回原/// </summary>/// <param name="nParam">回原方向 1:正方向 -1:負方向</param>/// <param name="timeout">超時時間(-1表示 不啟用超時時間)</param>/// <returns></returns>public abstract OperationResult Home(int nParam);/// <summary>/// 回原點是否正常停止/// </summary>/// <returns></returns>public abstract OperationResult IsHomeNormalStop();#endregion 2. 軸控制動作#region 3. 軸狀態/// <summary>///獲取軸運動狀態/// </summary>/// <returns></returns>public abstract int GetMotionState();///// <summary>/////獲取軸卡運動IO信號///// </summary>///// <returns></returns>//public abstract int GetMotionIoState();///// <summary>///// 軸是否正常停止///// </summary>///// <returns> -2:指令返回錯誤 -1:運動中 1:驅動器報警 4:正限位 5:負限位 3:未使能</returns>//public abstract int IsAxisNormalStop();/// <summary>/// 軸是否報警/// </summary>/// <returns>返回 true 報警 false 沒有報警</returns>public abstract bool IsAlarmFlag();/// <summary>/// 軸是否處于正限位/// </summary>/// <returns></returns>public abstract bool IsPosLimitFlag();/// <summary>/// 軸是否處于負限位/// </summary>/// <returns></returns>public abstract bool IsNegLimitFlag();public abstract bool IsHomeFlag();///// <summary>///// 等待軸正常停止///// </summary>///// <returns>操作結果</returns>//public abstract OperationResult WaitStop();#endregion 3. 軸狀態/// <summary>/// 設置軸的 單一控制參數/// </summary>/// <param name="nParam">參數類型:1:加速度 2:減速度 3:起跳速度 4:結束速度 5:平滑時間 其它:自定義擴展</param>/// <param name="nData">參數值</param>/// <returns></returns>public abstract bool SetAxisParam(AxisMotionParam nParam, int nData);/// <summary>/// 設置軸軟極限/// </summary>/// <returns></returns>public abstract bool SetSoftLimit();/// <summary>/// 軸狀態檢測/// </summary>/// <returns>檢測結果 OperationResult</returns>public abstract OperationResult CommonMotionValidate();/// <summary>/// 更新軸信息/// </summary>public void UpdataState(){axisParam.NegativeSignalState = IsNegLimitFlag();axisParam.PositiveSignalState = IsPosLimitFlag();axisParam.HomeSignalState = IsHomeFlag();axisParam.AxisPos = GetAixsPos();axisParam.IsErrState = IsAlarmFlag();}}