获取图表上达到目标(上方)和退出目标(下方)之间的时间
Get time between reaching target (above) and exiting target (below) on chart
下表每秒使用 winforms 计时器更新其值。红线表示恒定的目标测试压力,蓝线是从 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 中给了我一个误导性的答案(33 秒,你可以在图表上看到已经过去了 5 秒)并且在第一次将 tickCounter 分配给之后, aboveReq 日期时间戳不想更改。
有没有更好的方法来实现这个目标?我做错了吗?我应该提供更多详细信息吗?
我不得不假设您有多个名为 "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;
}
----------------------------编辑---------------- ----------------------
Am I going about it wrong?
如果您将压力监控逻辑移至单独的 class,将被认为更清洁,从而保持单一责任原则。
您可以通过实施压力监控 class 来做到这一点,该监控会在违反阈值时引发事件 - 类似于 -
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;
}
}
然后在你的主要class你会有字段
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;
}
并且在构造函数中您将订阅观察者 class
_pressureObserver = new PressureObserver(60); //replace 60 with threshold
_pressureObserver.OnRaisedAboveThreshhold += Obs_OnRaisedAboveTreshhold;
_pressureObserver.OnFellBelowThreshhold += Obs_OnFellBelowTreshhold;
在你的滴答计时器中你只需添加
_pressureObserver.Observe(plcTestpressure);
下表每秒使用 winforms 计时器更新其值。红线表示恒定的目标测试压力,蓝线是从 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 中给了我一个误导性的答案(33 秒,你可以在图表上看到已经过去了 5 秒)并且在第一次将 tickCounter 分配给之后, aboveReq 日期时间戳不想更改。
有没有更好的方法来实现这个目标?我做错了吗?我应该提供更多详细信息吗?
我不得不假设您有多个名为 "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;
}
----------------------------编辑---------------- ----------------------
Am I going about it wrong?
如果您将压力监控逻辑移至单独的 class,将被认为更清洁,从而保持单一责任原则。
您可以通过实施压力监控 class 来做到这一点,该监控会在违反阈值时引发事件 - 类似于 -
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;
}
}
然后在你的主要class你会有字段
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;
}
并且在构造函数中您将订阅观察者 class
_pressureObserver = new PressureObserver(60); //replace 60 with threshold
_pressureObserver.OnRaisedAboveThreshhold += Obs_OnRaisedAboveTreshhold;
_pressureObserver.OnFellBelowThreshhold += Obs_OnFellBelowTreshhold;
在你的滴答计时器中你只需添加
_pressureObserver.Observe(plcTestpressure);