AxisBean.cs 15.6 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 OnlineStore.DeviceLibrary
{
    public class AxisBean
    {
        public ConfigMoveAxis Config = null;
        public static int TimeoutInterval = 500;
        /// <summary>
        /// 是否需要回零
        /// </summary>
        public bool IsNeedHome = false;
        /// <summary>
        /// 正常工作过程中判断位置是否到达时使用
        /// </summary>
        public int LastPosition = 0;

        public string AxisName;
        public AxisBean(ConfigMoveAxis axisConfig, string deviceName, bool needHome = false)
        {
            this.IsNeedHome = needHome;
            this.Config = axisConfig;
            AxisName = deviceName + " " + Config.Explain + "[" + Config.DeviceName + "-" + Config.GetAxisValue() + "]";
        }


        private bool IsIntSlvBlock = false;
        public bool Open(bool isCheck, out string Msg)
        {
            Msg = "";
            string portName = Config.DeviceName;
            short slvAddr = Config.GetAxisValue();
            //打开所有轴 
            AxisManager.instance.OpenPort(Config.DeviceName);
            Thread.Sleep(50);
            //初始化
            if (!IsIntSlvBlock)
            {
                AxisManager.instance.InitSlvAddr(portName, slvAddr, Config.TargetSpeed, Config.AddSpeed, Config.DelSpeed);
                Thread.Sleep(100);
            }
            AxisManager.instance.AlarmClear(portName, slvAddr);
            Thread.Sleep(50);
            AxisManager.instance.ServoOn(portName, slvAddr);

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

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

        }

        /// <summary>
        /// 松下伺服电机运动
        /// </summary> 
        public void AbsMove(DeviceMoveInfo MoveInfo, int targetPosition, int targetSpeed)
        {
            bool rtn;
            if (MoveInfo == null)
            {
                rtn = AbsMove(targetPosition, targetSpeed);
                LogUtil.info($"{this.AxisName} AbsMove To [{targetPosition}] [speed={targetSpeed}][{rtn}][MoveInfo = null]");
            }
            else
            {
                MoveInfo.WaitList.Add(WaitResultInfo.WaitAxis(Config, targetPosition, targetSpeed));
                Config.TargetPosition = targetPosition;
                 rtn = AxisManager.instance.AbsMove(Config.DeviceName, Config.GetAxisValue(), targetPosition, targetSpeed, Config.AddSpeed, Config.DelSpeed);
                LogUtil.info($"{this.AxisName} AbsMove To [{targetPosition}] [speed={targetSpeed}][{rtn}]");
            }
        }

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

            bool isOk = AxisManager.instance.GetBusyStatus(deviceName, axisNo).Equals(0) && AxisManager.instance.GetInPositionSingle(deviceName, axisNo).Equals(1);
            int outCount = AxisManager.instance.GetActualtPosition(deviceName, axisNo);
            int targetCount = AxisManager.instance.GetTargetPosition(deviceName, axisNo);
            int errorCount = Math.Abs(outCount - targetPosition); 
            if (isOk)
            {
                string state = AxisManager.instance.GetStatus(deviceName, axisNo);
                //打印轴状态
                LogUtil.info($" {MoveInfo.SLog}{MoveInfo.Name}{axis.DisplayStr},目标位置[{targetPosition}]当前位置[{outCount}]规划位置[{targetCount}]轴状态[{state}]");
                if (errorCount <= axis.CanErrorCountMax)
                {
                    return true;
                }
                //轴不报警时才重新运动,否则直接报警
                int alarm = AxisManager.instance.GetAlarmStatus(deviceName, axisNo);

                //判断是否需要重新运动
                if (alarm.Equals(1))
                {
                    //msg = " " + MoveInfo.SLog + MoveInfo.Name + axis.DisplayStr + ",目标位置[" + targetPosition + "]当前位置[" + outCount
                    //   + "],误差过大且轴报警";
                    msg = $" {MoveInfo.SLog}{MoveInfo.Name}{axis.DisplayStr},目标位置[{targetPosition}]当前位置[{outCount}]误差[{errorCount}]规划位置[{targetCount}],误差过大且轴报警";
                    LogUtil.error(msg, 600);
                }
                else if (MoveInfo.CanWhileCount > 0 && alarm.Equals(0))
                {
                    string clearMsg = "";
                    ////判断轴是否报警
                    //if (MoveInfo.CanWhileCount <= 3)
                    //{
                    //    int isAlarm = AxisManager.instance.GetAlarmStatus(deviceName, axisNo);
                    //    if (isAlarm.Equals(1))
                    //    {
                    //        clearMsg = "清理报警,";
                    //        AxisManager.instance.AlarmClear(deviceName, axisNo);
                    //        Thread.Sleep(200);
                    //        AxisManager.instance.ServoOn(deviceName, axisNo);
                    //        Thread.Sleep(500);
                    //    }
                    //}
                    //if (String.IsNullOrEmpty(clearMsg))
                    //{
                    //    AxisManager.instance.SuddenStop(axis.DeviceName, axis.GetAxisValue());
                    //    Thread.Sleep(100);
                    //}
                    LogUtil.error($"{MoveInfo.Name}{axis.DisplayStr}目标位置[{targetPosition}]当前位置[{outCount}]误差[{errorCount}]规划位置[{targetCount}],误差过大, {clearMsg}重新开始运动,剩余[{MoveInfo.CanWhileCount}]次");
                    AxisManager.instance.AbsMove(axis.DeviceName, axis.GetAxisValue(), targetPosition, targetSpeed, axis.AddSpeed, axis.DelSpeed);
                    MoveInfo.CanWhileCount--;
                    Thread.Sleep(200);
                }
                else
                {
                    msg = $" {MoveInfo.SLog}{MoveInfo.Name}{axis.DisplayStr},目标位置[{targetPosition}]当前位置[{outCount}]误差[{errorCount}]规划位置[{targetCount}],误差过大,需要报警";
                    LogUtil.error(msg, 600);
                }
            }
            return false;
        }
        public static bool HomeMoveIsEnd(DeviceMoveInfo MoveInfo, ConfigMoveAxis axis, out string msg)
        {
            msg = "";
            if (AxisManager.instance.IsHomeMoveEnd(axis.DeviceName, axis.GetAxisValue()))
            {
                //原点完成并且位置=0
                int outCount = AxisManager.instance.GetActualtPosition(axis.DeviceName, axis.GetAxisValue());
                int errorCount = Math.Abs(outCount);
                if (errorCount <= axis.CanErrorCountMax)
                {
                    return true;
                }
                //判断是否需要重新运动
                //轴不报警时才重新运动,否则直接报警
                int alarm = AxisManager.instance.GetAlarmStatus(axis.DeviceName, axis.GetAxisValue());

                //判断是否需要重新运动
                if (alarm.Equals(1))
                {
                    msg = " " + MoveInfo.SLog + MoveInfo.Name + axis.DisplayStr + ",收到原点完成信号,当前位置[" + outCount + "],误差过大且轴报警";
                    LogUtil.error(msg, 600);
                }
                if (MoveInfo.CanWhileCount > 0)
                {
                    LogUtil.error(MoveInfo.Name + axis.DisplayStr + "收到原点完成信号,当前位置[" + outCount + "],重新回原点,剩余[" + MoveInfo.CanWhileCount + "]次");
                    //LogUtil.error( StoreName +  moveAxis.DisplayStr +  "重新回原点"); 
                    AxisManager.instance.HomeMove(axis.DeviceName, axis.GetAxisValue(), axis.HomeHighSpeed, axis.HomeLowSpeed, axis.HomeAddSpeed);
                    MoveInfo.CanWhileCount--;
                }
                else
                {
                    msg = MoveInfo.Name + " " + MoveInfo.SLog + axis.DisplayStr + ",收到原点完成信号,当前位置[" + outCount + "],误差过大,需要报警";
                    LogUtil.error(msg);
                }
            }
            return false;
        }

        /// <summary>
        /// 运动过程中轴状态打印
        /// </summary> 
        public static bool ACAxisStsInMove(DeviceMoveInfo MoveInfo, ConfigMoveAxis axis, int targetPosition, int targetSpeed, out string msg)
        {
            msg = "";
            string deviceName = axis.DeviceName;
            short axisNo = axis.GetAxisValue();

            bool isOk = AxisManager.instance.GetBusyStatus(deviceName, axisNo).Equals(0) && AxisManager.instance.GetInPositionSingle(deviceName, axisNo).Equals(1);
            int outCount = AxisManager.instance.GetActualtPosition(deviceName, axisNo);
            int targetCount = AxisManager.instance.GetTargetPosition(deviceName, axisNo);
            string state = AxisManager.instance.GetStatus(deviceName, axisNo);
            //实时打印轴状态
            LogUtil.LOGGER.Debug($" 轴实时状态打印:{MoveInfo.SLog}{MoveInfo.Name}{axis.DisplayStr},目标位置[{targetPosition}]当前位置[{outCount}]规划位置[{targetCount}]轴状态[{state}]");
            return false;
        }
        public int GetAclPosition()
        {
            int p = AxisManager.instance.GetActualtPosition(Config.DeviceName, Config.GetAxisValue());
            return p;
        }
        public bool IsInPosition(int targetP, int canErrorMax = 0)
        {
            if (canErrorMax <= 0)
            {
                canErrorMax = Config.CanErrorCountMax;
            }
            int currp = GetAclPosition();

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

        }
        public void SuddenStop()
        {
            AxisManager.instance.SuddenStop(Config.DeviceName, Config.GetAxisValue());
        }


        #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 AxisStopCheckMove()
        {
            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, 0).Equals(TargetIoValue))
                {
                    AxisStopCheckMove();
                    LogUtil.info(AxisName + "上料轴,检测到 " + TargetIoType + "=" + TargetIoValue + ",停止运动,AclPosition=" + GetAclPosition().ToString());
                    SuddenStop();
                }
            }
            catch (Exception ex)
            {
                LogUtil.error("CheckTimer_Elapsed出错:", ex);
            }
            finally
            {
                IsInProcess = false;
            }
        }

        public bool IsBatchMove()
        {
            if (axisCheckTimer != null && axisCheckTimer.Enabled)
            {
                return true;
            }
            return false;
        }
        #endregion
    }
}