detachInterupt() from the inside of the interupt function?

Hi

I would like to read to IO banks (data d0-d7, RS and RW from an Device with an LCD display) on the falling edge of the enable pin for a certain number of times. → And then convert the data string and look for certain characters to read out data to a seperate Arduino.

My idea was to call detachInterupt() inside my interupt routine. But this doesent seem to work as the interupt stays attached and the while loop in the main function does not break.
Is there a way to make this work or to call my interupt routine enCha only bufLen times directly?

const int en = 3; // Interupt Pin

byte data = 0;
byte cont = 0;

char dArr[100] = {};

int bufLen = 10;//Number of times to call interupt routine
int i = 0;

bool interuptFlag = false; // Indicate if interupt is still activ

//Interupt function on falling enable pin
void enCha()
{
  //Read Ports
  data = PINA;
  cont = PINB;

  if ((cont << 6) == 0b10000000)
  {
    dArr[i] = char(data);
    i++;
    if (i > bufLen)
    {
      interuptFlag = true;
      i = 0;
      detachInterrupt(en); //Does NOT detach????
    }
  }
}

void setup()
{
  Serial.begin(2000000);
}

void loop()
{
  attachInterrupt(digitalPinToInterrupt(en), enCha, FALLING); //Interupt on falling edge
  while (interuptFlag == false) {}; // Does NOT exit loop ever (???)

  //Print data
  String bufStr(dArr);
  Serial.print(bufStr);
}

Thank you so much for your help in advance!

How about immediately returning from the ISR if it has been called the requisite number of times ?

Incidentally, i should be declared volatile.

The loop() could run fast enough to read every data byte, so perhaps a buffer is not needed. Perhaps a counter could be added to detect a missing byte. If the data is not needed, it is okay to let the interrupt still be active.

Thanks to both of you :slight_smile:

Incidentally, i should be declared volatile.

Well it doesnt change if I set the i volatile. But it puts out a part of the data when I put the interuptFlag volatile.
Still, it misses some data. I guess the if(i > bufLen) statement adds to much delay :frowning: ? The enable period is about 1.1ms so that should work...

How about immediately returning from the ISR if it has been called the requisite number of times ?

What do you mean by returning from the ISR immediatly?

The loop() could run fast enough to read every data byte, so perhaps a buffer is not needed. Perhaps a counter could be added to detect a missing byte. If the data is not needed, it is okay to let the interrupt still be active.

Hmm... I'll try that as well.

detachInterrupt(en); //Does NOT detach????

I don't think this is not correct syntax. What Arduino are you using?

With this setup

const int en = 3; // Interupt Pin
attachInterrupt(digitalPinToInterrupt(en), enCha, FALLING); //Interupt on falling edge

Try

detachInterrupt(1);

Arduino 1.8.5 on a 2560 Mega

Yes, you are right. I see that this syntax is valid for the DUE only.

detachInterrupt(1);

Does works with en as well sinse en is just an const int … But thank you it makes more sense like this.

The code below seems to work well. Volatile interruptFlag seemed to do the trick.
Thank you all very much!

const int en = 3; // Interupt Pin

byte data = 0;
byte cont = 0;

char dArr[100] = {};

int bufLen = 20;//Number of times to call interupt routine
int i = 0;

volatile bool interuptFlag = false; // Indicate if interupt is still activ

//Interupt function on falling enable pin
void enCha()
{
  //Read Ports
  data = PINA;
  cont = PINB;

  if ((cont << 6) == 0b10000000)
  {
    dArr[i] = char(data);
    i++;
    if (i > bufLen)
    {
      interuptFlag = true;
      i = 0;
      detachInterrupt(1);
    }
  }
}

void setup()
{
  Serial.begin(2000000);
}

void loop()
{
  attachInterrupt(digitalPinToInterrupt(en), enCha, FALLING); //Interupt on falling edge
  while (interuptFlag == false) {}; 

  //Print data
  String bufStr(dArr);
  Serial.println(bufStr);

  //Reset
  interuptFlag = false;
}

bufLen must also be declared volatile as well as i.

You could also do this

detachInterrupt(digitalPinToInterrupt(en));

Pete

What do you mean by returning from the ISR immediatly?

At the start of the ISR

if (weHaveDoneThisEnoughTimes)
{
  return;  //don't execute the code in the ISR
}

UKHeliBob:
At the start of the ISR

if (weHaveDoneThisEnoughTimes)

{
  return;  //don't execute the code in the ISR
}

Dam, I was to fixed on the problem. This is much better.