Seeking guidance on PulseIn vs PulseInLong

Hi, folks.


(If you want, you can skip this lengthy background explanation and go directly to my questions below - which are also lengthy. :wink: )

I am working on a project to control a quartz analogue wall clock from a microcontroller. I know this has been done countless times, but I have some ideas to incorporate that I have not seen used in others’ projects.

Part of the development is the need to charactarise the circuit board module internal to the clock’s movement, in order to tweak parameters of both the hardware and software of the final project (which parameters are dependent on the specific clock motor coil being driven by the micro). One of the characteristics needed is the pulse width that the clock circuit module delivers to the clock motor coil, which can be different for different quartz wall clocks.

I have one of those cheap DSO 138 “Oh So Sillly Scopes” ; ), that is quite adequate to measure this for myself. But my intent is to eventually publish the project, and other builders or makers duplicating the project may not have a scope to measure the pulse width for their own clocks.

So, I want to write a “tool” sketch (for UNO or NANO) that will help characterise the pulse train outputs from the quartz clock circuit module. In addition to measuring the “active” pulse width, it would also be nice (but not absolutely essential) to be able to accurately measure the pulse train period (which should be 2 seconds). My intent is to use this tool software to measure several cycles of pulses, reporting the width and period of each cycle, and the minimum, maximum, and arithmetic mean of the pulse widths and pulse periods.

Just today, I discovered the Arduino PulseIn and PulseInLong library functions, described in the Arduino reference pages, which may be useful for this measurement tool software.


The reference descriptions of PulseIn and PulseInLong indicate that PulseIn may be more suitable to measure “shorter” pulse widths, and PulseInLong for “longer” (or “larger”) widths. Perhaps I missed it, but there does not seem to be any quantitative value given for “longer” (or “larger”). So …

Question 1: For exactly what ranges of pulse width measurements should each of these function (PulseIn and PulseInLong) be used for best accuracy?


As mentioned near the end of my Background description above, it would be nice to be able to accurately measure the total pulse train period, in addition to the “on-time” pulse width (although this is not absolutely essential to my project). I am wondering if it is possible to measure both the pulse width of one pulse, AND the time until the next pulse’s leading edge, using PulseIn (or PulseInLong, as the case may be). My understanding is that these functions are “edge triggered,” so once the trailing edge of the “on-time” has occurred to complete the measurement of the active “on-time” pulse width, it is too late to start timing the “off-time” pulse-width to the leading edge of the next pulse. (Is my understanding correct?) So …

Question 2: Is it possible to use PulseIn or PulseInLong to measure BOTH the pulse width AND the total cycle time of the same pulse cycle? Is it possible to simultaneously invoke two instances of the function to measure BOTH the “high” state width AND the “low” state width of the same pulse cycle? (I expect that PulseInLong is not capable of doing this, since it seems to be interrupt driven, and only one interrupt edge trigger can be defined for an input.) Another possible solution is to feed the pulse train to TWO inputs of the Arduino, and use one to measure the “active” width and the other the “inactive” width. Would that work?

Thanks for your help and insights, folks.

Oh rats.

Regarding Question 2, of course the function cannot be simultaneously invoked twice, because each individual call to PulseIn (or PulseInLong) is blocking; i.e. the function does not return until the end of the measurement of a pulse width. :frowning_face:

It would probably just be easier to write my own interrupt-driven software and avoid using PulsIn(Long) altogether. The ISR would just toggle between detecting rising and falling edges. But then, would the time reported by micros() be affected by interrupts?

So, new question: If the mode parameter of the attachInterrupt() function is set to CHANGE, is the resulting interrupt set up for edge or level triggering?

No. By the time you finish measuring the HIGH part of the cycle by seeing the pin go LOW it it too late to start measuring the LOW part of the cycle by seeing the pin go low.

Edge. Either RISING or FALLING edge. Either is a CHANGE.

The interrupts could be delayed… BUT, if you use the Input Capture pin, the time the interrupts WOULD have happened is stored in the Input Capture Register. The UNO has one Input Capture pin (Pin 8) for Timer/Counter1. The MEGA has at least two.

Thank you for your replies, John.

Yes, I answered that question for myself and also realised that I cannot start two, simultaneous instances of pulseIn (or pulseInLong). (See #2 in this thread.)

Thinking about it a bit more, I do not think that level of accuracy is required for this specific application. The pulse width of these clock circuit modules is generally about 20 to 50 milliseconds, and the period should be exactly 2 seconds. So I expect that inaccuracies due to interrupt latency would be negligible. So, I think it should be okay to just read the micros() function return in the regular INT0 and INT1 ISRs. That way, I don’t have to mess with the Timer1 registers in my sketch code.