zoukankan      html  css  js  c++  java
  • C#运动控制运动暂停思路检测沿信号方法

    以下是学习笔记:

    1.思路分析:

    【1.1】运动的两种方式:

    相对运动:相对于现在的位置走一段距离,相对运动走暂停比较麻烦,某一瞬间按了暂停,可能不知道走了多少,恢复比较麻烦。

    绝对运动:回原点,相对于原点的位置,相对运动做暂停简单些。

    【1.2】暂停按钮放在哪里?

    查看说明书:给轴运动指令号,暂停按钮应该放在等待停止的中。

     2,封装的运动控制方法

    【2.1】Motion.cs中:封装的单轴绝对定位的方法:就是发一个运动指令

            #region 单轴绝对定位
    
            /// <summary>
            /// 单轴绝对定位
            /// </summary>
            /// <param name="axis">轴号</param>
            /// <param name="pos">位置</param>
            /// <param name="vel">速度</param>
            /// <param name="acc">加减速度</param>
            /// <returns></returns>
            public OperationResult MoveAbs(short axis, double pos, double vel = 10, double acc = 0.0125)
            {
                //通用运动初始化验证
    
                OperationResult result = CommonMotionValidate(axis);
                if (!result.IsSuccess) return result;
    
                short error = 0;
    
                try
                {
                    //清除标志
                    error = gts.GT_ClrSts(axis, 1);
                    ErrorHandler("GT_ClrSts", error);
    
                    // 将轴设为点动模式
                    error = gts.GT_PrfTrap(axis);
                    ErrorHandler("GT_PrfTrap", error);
    
                    //创建一个TJboPra对象
                    gts.TTrapPrm trap;
    
                    //读取点位运动参数
                    error = gts.GT_GetTrapPrm(axis,out trap);
                    ErrorHandler("GT_GetTrapPrm", error);
    
                    trap.acc = acc;
                    trap.dec = acc;
                    trap.smoothTime = 25;//[0,50]
    
                    //设置点位运动参数
                    error = gts.GT_SetTrapPrm(axis, ref trap);
                    ErrorHandler("GT_SetTrapPrm", error);
    
                    int posPulse = 0;
    
                    if (axis == advancedParameter.Axis_X)
                    {
                        posPulse = Convert.ToInt32(Math.Round(pos * advancedParameter.Scale_X));
                    }
                    else if (axis == advancedParameter.Axis_Y)
                    {
                        posPulse = Convert.ToInt32(Math.Round(pos * advancedParameter.Scale_Y));
                    }
                    else if (axis == advancedParameter.Axis_Z)
                    {
                        posPulse = Convert.ToInt32(Math.Round(pos * advancedParameter.Scale_Z));
                    }
                    else
                    {
                        posPulse = Convert.ToInt32(pos);
                    }
    
                    //设置AIXS轴的目标位置
                    error = gts.GT_SetPos(axis, posPulse);
                    ErrorHandler("GT_SetPos", error);
                    //设置AIXS轴的目标速度
                    error = gts.GT_SetVel(axis, vel);
                    ErrorHandler("GT_SetVel", error);
                    //【上面的代码,都是设置参数的,GT_Update之前都是不动的】
                    //设置AIXS轴的的运动【调用GT_Update就是发运动指令,发完运动指令就开始运动的,发完运动指令后代码就结束了,不等待的】
                    error = gts.GT_Update(1<<(axis-1));
                    ErrorHandler("GT_Update", error);
    
                }
                catch (Exception e)
                {
                    result.IsSuccess = false;
                    result.ErrorMsg = e.Message;
                    return result;
                }
    
                return OperationResult.CreateSuccessResult();
            }
    
            /// <summary>
            /// 单轴绝对定位,方法的重载
            /// </summary>
            /// <param name="axis">轴相关信息类</param>
            /// <returns></returns>
            public OperationResult MoveAbs(Axis axis)
            {
                return MoveAbs(axis.AxisNo, axis.AxisDestPos, axis.AxisDestVel, axis.AxisDestAcc);
            }
            #endregion
    

     

    【2.1】Motion.cs中:封装的2单轴绝对定位的方法,就是调用上一个方法,实际自动流程中就是调用这里的方法。

            #region 2轴绝对定位
    
            /// <summary>
            /// 2轴绝对定位
            /// </summary>
            /// <param name="axis">轴号</param>
            /// <param name="pos">位置</param>
            /// <param name="vel">速度</param>
            /// <param name="acc">加减速度</param>
            /// <returns>操作结果</returns>
            public OperationResult Move2DAbs(short[] axis, double[] pos,double[] vel,double[] acc)
            {
                if (axis.Length == 2 && pos.Length == 2 && vel.Length == 2 && acc.Length == 2)//保证是2轴的2个参数
                {
                    //通用运动初始化验证
                    OperationResult result = CommonMotionValidate(axis[0]);
                    if (!result.IsSuccess) return result;
    
                    result = CommonMotionValidate(axis[1]);
                    if (!result.IsSuccess) return result;
    
                    Axis axisInfoX=new Axis();
                    axisInfoX.AxisNo = axis[0];
                    axisInfoX.AxisDestPos = pos[0];
                    axisInfoX.AxisDestVel = vel[0];
                    axisInfoX.AxisDestAcc = acc[0];
    
                    Axis axisInfoY = new Axis();
                    axisInfoY.AxisNo = axis[1];
                    axisInfoY.AxisDestPos = pos[1];
                    axisInfoY.AxisDestVel = vel[1];
                    axisInfoY.AxisDestAcc = acc[1];
    
                    //绝对定位
                    result = MoveAbs(axisInfoX);
                    if (!result.IsSuccess) return result;
    
                    result = MoveAbs(axisInfoY);
                    if (!result.IsSuccess) return result;
    
                    //【分析】上面的“绝对定位”的代码只是发了一个运动指令就结束了,就开始运动了,不费时间的
                    //【分析】费时间的是下面的“等待停止”的代码,轴运动了之后就一直等,一直在循环等待运动到位后轴停止
    
                    //等待停止
                    result = WaitStop(new List<Axis>(){ axisInfoX, axisInfoY });
                    if (!result.IsSuccess) return result;
    
    
    
                    return OperationResult.CreateSuccessResult();
                }
                return new OperationResult()
                {
                    IsSuccess = false,
                    ErrorMsg = "传递参数长度不正确"
                };
            }
    
            #endregion
    

    【2.3】Motion.cs中:封装的等待轴正常停止的方法,只要把判断暂停放在这里就可以了。

     

            #region 等待轴正常停止
    
            /// <summary>
            /// 等待轴正常停止
            /// </summary>
            /// <param name="axis">轴号</param>
            /// <returns>操作结果</returns>
            public OperationResult WaitStop(Axis axis)
            {
                //通用运动初始化验证
                OperationResult result = CommonMotionValidate(axis.AxisNo);
                if (!result.IsSuccess) return result;
    
                short error = 0;
                //轴状态
                int sts;
    
                do
                {
                    //如果isPause==True有人按了暂停
                    if (isPause)
                    {
                        StopAxis(axis.AxisNo);
                        while (true)
                        {
                            if (isPause)
                            {
                                Thread.Sleep(10);
                            }
                            else
                            {
                                //恢复指令
                                MoveAbs(axis);
    
                                //继续走
                                break;
                                
                            }
                        }
                    }
    
                    try
                    {
    
                        error = gts.GT_GetSts(axis.AxisNo, out sts,1,out uint pClock);
                        ErrorHandler("GT_GetSts", error);
                    }
                    catch (Exception e)
                    {
                        result.IsSuccess = false;
                        result.ErrorMsg = e.Message;
                        return result;
                    }
                } while ((sts&0x400)!=0);
    
                return OperationResult.CreateSuccessResult();
            }
    
            /// <summary>
            /// 等待2轴正常停止
            /// </summary>
            /// <param name="axis">轴号</param>
            /// <returns>操作结果</returns>
            public OperationResult WaitStop(List<Axis> axis)
            {
                if (axis.Count != 2)
                {
                    return new OperationResult()
                    {
                        IsSuccess = false,
                        ErrorMsg = "传递对象集合数量不为2"
                    };
                }
                //通用运动初始化验证
                OperationResult result = CommonInitedValidate();
                if (!result.IsSuccess) return result;
    
                short error = 0;
                //轴状态
                int sts0;
                int sts1;
    
                do
                {
                    //如果isPause==True有人按了暂停
                    if (isPause)
                    {
                        //先停止
                        StopAxis(axis[0].AxisNo);
                        StopAxis(axis[1].AxisNo);
    
                        //再一直等
                        while (true)
                        {
                            //如果按钮还是按下的状态
                            if (isPause)
                            {
                                Thread.Sleep(10);
                            }
                            //如果有人回复的暂停按钮
                            else
                            {
                                //恢复指令
                                MoveAbs(axis[0]);
                                MoveAbs(axis[1]);
    
                                //继续走,跳出循环
                                break;
                            }
                        }
                    }
    
                    try
                    {
                        error = gts.GT_GetSts(axis[0].AxisNo, out sts0, 1, out uint pClock0);
                        error = gts.GT_GetSts(axis[1].AxisNo, out sts1, 1, out uint pClock1);
                        ErrorHandler("GT_GetSts", error);
                    }
                    catch (Exception e)
                    {
                        result.IsSuccess = false;
                        result.ErrorMsg = e.Message;
                        return result;
                    }
                } while ((sts0 & 0x400) != 0|| (sts1 & 0x400) != 0);
    
                return OperationResult.CreateSuccessResult();
            }
    
            #endregion
    

    3,主窗体实现运动暂停的方法(主要代码)

    【3.1】变量:

            //创建暂停按钮上升沿的缓存值
            private bool PauseRiseCache = false;
    
            //创建暂停按钮下降沿的缓存值
            private bool PauseFallCache = true;
    

      

    【3.2】创建自动循环流程,一直检测暂停按钮的状态

     

            private void FrmMain_Load(object sender, EventArgs e)
            {
                //导航按钮事件绑定
                NaviButtonBind();
    
                //打开默认的窗体:实时监控窗体
                CommonNaviButton_ClickEvent(this.btn_monitor, null);
    
                //更新用户
                this.lbl_user.Text = Program.GlobalSysAdmin.LoginName;
    
                //板卡初始化
                AddLog(0, "板卡正在初始化");
                var result = motionEx.InitCarl();
    
                if (!result.IsSuccess)
                {
                    AddLog(1, "板卡初始化失败:" + result.ErrorMsg);
                }
                else
                {
                    AddLog(0, "板卡初始化成功");
                }
    
                //扫码枪
                result = scanner.StartMonitor();
                SetScanner(result.IsSuccess);
                if (!result.IsSuccess)
                {
                    AddLog(1, "扫码枪连接失败:" + result.ErrorMsg);
                }
                else
                {
                    scanner.ScannerReceived += Scanner_ScannerReceived;
                    AddLog(0, "扫码枪连接成功");
                }
    
                //调用委托更新界面
                SetRowState();
    
                //测试
                SetSNCode("123123123");
    
                //创建自动流程线程
                cts = new CancellationTokenSource();
    
                Task MainTask = new Task(MainPorcess, cts.Token);
    
                //创建检测暂停按钮的线程
                Task CheckPause = new Task(CheckPauseProcess, cts.Token);//可以用同一个标志位Token
    
                //线程关闭时调用的方法【关闭运动控制卡】
                cts.Token.Register(() => { motionEx.CloseCard(); });
    
                //开启线程
                MainTask.Start();
                CheckPause.Start();
            }
    
            #region 检测暂停线程
      
            private void CheckPauseProcess()
            {
                while (!cts.IsCancellationRequested)
                {
                    //获取暂停按钮的状态(输入)
                    bool current = motionEx.GetPauseButton();
                    //检测上升沿信号
                    if (CheckEdgeSingal(current, ref PauseRiseCache,true))
                    {
                        //按下了按钮
                        motionEx.IsPause = true;
                    }
                    //检测下降沿信号
                    if (CheckEdgeSingal(current, ref PauseFallCache,false))
                    {
                        //松开了按钮,恢复暂停
                        motionEx.IsPause = false;
                    }
                }
            }
    
            #endregion
    
            private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
            {
                cts.Cancel();
            }
    

      

    【3.3】检测沿信号的方法

            /// <summary>
            /// 检测沿信号
            /// </summary>
            /// <param name="current">当前值</param>
            /// <param name="cache">缓存值(上一次值)</param>
            /// <param name="isRsieOrFall">上升沿或下降沿,True为上升沿,False为下降沿</param>
            /// <returns>是否检测到沿信号</returns>
            private bool CheckEdgeSingal(bool current, ref bool cache, bool isRsieOrFall = false)
            {
                //如果是上升沿
                if (isRsieOrFall)
                {
                    //如果当前值为true并且上一次值为false,就说明是上升沿信号
                    if (current && !cache)
                    {
                        cache = current;
                        return true;
                    }
                    else
                    {
                        cache = current;
                        return false;
                    }
                }
                //否则是下降沿
                else
                {
                    //如果当前值为false并且上一次值为true,就说明是下降沿信号
                    if (!current && cache)
                    {
                        cache = current;
                        return true;
                    }
                    else
                    {
                        cache = current;
                        return false;
                    }
                }
            }
    

      

      

      

  • 相关阅读:
    网络设备
    Linux常用操作
    工作常用笔记
    性能测试问题总结
    mysql性能分析
    Java8新特性学习笔记-CompletableFuture
    Java语言定义的线程状态分析
    Gatling-插件开发
    RabbitMQ记录
    Go常用库
  • 原文地址:https://www.cnblogs.com/baozi789654/p/15706423.html
Copyright © 2011-2022 走看看