2

I am making a small project, and for that, I need to measure the time between 2 inputs. basically, a program to measure the time elapsed from when digital pin 2 is high to when it again becomes high.

asked Dec 30, 2020 at 9:35
1
  • Have you seen the millis() function and the time measurement in the BlinkWithoutDelay example? There are lots of tutorials about millis() on the web Commented Dec 30, 2020 at 10:16

2 Answers 2

3

The way to go depends on the time range, that the event will have. The Arduino framework already includes a function for timekeeping: millis(). It returns the number of milliseconds since the startup (much like a clock) and measures the time via the hardware Timer0 and it's interrupts. This function will work good in the 2 digit millisecond range and above. With single digit millisecond or the microsecond domain, you should instead use micros() with works similar, but returns the microseconds since startup. For the low microsecond range and below you would need to work directly with a dedicated hardware timer, configuring it via its hardware registers.

Here I would show the principle of millis()/micros(), since that is most likely what you need. In the following I will only write millis(), but all the calculations can also be done with micros(). The only difference for the calculations is the factor 1000 between milli- and microseconds.

When you look at your watch and want to measure a time difference, you take note of the start time and the end time. Then you calculate the difference to get the event duration. You can do the same with millis():

unsigned long starttime = millis(); // take note of start time
// here the event to measure
unsigned long endtime = millis(); // take note of end time
unsigned long duration = endtime - starttime; // duration of the event in ms

So in your code you need to check for a rising edge of your signal. On every rising edge you calculate the time difference between the last timestamp and the current time. Then you reset the timestamp. Something like this:

int last_input_state = LOW;
unsigned long timestamp;
//setup here
void loop(){
 int current_input_state = digitalRead(2); // get current signal level
 if(current_input_state && !last_input_state){ //check, if signal is now high and was low before
 unsigned long current_time = millis(); // take note of the current time
 unsigned long duration = current_time - timestamp; // calculate the duration and do something with it
 timestamp = current_time; // update the timestamp with the current time
 }
 last_input_state = current_input_state; // update the last input state with the new measured one
}

Note:

  • This code is non-blocking. It needs to run fast and continuously to work correctly. You cannot do long blocking things in the rest of your code, like using high delay() calls, but you shouldn't do that either way, since that will block anything from going on.
  • You can go even further to lift the weight from your CPU and use an interrupt to sense the rising edge. You could use attachInterrupt(digitalPinToInterrupt(pin), service_function, RISING); and provide a void service_function(), which does the timestamp measurement and calculation (basically the same code as in the if statement of the code above).
answered Dec 30, 2020 at 11:43
1

You could do something like this:

unsigned long startTime;
unsigned long elapsedTime;
// Any needed setup stuff
void setup()
{
 ...
}
void loop()
{
 // Wait for input to go high
 while(digitalRead(2) == LOW);
 // Start timing
 startTime = millis();
 // Wait for input to go low
 while(digitalRead(2) == HIGH);
 // Now wait for it to go high again
 while(digitalRead(2) == LOW);
 // Now get the time interval
 elapsedTime = millis() - startTime;
 // Do whatever with the result.
 ...
}

Keep in mind that the millis() value will overflow every 50 days or so. If you need to run this continuously, you need to check for an overflow and adjust things accordingly.

answered Dec 30, 2020 at 11:26
4
  • elapsedTime = millis() - startTime; even works well while millis passes 0 on "overflow". Nothing to adjust. Commented Dec 30, 2020 at 17:16
  • Altough working with millis(), this is a blocking example, due to the while statements. (Even worse that the Arduino pulseIn function, which has a timeout) Commented Dec 30, 2020 at 17:19
  • I did not see any requirement to do anything but measure the interval. Therefore a blocking solution is ok. Why complicate it if it's not needed? As is so often the case, there are many many possible solutions. Commented Dec 30, 2020 at 17:49
  • So one should compare your solution to standard pulseIn. Commented Dec 31, 2020 at 11:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.