Switch on/off state timer with display

I am working on a device to test the function of a switch in a machine. The switch is activated by the machine and is supposed to change states around 900 times a minute.

I need to monitor the status of the switch and display some information I am using an Arduino UNO with a 2X16 LCD display.

The type of information I need is Longest/Shortest On Time (in Milliseconds) Longest/Shortest Off Time (in Milliseconds)

Any suggestions on code or some examples would be very helpful.



Well you can define some global variables like

byte onTimeMax = 0;
byte offTimeMax = 0;
byte onTimeMin = 255;
byte offTimeMin = 255;
unsigned long transitionTime;

Then in your loop you can do something like

static byte lastState = 0;
byte newState = digitalRead(inputPin);
if(newState != lastState)
  unsigned long newTransitionTime = millis(); // capture the time of the pin change event as quickly as possible
  if(newState == HIGH) // pin went from LOW to HIGH
    byte offTime = newTransitionTime - transitionTime; // see how many millis since the last time the pin changed
    if(offTime > offTimeMax)
      { offTimeMax = offTime; }
    else if(offTime < offTimeMin)
      { offTimeMin = offTime; }
  else // newState == LOW
    // left as exercise for the reader
  transitionTime = newTransitionTime;
  lastState = newState;
  // update LCD here

Only problem may be the LCD take many milliseconds to update, which will hurt the accuracy of your timers. This may be an argument for using interrupts.

Do you ever want to reset your max/min on/off timers? Or do you want a running window of the min/max on/off for the last 60 seconds?

Thank You

This looks great,

I think a 60 second window will work fine.

More detail on what I am doing
we have machines that make things out of wire. Pieces of wire are fed into the machine. when the piece of wire is in position it touches a steel roller. The wire touching the roller actually completes a circuit that starts a timer. If a connection is not made at least every second the machine will shut down. If there is an alignment problem and the piece of wire will fall out and never touches the roller, the machine will not run. The operator can tell if these pieces of wire fall out but since they are responsible for fixing this type of problem they get rid of the pieces and say it is an electrical problem and call me (maintenance).
I am hoping that I can monitor the connection and quickly tell if there are times that the wire never touches. If the wire never touches the roller it is not an electrical problem and therefor it is not my problem.

As far as the LCD being slow. I guess I really don’t need to display the times in real time or not at all for that matter.
I could just display Error Messages
while the machine is running the program watches the on/off times
If the switch stays on for more than 2 seconds - display “Always On” Meaning there might be an electrical problem.
If it doesn’t come on at all for more than 2 seconds - display “Never On” Meaning an alignment problem or mechanical.
If it doesn’t switch on and off at least 2 times per second - display “Dropping Wire” Meaning wire is not touching every time
If it turns on and off 3 or more times per second - display “Working Fine”

So, bad news. I did a test on my sketch and it took 12 milliseconds to update my LCD. Now, as long as the events you want to time happen less frequently than every 12 milliseconds, then you're fine and you won't miss any events.

If you need to time faster events, I think you still can, you just have to use interrupts so an event will interrupt the LCD display routine. Interrupts are quite feasible but hopefully you don't have to go there.

But, it will be simpler to just have the four messages you mention. You can still save the min/max on/off times in variables, and then display them if an error occurs.

If you want to save a 60-second sliding window history of times, in your loop, keep track of the min/max on/off times as usual. Then every 1000 millis(), store the min/max on/off times into a ringbuffer and reset the counters. I wrote some ringbuffer code for this thread: http://forum.arduino.cc/index.php?topic=186390.0 (the ringbuffer code is spread across a few posts, so read the whole thing). You'd need to define four ringbuffers (on max, on min, off max, off min) each 60 elements in length (you'd also want to use bytes rather than chars).

Note, I tend to use bytes rather than ints in my sketches as bytes take up half the RAM as ints. But if you need to measure intervals greater than 255 milliseconds (about a quarter of a second), you'll need to use ints. Four 60-int ringbuffers would consume 480 bytes, which should be fine (your Arduino has 2,048 bytes, of which about 1,536 is safe to use). An int will store an interval up to approx. 32 seconds long.