Fading LED outside loop() function

Hello!

I am using a Arduino Pro Micro, a pushbutton and a potmeter to toggle an RGB LED-strip. The button toggles the lights from red to green to blue, but I want to be able to have a fade function at the 4th, 5th and 6th push of the button.

I have found the code for the fade function online, and I have made it work. The only problem I have is that I cant get the function to run more than once before it switches to another mode.

To clarify: I want the function fade() to run forever, until I push the button.

I think should be rather easy to fix, but I just cant figure it out. Can anyone help me?

#define red 9
#define green 10
#define blue 6
#define potPin A0

//brightness
int analog_red = 10; //150
int analog_green = 10; //100
int analog_blue = 10; //200
int brightness = 0;

//buttons
#define inPin 2

//toggle
volatile int buttonState = HIGH;
volatile int lastButtonState = LOW;
volatile int stateNum = 0;

long time = 0;
long debounce = 200;

//fade
int fadeAmount = 5;
int fadetime = 20;
int value = 0;

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

  Serial.begin(9600);

  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(inPin, INPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

  brightness = (analogRead(potPin) / 4);

  toggle();
}

void toggle() {
  buttonState = digitalRead(inPin);

  if (buttonState != lastButtonState) {

    //change the state of the led when someone pressed the button
    if ((buttonState == HIGH &&  lastButtonState == LOW)) {
      stateNum++;
    }

    if (stateNum == 1)
    {
      analogWrite(red, brightness);
      analogWrite(green, 0);
      analogWrite(blue, 0);
    }

    if (stateNum == 2 || green == brightness) {
      analogWrite(red, 0);
      analogWrite(green, brightness);
      analogWrite(blue, 0);
    }

    if (stateNum == 3)
    {
      analogWrite(red, 0);
      analogWrite(green, 0);
      analogWrite(blue, brightness);
    }

    if (stateNum == 4)
    {
      stateNum = 0;
      analogWrite(red,  0);
      analogWrite(green, 0);
      analogWrite(blue, 0);
      fade(green);
    }

    lastButtonState = buttonState;
    delay(debounce);

  }

}

void fade(int led)
{

  while (stateNum == 0)
  {
    for (value = 255; value >= 30; value -= 5) // fade out (from max to min)
    {
      analogWrite(led, value);
      delay(25);
    }

    for (value = 30 ; value <= 255; value += 5) // fade in (from min to max)
    {
      analogWrite(led, value);           // sets the value (range from 0 to 255)
      delay(25);                            // waits for 30 milli seconds to see the dimming effect
    }

    if (buttonState != lastButtonState)
    {
      if ((buttonState == HIGH &&  lastButtonState == LOW))
      {
        stateNum++;
      }
    }

  }
}

I think should be rather easy to fix, but I just cant figure it out.

That is because it is not easy to fix.

Basically you have loops that contain a delay so they are not going to return to the main function until they are done. This means you only get to look at any push button at the end of a fade.

You need to implement the code as a state machine rather than a loop with embedded delays. Look for examples in the blink without delay example in the IDE, or the many other state machine examples. This is the next step up in learning to program.

Okey, thank you very much! I feared I had to do something drastic about the code, but I did not know what. I will look at the blink example and hopefully figure it out.

Hi Bjornarm...

have You solved Your fading problem?

Ramotny: Hi Bjornarm...

have You solved Your fading problem?

Hello!

Sadly I have not, mostly because I have not had any time. Will try to update as soon as I can get it working!

For help on state machines see my http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html Or Robin2's several things at once http://forum.arduino.cc/index.php?topic=223286.0

Have the push button increment a counter, have the counter variable determine which mode to perform in until the counter changes.

Looks like you were trying that, but idk why you were setting it back to 0 every time.

Hello again!

I made it work, the biggest problem I see now is that the button gets too sensitive. It is as if it read all the time, with no delay from the last push. I have tried altering the variabel "interval" but it is still to sensitive. Any ideas?

EDIT: I also think I got this a bit wrong. When I implement the fade-function it does not fade, it does only turn on at the value it reads when the button is pushed. At least that is my theory.

I added the fade function as well, maybe some of you know wether there is a better one to use or not?

#define red 9
#define green 10
#define blue 6
#define potPin A0

//brightness
int analog_red = 10; //150
int analog_green = 10; //100
int analog_blue = 10; //200
int brightness = 0;

//buttons
#define inPin 2

//toggle
volatile int buttonState = HIGH;
volatile int lastButtonState = LOW;
volatile int stateNum = 0;
const long interval = 25;
unsigned long previousMillis = 0;

//fade
int value = 0;
unsigned long time = 0;
int periode = 2000;

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

  Serial.begin(9600);

  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(inPin, INPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

  brightness = (analogRead(potPin) / 4);

  buttonState = digitalRead(inPin);

  unsigned long currentMillis = millis();

  if ((buttonState != lastButtonState) && ((currentMillis - previousMillis) >= interval)) {

    //change the state of the led when someone pressed the button
    if ((buttonState == HIGH &&  lastButtonState == LOW)) {
      stateNum++;
    }

      if (stateNum == 1) {
        analogWrite(red, brightness);
        analogWrite(green, 0);
        analogWrite(blue, 0);
    }

      if (stateNum == 2 || green == brightness) {
        analogWrite(red, 0);
        analogWrite(green, brightness);
        analogWrite(blue, 0);
      }

      if (stateNum == 3)
      {
        stateNum = 4;
        analogWrite(red, 0);
        analogWrite(green, 0);
        analogWrite(blue, brightness);
      }

      if (stateNum == 4)
      {
        stateNum = 0;
        analogWrite(red, 0);
        analogWrite(green, 0);
        analogWrite(blue, 0);
        fade();
      }

      lastButtonState = buttonState;

}

void fade() 
{ 
 time = millis();
 value = 128+127*cos(2*PI/periode*time);

 analogWrite(blue, value);           // sets the value (range from 0 to 255) 

}
}

So you're analogWrite-ing a number, just once, how is it supposed to fade