2

I apologize in advance that the title might be very confusing, but I wasn't sure how else to explain this due to my English issue.

I have a form application written in C# using VS2008, and it constantly reads data from an external device. The data read is either 0 (OFF) or 1 (ON). Most of the time, it stays 0, but when something occurs in the system, it becomes 1 and stays 1 for 5 seconds and goes back to 0.
What my program needs to do is to always watch the value change from 0 to 1, and count the number of the occurrences of catching the 1.

The problem is, sometimes the external device has a mistake and changes the value from 0 to 1 on accident for a second or less.

My program needs to ignore and not count the occurrence if the value change from 0 to 1 lasted for less than 1 second, and accept and count the occurrence if the value change from 0 to 1 lasted for 2 seconds out of the 5 seconds life.

I am thinking that basically I can just increment the count only if it stays 1 for more than 2 seconds, and do nothing otherwise. I tried to use Thread.Sleep(2000), but it does not work, and I don't think this is the right way, but I haven't found a solution to achieve this.

private int data; //will contain the data read from the ext. device
private int occurrence = 0; 
//Tick runs every 100 seconds
private void MyTick(object sender, EventArgs e)
{
    //if data becomes 1
    if(data == 1)      
    {
          Thread.Sleep(2000); //wait 2 seconds??? does not work
          //if the data stays 1 for 2 seconds, it is a valid value
          if(?????)
          {
              occurrence++; //count up the occurrence
          }
    }  
}

Can someone please give me some advice on what I can do to achieve this?

dymanoid
  • 14,771
  • 4
  • 36
  • 64
Mika Jones
  • 287
  • 1
  • 5
  • 13

1 Answers1

1

You can track the time point when the switch from 0 to 1 has been detected and then check the length of that time period.

Something like this:

private int occurrence; 
private int data;
private int previousData;
private DateTime? switchToOne;

private void MyTick(object sender, EventArgs e)
{
    if (data == 1 && previousData == 0) // switch detected
    {
        switchToOne = DateTime.Now; // notice the time point when this happened
    }

    // if the current value is still 1
    // and a switch time has been noticed
    // and the "1" state lasts for more than 2 seconds
    if (data == 1 && switchToOne != null && (DateTime.Now - switchToOne.Value) >= TimeSpan.FromSeconds(2))
    {
        // then count that occurrence
        occurrence++;

        // and reset the noticed time in order to count this occurrence
        // only one time
        switchToOne = null;
    }

    previousData = data;
}

Note that DateTime is not very accurate. If you need to perform very accurate time measurements, you will need to use Stopwatch. But since you're using a Timer (I'm inferring this from your event handler) which is not accurate anyway, I could suppose that the DateTime resolution will suit your needs.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • Thanks for the answer. I was wondering how this could be done without using a `Timer` control, because it keeps reading data. Does ValueChange event work in this case with the `Stopwatch` Control? – Mika Jones Oct 18 '17 at 15:49
  • 1
    I supposed that you use the `MyTick` event handler with a `Timer`. Do you use it with some `ValueChanged` event? (I don't know where this event comes from.) If so, then my solution will work anyway. – dymanoid Oct 18 '17 at 15:55
  • Yes your guess is correct, and MyTick is a `Timer` control (My bad for not mentioning that in the first place). I was just wondering why `Timer` is not a good idea to achieve what I want to achieve. – Mika Jones Oct 18 '17 at 15:58
  • It isn't a bad idea in general. It depends on the API that you use for accessing to the device's data. If the API doesn't provide any "push" access methods (e.g. events or callbacks), then you need to poll it somehow. The timer will do the job, but it isn't very accurate (the default timer resolution on Windows 7 is 15.6 ms). You could set it to e.g. 1 ms, but it will drain more battery for example. There is a [high resolution timer](https://stackoverflow.com/a/45097518/2846483) example too. – dymanoid Oct 18 '17 at 16:03