I am working on comparing autopilots like Ardupilot, CC3D, KK2.1.5. The comparision is about system reactions/behaviors that it gives during flight. For this purpose, I need to read the PWM duty cycle (like osilascopes - the PWM frequency can be vary from 50 to 430 Hz) values from autopilot card. There are 4 command input PWMs and 4 esc control PWMs for a typical quadrotor. I have to read 8 duty cycle values with digital/analog input pins. How do I measure duty cycle of 8 PWM signals? Also, is digital or analogue measurement precise and faster?

Note about attachInterrupt command: According to arduino.cc AtMega328 series have 2 interrupts, Arduino ATmega 2560 series have 7 interrupts.

2 Answers 2


The code shown in my answer to question 18183, “Read RC receiver channels using Interrupt instead of PulseIn”. That answer has code to read four channels of RC PWM. It can easily be adapted to work with eight channels. It has an ISR that runs when selected pins change. It sorts out which channel(s) changed, and stores the value of micros() at each change.

Also see my answer to question 19106, “Can external interrupts be OR'd together on the '328 (Uno)?” That answer includes a sketch for generating appropriate ISR code. My answer to question 32572, “How to detect the direction of a rotary encoder?”, shows another instance.

Digital input, as used in the code mentioned above, takes under a microsecond ten microseconds in the ISR. As noted in dannyf's comment, unrolling the for loop and (where possible) using constants instead of variables can reduce the in-ISR time to 3.4 μs. Note, ISR entry and exit still add several microseconds.

10-bit analog input, on the other hand, will take around 104 microseconds per reading, a time comparable to some of the pulse widths you'll be measuring. So it isn't fast enough. If degraded ADC accuracy is acceptable, decreasing the ADC-clock scale factor as explained in a webpage at microsmart.co.za can get AD conversion time down to 20 μs. This is around three times as long as digital input takes, so rather slow.

  • > takes under a microsecond in the ISR, I find that unlikely. Obviously, I'm not sure which code pieces you were talking about - as they are three of them. but a causal look on them would suggest that it will take more than 16 ticks to execute the body of the ISR - not counting the overhead. As a matter of fact, a little birdie of mine said that it would take close to 8us to execute them on an Uno, :)
    – dannyf
    Commented Jan 22, 2017 at 22:20
  • @dannyf, I was looking at one of the simpler ISRs (single encoder counting) when I wrote that, so will need to edit answer with correct time. Sorry! Commented Jan 23, 2017 at 0:18
  • not a problem. two suggestions: 1) unroll the while loop; 2) use constants rather than variables. and I would also make rcOld a static inside the ISR so the code is more modular. with that, I got the execution time down to 3.4us.
    – dannyf
    Commented Jan 23, 2017 at 0:36
  • Can you share your code instead of links. Also, AtMega328 series have 2 interrupts, Arduino ATmega 2560 series have 7 interrupts. So how can I measure 8 simultaneus PWM signals? arduino.cc/en/Reference/attachInterrupt
    – acs
    Commented Jan 23, 2017 at 8:00
  • 1
    @acs, ATmega328's have 26 different interrupt vectors. The vectors used in the referenced code are for pin change interrupts, or PCINTs, which use 3 of those vectors. PCINTs are available on 22 of the ATmega328-based-Nano pins, and a similar number on Uno's. Please refer to the code shown in the previous questions -- at the moment I have work deadlines to meet. Commented Jan 23, 2017 at 8:34

if done in analog, run the pwm through a lpf and perform an adc on the output;

if done in digital, use a timer's capture function, or use external interrupt / pin change interrupt to capture the timing off a time base.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.