new problem with start/stop interrupts with IntervalTimer

Status
Not open for further replies.

NikoTeen

Well-known member
[solved] new problem with start/stop interrupts with IntervalTimer

Hi,
I declared my old post on "start/stop interrupts with IntervalTimer" as solved.
But now there is a new problem. The following code of a test sketch describes it.
Code:
// Create an IntervalTimer object 
IntervalTimer myTimer;

const int ledPin = LED_BUILTIN;  // the pin with a LED
elapsedMicros blinkPrint=0;
uint16_t looping=0;

// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
volatile unsigned long blinkCount = 0; // use volatile for shared variables
volatile  boolean  LEDon=true;

byte isr_disen =0;

void setup() {
  // put your setup code here, to run once:

  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  
  myTimer.begin(audio_interrupt, 50000);  // audio_interrupt to run every 50 ms

  Serial.print("setup: myTimer=");Serial.println(myTimer);
}

/* interrupt function called by IntervalTimer
    functions called by IntervalTimer should be short, run as quickly as
    possible, and should avoid calling other functions if possible.*/
void audio_interrupt(void) {
  if (LEDon) {
      digitalWrite(ledPin,1);
      blinkCount = blinkCount + 1;  // increase when LED turns on
  }
  else {
      digitalWrite(ledPin,0);
  }

  LEDon = !LEDon;
}

void IntOn(IntervalTimer actTimer) {
  NVIC_ENABLE_IRQ(actTimer);
  Serial.print("enable ");Serial.println(actTimer);
}

void IntOn2(void) {
  NVIC_ENABLE_IRQ(myTimer);
}

void IntOff(IntervalTimer actTimer) {
  NVIC_DISABLE_IRQ(actTimer);
  Serial.print("disable ");Serial.println(actTimer);
}

void IntOff2(void) {
  NVIC_DISABLE_IRQ(myTimer);
}

void loop() {
 
  unsigned long blinkCopy;  // holds a copy of the blinkCount

  // to read a variable which the interrupt code writes, we
  // must temporarily disable interrupts, to be sure it will
  // not change while we are reading.  To minimize the time
  // with interrupts off, just quickly make a copy, and then
  // use the copy while allowing the interrupt to keep working.
  
  delay(50);
  if (blinkPrint > 1000000) { // every second
    blinkPrint = 0;
    
    noInterrupts();
    blinkCopy = blinkCount;
    interrupts();
    Serial.print("blinkCount = ");
    Serial.print(blinkCopy);
    
    Serial.print("  isr_disen=");Serial.println(isr_disen); 
    if (isr_disen) {
//      NVIC_ENABLE_IRQ(myTimer); // method 1
      IntOn(myTimer);           // method 2
//      IntOn2();                 // method 3
      isr_disen=0;
    }
    else {
//      NVIC_DISABLE_IRQ(myTimer); // method 1
      IntOff(myTimer);          // method 2
//      IntOff2();              // method 3
      isr_disen=1;
    }
    looping++;
  }

  if (looping > 9) {
    looping=0;
    myTimer.end();
    delay(500);
    myTimer.begin(audio_interrupt, 50000);
    Serial.print("new Timer: ");Serial.println(myTimer);
  }
}
For test purposes there are 3 methods implemented to enable or disable the interrupts. They are activated by uncommenting.
Method 1 and 3 are working, i.e. the LED is blinking for a second then blinking stops for a second, and so on.
Method 1 is the method recommended as answer to my first post.

Method 2 is not working, i.e. after the statement "myTimer.begin(..)" within setup() the LED is blinking for a short time and then stops blinking until "myTimer.begin(..)" is called again at the end of loop(). After this call the LED again is blinking for a short time and then stops, and so on.

The value of "myTimer" printed within setup() is the same as within IntOn() and IntOff() for method 2.
Method 2 is the method I need in my application.
Why does method 2 not work?

supArdu
 
Last edited:
Why does method 2 not work?
Possibly because you are doing pass by value instead of pass by reference. Try changing the function arguments to references:
Code:
void IntOn([COLOR=#ff0000]IntervalTimer&[/COLOR] actTimer) {
 
Possibly because you are doing pass by value instead of pass by reference. Try changing the function arguments to references
It does not work.
I tried it also with pointer, but also no success.
I don't understand that.

But meantime I found a solution. I transferred the creation of the timer into a class definition with start() and stop() definitions. The implementation of the class then calls NVIC_ENABLE_IRQ(myTimer) and NVIC_DISABLE_IRQ(myTimer) directly.
Class definition in a header file, myaudio.h:
Code:
class AudioClass {
  private:
...
    // Create an IntervalTimer object 
    IntervalTimer myTimer;
  
  public:
    AudioClass(void);  // constructor
    ~AudioClass(void); // destructor

    boolean init(void);
 
    void    start(void);  // starts interrupts
    void    stop(void);  // stops playback if playing, sets playposition to zero
...
};

extern AudioClass SdPlay;

Implementation in a cpp file, myaudio.cpp:
Code:
AudioClass SdPlay;

const int ledPin = LED_BUILTIN;  // the pin with a LED
volatile  boolean  LEDon=true;

void audio_interrupt(void) {    // must not be defined within the class but here!!
  if (LEDon) {
      digitalWrite(ledPin,1);
      SdPlay.blinkCount += 1;  // increase when LED turns on
  }
  else {
      digitalWrite(ledPin,0);
  }

  LEDon = !LEDon;
}

boolean AudioClass::init(void) {
...
  pinMode(ledPin, OUTPUT);

  myTimer.begin(audio_interrupt, 50000);

  stop();
...
}

void    AudioClass::start(void) {
 
  NVIC_ENABLE_IRQ(myTimer);
}

void AudioClass::stop(void) {
   NVIC_DISABLE_IRQ(myTimer);
}
Now the timer can be controlled from a sketch by SdPlay.start() and SdPlay.stop() after calling SdPlay.init() within setup().

Thank you for your time

NikoTeen
 
Status
Not open for further replies.
Back
Top