PWM Pin Interrupts on Due

Hi everyone! I'm trying to read some PWM signals off a radio receiver using a Due.

My oscilloscope says I'm around 55Hz, with a VMax of 3.3v, which matches the logic level of the Due.

My code is here.

Here's a picture of the wiring.

Very simple, signal wire to pin. Shared ground. The pins coming off are for the oscilloscope.

I've added a few debug messages here and there and it looks like the interrupts are not being called at all. Any ideas?

For each attachInterrupt(PinInterrupt, ...., CHANGE), you should have in setup():

pinMode(PinInterrupt, INPUT_PULLDOWN) so that the Px PIO peripheral is activated and the Pull Down will be most useful to avoid EMI.

Test firstly with a single attachInterrupt(), then 2,........ step by step.

BTW, why are you triggering an interruption on CHANGE rather than HIGH ? That is twice the number of useful interruptions. The more you have interruptions in your code, the more it runs slowly.

Radio PWMs only have useful information for the duration of HIGH, so to get the correct duty, I have to measure micros() from HIGH to FALLING.

If I'm wrong in that, please let me know.

I'll give it a try with your suggested modifications.

The Arduino Due does not have INPUT_PULLDOWN. I added a manual 1k pulldown resistor. No change in results for Channel 1.

I already have pinMode setup in the for loop, so I’m not sure it’s that.

I suspect an issue with all your struct channel. Once you have defined :

struct channel …

Then declare

channel MyChannel;

Here is an example sketch to work with an basic attachInterrupt() triggered by a PWM:

/*                Hook a jumper between pin 24 and pin 2           */
/*            Hook a 100 K resistor between pin 24 and Ground      */ 

void ISR1() {
static uint32_t Count;
   if (Count++ == 125000) { // MCK/2/TC_RC
    Count = 0;
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;   // Toggle LED with a 1 Hz frequency

void setup() {
  pinMode(24, INPUT);
  /*************  Timer Counter 0 Channel 0 to generate PWM pulses thru TIOA0  ************/
  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                      // TC0 power ON - Timer Counter 0 channel 0 IS TC0


  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC        // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR          // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;           // Set TIOA0 on RC compare match

  TC0->TC_CHANNEL[0].TC_RC = 336;//<*********************  Frequency = (Mck/2)/TC_RC  Hz
  TC0->TC_CHANNEL[0].TC_RA = 1;//<********************   Duty cycle = (TC_RA/TC_RC) * 100  %

  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable

  attachInterrupt(24, ISR1, RISING);

void loop() {


Cool, with your example I've determined the problem is actually the receiver, which has an actual VMax of 3.1v, which is not triggering the interrupt.

From this, I take it I need to just hook up a bipolar transistor and do a logic level shift from 3v to 3.3v.

Very odd, I thought all mainstream RC receivers ran at 3.3v already..