西门子PLC编码器数据读取异常:两个文本框数值一致
解决西门子PLC编码器数据时间节点读取重复问题
问题背景
- 硬件配置:编码器与西门子PLC相连,对应数据块为
DB1.DBD56 - 异常现象:两个文本框
txtbefore和txtafterWeld显示的编码器数值完全相同 - 需求目标:分别读取1秒前和1秒后的编码器数值
问题根源分析
现有代码中,Read_Before和Read_After方法直接复用同一个变量convertTomm——这个变量存储的是当前最新的编码器转换值,没有单独保存1秒前的历史数据,导致两个文本框始终显示相同数值。同时缺少明确的时间节点触发逻辑,无法实现“1秒间隔读取”的要求。
解决方案
1. 添加历史值存储变量
在类的成员区域定义变量,专门保存1秒前的编码器数值:
private double _previousEncoderValue = 0;
2. 实现1秒间隔的时间触发逻辑
假设timer_OneCycleProcess是用于控制时间间隔的计时器(需将其Interval属性设置为1000即1秒),修改其Tick事件处理方法:
private void timer_OneCycleProcess_Tick(object sender, EventArgs e) { try { if (plc_s7_1200.IsConnected) { // 读取PLC中编码器的原始值并转换为毫米(复用原有转换逻辑) double rawEncoderValue = Convert.ToDouble(plc_s7_1200.Read("DB1.DBD56")); convertTomm = rawEncoderValue; // 假设convertTomm是已实现的毫米转换变量 // 首次触发:记录1秒前的初始值 if (_previousEncoderValue == 0) { _previousEncoderValue = convertTomm; txtbefore.Text = string.Format("{0:0.0}", _previousEncoderValue); } else { // 1秒后:读取当前值并更新文本框 txtafterWeld.Text = string.Format("{0:0.0}", convertTomm); // 重置变量,准备下一次周期读取 _previousEncoderValue = 0; timer_OneCycleProcess.Stop(); } } } catch (Exception ex) { MessageBox.Show("读取编码器数据出错: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
3. 调整状态触发计时器逻辑
修改timer_anvilState_Tick方法,确保在触发读取周期前重置历史值:
private void timer_anvilState_Tick(object sender, EventArgs e) { try { bool anvilState = (bool)plc_s7_1200.Read("DB1.DBX68.4"); if (plc_s7_1200.IsConnected) { if (anvilState == true) { // 启动读取周期前重置历史值,避免旧数据干扰 _previousEncoderValue = 0; timer_OneCycleProcess.Start(); } else { timer_OneCycleProcess.Stop(); command = "IDLE"; } } // 保留原有业务逻辑调用 Edata_convertion(); read_lastweld_result(); } catch (Exception ex) { MessageBox.Show("请检查PC与PLC连接: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
4. 简化原读取方法(可选)
如果仍需保留Read_Before和Read_After方法,可修改为基于存储的历史值更新:
#region READ BEFORE public void Read_Before() { txtbefore.Text = string.Format("{0:0.0}", _previousEncoderValue); } #endregion #region READ AFTER public void Read_After() { txtafterWeld.Text = string.Format("{0:0.0}", convertTomm); } #endregion
关键注意事项
- 必须使用独立变量存储历史值,禁止直接复用当前读取的实时值
- 确保
timer_OneCycleProcess的Interval属性设置为1000毫秒,保证两次读取的时间差为1秒 - 每次启动读取周期前重置历史值,避免上次周期的残留数据影响结果
内容的提问来源于stack exchange,提问作者GMK
相关产品推荐
相关产品推荐

