AxisBean.cs 13.1 KB
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    public class AxisBean
    {
        public static List<AxisBean> List = new List<AxisBean>();
        public ConfigMoveAxis Config = null;
        public static int TimeoutInterval = 500;
        /// <summary>
        /// 正常工作过程中判断位置是否到达时使用
        /// </summary>
        public int LastPosition = 0;
        /// <summary>
        /// 干涉检测回调 from, to
        /// </summary>
        public event Func<int,int,(bool,string)> interference;
        public string AxisName;
        public AxisBean(ConfigMoveAxis axisConfig, string deviceName)
        {
            this.Config = axisConfig;
            AxisName = deviceName + " " + Config.Explain + "[" + Config.DeviceName + "-" + Config.GetAxisValue() + "]";
            List.Add(this);
        }

        public bool Open(bool isCheck, out string Msg)
        {
            Msg = "";
            string portName = Config.DeviceName;
            short slvAddr = Config.GetAxisValue();
            AxisManager.AlarmClear(portName, slvAddr);
            Thread.Sleep(50);
            AxisManager.ServoOn(portName, slvAddr);
            Thread.Sleep(50);
            //打开所有轴
            if (isCheck)
            {
                if (!OpenAxis(out Msg))
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 打开所有轴
        /// </summary>
        /// <returns></returns>
        private bool OpenAxis(out string msg)
        {
            msg = "";
            //判断轴是否正常
            string portName = Config.DeviceName;
            short slvAddr = Config.GetAxisValue();
            if (AxisManager.IsServeoOn(portName, slvAddr))
            {
                LogUtil.info(AxisName + "成功打开");
            }
            else
            {
                //清理报警,再重新打开一次
                LogUtil.info(AxisName + "第一次打开失败,先清理一下报警,再重新打开一次");
                AxisManager.AlarmClear(portName, slvAddr);
                System.Threading.Thread.Sleep(1000);
                AxisManager.ServoOn(portName, slvAddr);
                System.Threading.Thread.Sleep(100);
                if (AxisManager.IsServeoOn(portName, slvAddr))
                {
                    LogUtil.info(AxisName + "清理报警后重新打卡轴成功:" + Config.Explain);
                }
                else
                {
                    AxisManager.ServoOff(portName, slvAddr);
                    msg = "打开轴" + Config.Explain + "失败 ";
                    LogUtil.info(AxisName + msg);
                    return false;
                }
            }

            return true;
        }
        public void ServoOff()
        {
            LogUtil.info("ServoOff【" + AxisName + "】");
            AxisManager.ServoOff(Config.DeviceName, Config.GetAxisValue());
        }
        public void HomeMove(MoveInfo MoveInfo)
        {
            Config.TargetPosition = 0;
            LogUtil.info(AxisName + "speed[" + Config.HomeHighSpeed + "]开始原点返回");
            MoveInfo.WaitList.Add(WaitResultInfo.WaitAxis(Config, true));
            AxisManager.HomeMove(Config.DeviceName, (short)Config.GetAxisValue(), Config.HomeHighSpeed, Config.HomeLowSpeed, Config.HomeAddSpeed);
        }

        /// <summary>
        /// 松下伺服电机运动
        /// </summary> 
        public void AbsMove(MoveInfo MoveInfo, int targetPosition, int targetSpeed)
        {
            if (MoveInfo == null)
            {
                AbsMove(targetPosition, targetSpeed);
            }
            else
            {
                MoveInfo.WaitList.Add(WaitResultInfo.WaitAxis(Config, targetPosition, targetSpeed));
                Config.TargetPosition = targetPosition;
                AxisManager.AbsMove(Config.DeviceName, Config.GetAxisValue(), targetPosition, targetSpeed, targetSpeed * 4, targetSpeed * 4);// Config.AddSpeed, Config.DelSpeed);
            }
        }

        /// <summary>
        /// 判断AC伺服电机轴是否运动完成
        /// </summary> 
        public static bool ACAxisMoveIsEnd(MoveInfo MoveInfo, ConfigMoveAxis axis, int targetPosition, int targetSpeed, out string msg)
        {
            msg = "";
            string deviceName = axis.DeviceName;
            short axisNo = axis.GetAxisValue();

            bool isOk = AxisManager.GetBusyStatus(deviceName, axisNo).Equals(0);
            int outCount = AxisManager.GetActualtPosition(deviceName, axisNo);
            int errorCount = Math.Abs(outCount - targetPosition);
            if (isOk)
            {
                if (errorCount <= axis.CanErrorCountMax)
                {
                    return true;
                }
                //判断是否需要重新运动
                if (MoveInfo.CanWhileCount > 0)
                {
                    string clearMsg = "";
                    //判断轴是否报警
                    if (MoveInfo.CanWhileCount <= 3)
                    {
                        int isAlarm = AxisManager.GetAlarmStatus(deviceName, axisNo);
                        if (isAlarm.Equals(1))
                        {
                            clearMsg = "清理报警,";
                            AxisManager.AlarmClear(deviceName, axisNo);
                            Thread.Sleep(200);
                            AxisManager.ServoOn(deviceName, axisNo);
                            Thread.Sleep(200);
                        }
                    }
                    if (string.IsNullOrEmpty(clearMsg))
                    {
                        AxisManager.SuddenStop(axis.DeviceName, axis.GetAxisValue());
                        Thread.Sleep(100);
                    }
                    LogUtil.error($"{ MoveInfo.Name} {MoveInfo.MoveStep} {axis.DisplayStr}目标位置{targetPosition}当前位置{outCount},误差过大,{clearMsg}重新开始运动,剩余{MoveInfo.CanWhileCount}次");
                    AxisManager.AbsMove(axis.DeviceName, axis.GetAxisValue(), targetPosition, targetSpeed, targetSpeed * 4, targetSpeed * 4);// , axis.AddSpeed, axis.DelSpeed);
                    MoveInfo.CanWhileCount--;
                    Thread.Sleep(200);
                }
                else
                {
                    msg = $"{MoveInfo.Name} {MoveInfo.MoveStep} {axis.DisplayStr},目标位置{targetPosition},当前位置{outCount},误差过大,需要报警";
                    LogUtil.error(msg, 600);
                }
            }
            return false;
        }
        public static bool HomeMoveIsEnd(MoveInfo MoveInfo, ConfigMoveAxis axis, out string msg)
        {
            msg = "";
            if (AxisManager.IsHomeMoveEnd(axis.DeviceName, axis.GetAxisValue()))// || AxisManager.AxisStsINP(axis.DeviceName, axis.GetAxisValue()).Equals(1))
            {
                //原点完成并且位置=0
                int outCount = AxisManager.GetActualtPosition(axis.DeviceName, axis.GetAxisValue());
                int errorCount = Math.Abs(outCount);
                if (errorCount <= axis.CanErrorCountMax)
                {
                    return true;
                }
                //判断是否需要重新运动
                if (MoveInfo.CanWhileCount > 0)
                {
                    LogUtil.error(MoveInfo.Name + axis.DisplayStr + "收到原点完成信号,当前位置[" + outCount + "],重新回原点,剩余[" + MoveInfo.CanWhileCount + "]次");
                    //LogUtil.error( StoreName +  moveAxis.DisplayStr +  "重新回原点"); 
                    AxisManager.HomeMove(axis.DeviceName, axis.GetAxisValue(), axis.HomeHighSpeed, axis.HomeLowSpeed, axis.HomeAddSpeed);
                    MoveInfo.CanWhileCount--;
                }
                else
                {
                    msg = MoveInfo.Name + " " + MoveInfo.MoveStep + axis.DisplayStr + ",收到原点完成信号,当前位置[" + outCount + "],误差过大,需要报警";
                    LogUtil.error(msg);
                }
            }
            return false;
        }

        public int GetAclPosition()
        {
            int p = AxisManager.GetActualtPosition(Config.DeviceName, Config.GetAxisValue());
            return p;
        }
        public bool IsInPosition(int targetP)
        {
            int currp = GetAclPosition();

            int chaz = targetP - currp;
            if (Math.Abs(chaz) < Config.CanErrorCountMax)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 绝对运动至点,不等待结果
        /// </summary> 
        private void AbsMove(int targetPos, double targetSpeed)
        {
            if (targetPos.Equals(-1))
            {
                return;
            }
            LastPosition = -1;
            //if (targetSpeed <= 0)//targetSpeed > Config.TargetSpeed || 
            //{
            //    targetSpeed = Config.TargetSpeed;
            //}
            //小于1,表示是目标速度的百分比
            if (targetSpeed <= 1)
            {
                targetSpeed = Config.TargetSpeed * targetSpeed;
            }
            AxisManager.AbsMove(Config.DeviceName, Config.GetAxisValue(), targetPos, (int)targetSpeed, (int)targetSpeed * 4, (int)targetSpeed * 4);// , Config.AddSpeed, Config.DelSpeed);

        }
        public void SuddenStop()
        {
            AxisManager.SuddenStop(Config.DeviceName, Config.GetAxisValue());
        }
        /// <summary>
        /// 判断轴运动是否安全
        /// </summary>
        /// <returns></returns>
        public bool IsSafe(int Targetpos,out string msg) {
            msg = "";
            if (interference == null)
                return true;
            bool result;
            (result,msg) = interference.Invoke(GetAclPosition(), Targetpos);
            return !result;
        }


        #region  匀速上升处理 
        private System.Timers.Timer axisCheckTimer = null;
        internal string TargetIoType = "";
        internal IO_VALUE TargetIoValue = IO_VALUE.HIGH;
        public bool BatchAxisStartCheck(string targetIo, IO_VALUE value = IO_VALUE.HIGH)
        {
            if (String.IsNullOrEmpty(targetIo))
            {
                targetIo = "";
            }
            if (axisCheckTimer == null)
            {
                axisCheckTimer = new System.Timers.Timer();
                axisCheckTimer.AutoReset = true;
                axisCheckTimer.Interval += 30;
                axisCheckTimer.Elapsed += CheckTimer_Elapsed;
                axisCheckTimer.Enabled = false;
            }
            TargetIoValue = value;
            TargetIoType = targetIo;
            IsInProcess = false;
            axisCheckTimer.Start();
            return true;
        }

        public bool StopAxisCheckMove()
        {
            if (!(axisCheckTimer == null))
            {
                axisCheckTimer.Stop();
            }
            return true;
        }
        private bool IsInProcess = false;
        private DateTime lastOkTime = DateTime.Now;
        private void CheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TimeSpan pan = DateTime.Now - lastOkTime;
            if (IsInProcess && pan.TotalMilliseconds < 100) { return; }
            try
            {

                IsInProcess = true;
                lastOkTime = DateTime.Now;
                if (IOManager.IOValue(TargetIoType).Equals(TargetIoValue))
                {
                    StopAxisCheckMove();
                    LogUtil.info(AxisName + "上料轴,检测到 " + TargetIoType + "=" + TargetIoValue + ",停止运动");
                    SuddenStop();
                }
            }
            catch (Exception ex)
            {
                LogUtil.error("CheckTimer_Elapsed出错:", ex);
            }
            finally
            {
                IsInProcess = false;
            }
        }
        #endregion

        public static bool RunMultiAxis(bool isCheck, out string msg, List<AxisBean> axisArray)
        {
            msg = "";
            foreach (AxisBean axis in axisArray)
            {
                bool result = axis.Open(false, out msg);
                if (!result || (!String.IsNullOrEmpty(msg)))
                {
                    //SetWarnMsg(Name + msg);
                    //Alarm(AlarmType.AxisAlarm);
                    return false;
                }
            }
            Thread.Sleep(50);
            return true;
        }
        public static void StopMultiAxis(List<AxisBean> axisArray)
        {
            foreach (AxisBean axis in axisArray)
            {
                axis.SuddenStop();
                Thread.Sleep(10);
            }
        }
        public static void CloseMultiAxis(List<AxisBean> axisArray)
        {
            foreach (AxisBean axis in axisArray)
            {                
                axis.ServoOff();
                Thread.Sleep(10);
            }
        }

    }

}