C#--运动控制--运动暂停思路--检测沿信号方法

以下是学习笔记:

1.思路分析:

【1.1】运动的两种方式:

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

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

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

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

 

 

 2,封装的运动控制方法

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

 

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

 

 

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

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#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】变量:

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

  

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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】检测沿信号的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/// <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;
        }
    }
}

  

  

 

  

 

posted @   包子789654  阅读(3990)  评论(5编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示