help needed with attachInterrupt on DUE

Hi everybody,

I just started with Arduino and could need some help. My projects is to build a lamp using 4 Robotdyn AC dimmers with 4 220V light bulbs. I want to program an Arduino DUE in such a way that the 4 dimmers create various light patterns (like running lights,…). I want to use a switch button to change between the patterns.
I have reduced my code in order to highlight my problem.
The following code is for one dimmer and three different button states only. The first two states (0 and 1), only change the intensity of the light (100% for state 0 and 50% for state 1). The third button state (2) should increase the light intensity in steps of 1% until 100% and then start over until the button states changes.
The pushbutton is connected to D4. I use attachInterrupt to call buttonPress(). buttonPress() should change the button state. The code works fine to change from button state 0 to 1 and 1 to 2. But it does not react anymore while button state 2 is active.
I would appreciate some help here.

#include <Wire.h>
#include <RBDdimmer.h>

#define dimmer_outputPin  9 //dimmer pins
#define zerocross  2        //dimmer pins

volatile int buttonState = 0;
int old_buttonState = 0;
int current_State=0;
     
dimmerLamp dimmer(dimmer_outputPin, zerocross); //defining dimmer

void setup() {
  Serial.begin(115200);
  attachInterrupt(4,buttonPress, RISING); //pushbutton attached to D4
  dimmer.begin(NORMAL_MODE, ON); //dimmer initialisation: name.begin(MODE, STATE) 
}

void loop() { 
if (buttonState==0)
    { 
    old_buttonState=0; 
    dimmer.setPower(100); // setPower(0-100%);
    }

if (buttonState==1)
    {  
    old_buttonState=buttonState;
    dimmer.setPower(50); // setPower(0-100%);
    }

if (buttonState==2)
    {
    old_buttonState=buttonState;
    current_State = buttonState;
        while(buttonState==current_State) 
        {
          for (int i=1; i <= 100; i++)
          {
            dimmer.setPower(i);
            delay(100);
          }
        }
    }
   
if (buttonState ==3)
    {
    old_buttonState=0;
    buttonState=0;
    }         
}

//ISR
void buttonPress()
{
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 200ms, assume it's a bounce and ignore
    if (interrupt_time - last_interrupt_time > 100)
       {
       buttonState = old_buttonState + 1;
       }
   last_interrupt_time = interrupt_time;
}

I suggest putting a Serial.println(".") inside your FOR loop for buttonState == 2 to help you debug.

Your code looks more complicated than it needs to be.

void loop()
{
  if ( buttonState == 0 )
  {
    dimmer.setPower( 100 ); // setPower(0-100%);
  }

  if ( buttonState == 1 )
  {
    dimmer.setPower( 50 ); // setPower(0-100%);
  }

  if ( buttonState == 2 )
  {
    for ( int i = 1; i <= 100; i++ )
    {
      dimmer.setPower( i );
      delay( 100 );
    }
  }


}

//ISR
void buttonPress()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if ( interrupt_time - last_interrupt_time > 100 )
  {
    buttonState = ( buttonState + 1 ) % MAX_BUTTON_STATE;
  }
  last_interrupt_time = interrupt_time;
}

You should try to remove the delay function. This is just wasted CPU cycles and makes your program react slowly. Check out the BlinkWithoutDelay example.

ieee488: I suggest putting a Serial.println(".") inside your FOR loop for buttonState == 2 to help you debug.

Hi. Thanks for your reply. In my complete code I have added Serial.println at different locations. Still, I couldn't find a solution until now.

Klaus_K:
Your code looks more complicated than it needs to be.

void loop()

{
  if ( buttonState == 0 )
  {
    dimmer.setPower( 100 ); // setPower(0-100%);
  }

if ( buttonState == 1 )
  {
    dimmer.setPower( 50 ); // setPower(0-100%);
  }

if ( buttonState == 2 )
  {
    for ( int i = 1; i <= 100; i++ )
    {
      dimmer.setPower( i );
      delay( 100 );
    }
  }

}

//ISR
void buttonPress()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it’s a bounce and ignore
  if ( interrupt_time - last_interrupt_time > 100 )
  {
    buttonState = ( buttonState + 1 ) % MAX_BUTTON_STATE;
  }
  last_interrupt_time = interrupt_time;
}




You should try to remove the delay function. This is just wasted CPU cycles and makes your program react slowly. Check out the BlinkWithoutDelay example.

Thanks for this advice. I will definitely do that. I will have time tonight to continue working on my project. However, this shorter version of the code will not solve my initial problem, right?

By the way, I just noticed that my friend CBRIG was still logged into my computer. I accidentally started this post under his name.

However, this shorter version of the code will not solve my initial problem, right?

If you replace the delay() with millis() the problem will go away.

And if you replace the for loop() with a counter your code will get very responsive.

If you get stuck let me know and I will clean up my test code and post it.

Thanks a lot Klaus! I will try and let you know asap.

I just wanted to test the shorter code as Klaus recommended. Unfortunately, my Arduino is behaving somehow weird. All dimmers are flickering and do random stuff. The Oled display also displays weird stuff. I have the bad feeling that I destroyed the board by applying 5V to the input. I should have read the specs of the DUE before :( I will order a new board and continue trying.

Hey guys,

I have installed a new DUE in my setup and uploaded the shorter code that Klaus suggested.
Everything works fine except for the part where I try to replace the delay commend with millis()

This code works with delay which unfortunately causes sporadic response of the button:

if (buttonState==5){

        unsigned long begin_millis = millis();
        
        for (int i=1; i <= 96; i++)
        {
          dimmer1.setPower(dimlev1[i]);
          dimmer2.setPower(dimlev2[i]);
          dimmer3.setPower(dimlev3[i]);
          dimmer4.setPower(dimlev4[i]);
          delay(200);
        }
}

And this is my try using millis() (which does not work :frowning: ). Can some body help me on this part?

if (buttonState==5){

        unsigned long begin_millis = millis();
        
        for (int i=1; i <= 96; i++)
        {
         if (millis()-begin_millis > 200)
         { 
          dimmer1.setPower(dimlev1[i]);
          dimmer2.setPower(dimlev2[i]);
          dimmer3.setPower(dimlev3[i]);
          dimmer4.setPower(dimlev4[i]);
          begin_millis = millis();
         }
        }

}

You need to conceptionally change the code. Do not try to create another version of the current code. You need to leave the if(buttonState == 5) statement, do all the other things your code needs to do and come back again and again.

Here is a very simple example of how you could look at the problem.

void loop()
{
  static int loopCounter = 0;
  static int slowCounter = 0;
  loopCounter++;

  if(loopCounter % 10 == 0)
  {
    // do something only every 10th time loop runs
    slowCounter++;
    if(slowCounter > 100)
      slowCounter = 0;
    // Now we have a value that slowly counts up to 100
  }

  // here you can do things every time loop runs
}

Hi Klaus!

I was already afraid you would suggest something like that :) Anyhow, because my programming skills are somehow limited I continued to play around with my approach and finally my code does what it should do.

Here is how I replaced the delay-function with millis(). The code is responsive to the button press and runs without problems.

Thanks again for all you help!

int dimlev1[] ={89,69,49,35,35,35};
int dimlev2[] ={89,69,49,35,35,35};
int dimlev3[] ={89,69,49,35,35,35};
int dimlev4[] ={89,69,49,35,35,35};

int i=1;

unsigned long previousMillis =0;
unsigned long currentMillis;

void setup() {
  // here some dimmer code - see RBDdimmer.h

}

void loop() {
if (buttonState==4){
        
          if (millis()-previousMillis > 150)
          { 
            currentMillis = millis();
            dimmer1.setPower(dimlev1[i]);
            dimmer2.setPower(dimlev2[i]);
            dimmer3.setPower(dimlev3[i]);
            dimmer4.setPower(dimlev4[i]);
            previousMillis = currentMillis;
            i++;
            if(i == 6){
               i=1;
              }
         }
}
}

Here is a youtube-link to the finished project:

https://www.youtube.com/watch?v=LDxYbdyTckc