Analog rising and falling edge detect and interrupt on Arduino DUE

Based on ard_newbie suggestion on Analog interrupt - Arduino Due - Arduino Forum I wrote a small test for detect and generate an interrupt on both rising and falling edge of a analog input signal on Arduino DUE as following, but it does not work and always generated two interrupts dispite what is happening on corresponding analog signal... A big headache for me !!!

volatile boolean Look_for_Rising=true; // thru is looking for rising/false is looking for falling

void setup() {
  Serial.begin(115200);
  adc_setup();
}

void loop() {
}

void adc_setup ()
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID37;                    // ADC power ON
  ADC->ADC_WPMR = 0x41444300;                           // Disable write protect 
  ADC->ADC_CR = ADC_CR_SWRST;                           // Reset ADC
  ADC->ADC_MR |= ADC_MR_FREERUN_ON                      // ADC in free running mode
                 | ADC_MR_LOWRES_BITS_12                // 12 bits resolution
                 | ADC_MR_PRESCAL(1)
                 | ADC_MR_SETTLING_AST3
                 | ADC_MR_TRACKTIM(10)
                 | ADC_MR_TRANSFER(2);

  ADC->ADC_EMR = ADC_EMR_CMPMODE_OUT                    // Generates an event when the converted data is out of the comparison window.
                 | ADC_EMR_CMPSEL(0)                    // Compare channel 0 = A7
                 | ADC_EMR_CMPFILTER(0);                // Number of consecutive compare events necessary
                                                        // to raise the flag = CMPFILTER+1

  ADC->ADC_CWR = ADC_CWR_LOWTHRES(0) | ADC_CWR_HIGHTHRES(2047); // at begin, looking for rising
  
  ADC->ADC_CHER = ADC_CHER_CH0;                         // Enable Channel 0 = A7
  ADC->ADC_IER = ADC_IER_COMPE;                         // Interrupt on Compare match enable
  NVIC_EnableIRQ(ADC_IRQn);                             // Enable ADC interrupt
}

void ADC_Handler() {
  ADC->ADC_ISR; // Read and clear status register

  // print what kind of interrupt is this 
  // 1=found Rising edge; 0=found Falling edge 
  Serial.println(Look_for_Rising); 
  
  Look_for_Rising=!Look_for_Rising; // invert what to looking for
  
  if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(4095) | ADC_CWR_HIGHTHRES(2048);} // looking for falling
  if (Look_for_Rising) {ADC->ADC_CWR = ADC_CWR_LOWTHRES(0)    | ADC_CWR_HIGHTHRES(2047);} // looking for raising
}

What is the amplitude of the analog input signal ?

ard_newbie:
What is the amplitude of the analog input signal ?

Exactly 0 ~ 3.3v i.e. 0 ~ 4095 after adc convertion.

So why don't you use a digital pin and an attachInterupt() on Rising edge or falling edge or both ?

ard_newbie:
So why don't you use a digital pin and an attachInterupt() on Rising edge or falling edge or both ?

This is a osciloscope project. So I need to detect a variety of analog rising/falling and trigger level...

As soon as you get a trigger, you need to disable interrupts until you have captured your scope waveform, otherwise you can get multiple triggers which could be an issue.

weird_dave:
As soon as you get a trigger, you need to disable interrupts until you have captured your scope waveform, otherwise you can get multiple triggers which could be an issue.

Yes yes weird_dave... For sure. But the problem is that I could not get the trigger yet :frowning:

ard_newbie:
What is the amplitude of the analog input signal ?

Hello ard_newbie... How did you ask this question ? Would be it related with my problem ? Anyway the analog signal is located between 0 and 3.3v. Thanks

I'm not sure if this is valid:

if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(4095) | ADC_CWR_HIGHTHRES(2048);} // looking for falling

The lower threshold is higher the the high, I would swap those numbers and see if that improves the situation.

weird_dave:
I'm not sure if this is valid:

if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(4095) | ADC_CWR_HIGHTHRES(2048);} // looking for falling

The lower threshold is higher the the high, I would swap those numbers and see if that improves the situation.

Yes. I did the swap to garantee lowthres always less than highthres but result was the same :frowning:

if (!Look_for_Rising){ADC->ADC_CWR = ADC_CWR_LOWTHRES(2047) | ADC_CWR_HIGHTHRES(4095);} // looking for falling
  if (Look_for_Rising) {ADC->ADC_CWR = ADC_CWR_LOWTHRES(0)    | ADC_CWR_HIGHTHRES(2046);} // looking for raising

After many burned neuronium and a lot of tests the solution was found. Simple move the command ADC->ADC_ISR; (Read and clear status register) to the end of interrupt handler routine !!! It seams that if the status register was read at begining, something lock and nothing else happens...