在图表上达到目标(上方)和退出目标(下方)之间的时间

问题描述 投票:1回答:1

下面的图表每秒使用一个winforms Timer更新其值。红线表示恒定的目标测试压力,蓝线表示从PLC对象读取的实际压力。

Y Axis = Testing Pressure, X Axis = Current Time, chart is updated with winforms timer at Interval = 1000 (every second)

要求显示蓝线达到恒定的所需测试压力(红线)和低于标准值之间经过了多少秒 不断要求的测试压力。

设置常量所需测试压力的块:

...
        chart1.ChartAreas[0].CursorY.Position = d;
        chart1.ChartAreas[0].CursorY.LineWidth = 1;
        chart1.ChartAreas[0].CursorY.LineColor = System.Drawing.Color.Red;

我被卡住的部分(这个块在每秒更新图表的方法内):

                                                                        double plcTestpressure = ((uint)plc.Read("MD220")).ConvertToDouble();
                    double reqTestPressure = Convert.ToDouble(txtTestingPressure.Text);

                    if (plcTestpressure > reqTestPressure && !isAboveReq)
                    {
                        DateTime aboveReq = new DateTime();
                        aboveReq = DateTime.Now;
                        isAboveReq = true;
                        //this is for checking the plc read pressure
                        string currentpressure = ((uint)plc.Read("MD220")).ConvertToDouble().ToString();
                    }
                    //check if current pressure is below required and that pressure WAS above required a second ago...
                    if(plcTestpressure < reqTestPressure && isAboveReq)
                    {
                        DateTime belowReq = new DateTime();
                        belowReq = DateTime.Now;                    
                        tickCounter = (belowReq - aboveReq).TotalSeconds;
                        isAboveReq = false;
                    }

我已尝试并逐步完成此块,但它在tickCounter中给出了一个误导性的答案(当你可以在图形上看到5秒钟时可以看到33秒)并且在第一次分配tickCounter之后,上面的req日期时间戳确实不想改变。

有没有更好的方法来实现这一目标?我错了吗?我应该提供更多细节吗?

c# winforms plc
1个回答
0
投票

我必须假设您有多个名为“aboveReq”的变量,因为在“if”块中声明的变量是块的本地变量。这意味着当您访问第二个“if”块中的“aboveReq”变量时,您不会访问同一个变量。

string currentpressure = ((uint)plc.Read("MD220")).ConvertToDouble().ToString();真的需要在if块内(仅在跟踪目标时跟踪当前压力)吗?

//Outside of method, top of class
private DateTime? _startTime = null;
private DateTime? _endTime = null;

//In method
 string currentpressure = ((uint)plc.Read("MD220")).ConvertToDouble().ToString();

 bool breachPressure = plcTestpressure > reqTestPressure;

 if (breachPressure && _startTime == null)
 {
    _startTime = DateTime.Now;
 }
 else if(!breachPressure && _startTime != null)
 {
    _endTime = new DateTime();
    var tickCounter = _endTime.Value.Subtract(_startTime.Value).TotalSeconds;
 }

- - - - - - - - - - - - - - -编辑 - - - - - - - - - - -------------------

我错了吗?

如果将压力监测逻辑移到一个单独的类中,那么它将被认为是更清晰的,从而保持单一责任原则。

你可以通过实施一个压力监控类来实现这一点,该类可以在违反阈值时引发事件 - 类似于 -

        public class PressureObserver
        {
            public event EventHandler<double> OnRaisedAboveThreshhold;
            public event EventHandler<double> OnFellBelowThreshhold;

            public double ThresholdPressure{ get; }

            private double _lastMeasured = 0; //Initial Pressure

            public PressureObserver(double thresholdPressure)
            {
                ThresholdPressure = thresholdPressure;
            }

            public void Observe(double plcTestpressure)
            {
                double pressureDelta = plcTestpressure - _lastMeasured;

                if (pressureDelta > 0) //Pressure climbed
                {
                    if(_lastMeasured < ThresholdPressure &&  //Last measurement was below threshold
                        plcTestpressure > ThresholdPressure) //This one is above, cross made
                    {
                        OnRaisedAboveThreshhold?.Invoke(this, plcTestpressure);
                    }
                }
                else if(pressureDelta < 0) //Pressure declined
                {
                    if (_lastMeasured > ThresholdPressure &&  //Last measurement was above threshold
                        plcTestpressure < ThresholdPressure) //This one is below, cross made
                    {
                        OnFellBelowThreshhold?.Invoke(this, plcTestpressure);
                    }
                }

                _lastMeasured = plcTestpressure;
            }
        }

然后在你的主要课程中你会有字段

        private PressureObserver _pressureObserver;
        private DateTime _raisedAboveTime;
        private DateTime _fellBelowTime;
        private double _overpressureDuration;

您将定义两种方法来响应阈值更改

        private void Obs_OnRaisedAboveTreshhold(object sender, double e)
        {
            //Code to do on raised above
            _raisedAboveTime = DateTime.Now;
        }

        private void Obs_OnFellBelowTreshhold(object sender, double e)
        {
            //Code to do on fell below
            _fellBelowTime = DateTime.Now;
            _overpressureDuration = _fellBelowTime.Subtract(_raisedAboveTime).TotalSeconds;
        }

在构造函数中,您将订阅观察者类

       _pressureObserver = new PressureObserver(60); //replace 60 with threshold

       _pressureObserver.OnRaisedAboveThreshhold += Obs_OnRaisedAboveTreshhold;
       _pressureObserver.OnFellBelowThreshhold += Obs_OnFellBelowTreshhold;

在你的滴答计时器你只需要添加

_pressureObserver.Observe(plcTestpressure);
© www.soinside.com 2019 - 2024. All rights reserved.