2

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.

acs
  • 235
  • 5
  • 16

2 Answers2

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.

James Waldby - jwpat7
  • 8,840
  • 3
  • 17
  • 32
  • 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 Jan 22 '17 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! – James Waldby - jwpat7 Jan 23 '17 at 00: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 Jan 23 '17 at 00: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? https://www.arduino.cc/en/Reference/attachInterrupt – acs Jan 23 '17 at 08: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. – James Waldby - jwpat7 Jan 23 '17 at 08:34
  • @jwpat7 This link says there are only 3 interrupt vector ==> http://playground.arduino.cc/Main/PinChangeInterrupt So, how did you do this possible? I couldn't find any solution. Please share your code. – acs Jan 25 '17 at 09:39
  • @acs, Are you unable to follow the links and look at other questions on Arduino stackexchange? In particular, see my answer to question 18183, linked in first line of answer above. That code handles 4 RC inputs and can be adapted for as many as there are pins for. ¶ Note, each of the 3 PCI vectors has 8 pins assigned to it. ISRs can read ports and figure out which bits changed. ¶ I have some 8-RC-inputs code (adaptation of that shown in answer to 18183) that I can post after some more work deadlines; a couple of days from now. – James Waldby - jwpat7 Jan 26 '17 at 00:42
0

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.

dannyf
  • 2,770
  • 10
  • 13