Dimming RGB with TIP120 - What i'am doing wrong....

Hello !
I trying to dim a rgb light with a TIP120 and have no trouble dimming it.

But I want it do dim up to full light when a button have HIGH and when the button go low i want it to dim the light down to off..

Here is my code:

int ledPin = 3;
const int buttonPin = 2; // the number of the pushbutton pin

int buttonState = 0; // variable for reading the pushbutton status

void setup() {
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}

void loop() {
// fade in from min to max in increments of 5 points:
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
// turn LED on:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(100);
}
}
if (buttonState == LOW) {
// turn LED on:
// fade out from max to min in increments of 5 points:
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(100);
}
}
}

The problem is that the dimming always restart itself. When the button is LOW the light goes from 255 to 0 but after that i restart and do it again...

Please use code tags when posting code; so much easier to copy :wink:

type
** **[code]** **

paste your code after that
type
** **[code]** **
after that

It will look like below.

OK, the problem is that loop() is executed time after time after time. So every time you have done a dim cyle, loop is started again and the dim cycle starts again.

You need to keep track when the dimming is finished; the below uses a boolean variable that indicates the direction (up or down). The variable is static so its information is not lost between successive calls to loop. Once a down cycle is done, you can only do an up cycle and vice versa.

Be aware that you have to complete a dim cycle, else the direction will not change; this is just a quick and dirty solution (not tested).

int ledPin = 3;
const int buttonPin = 2;     // the number of the pushbutton pin

int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop() {
  
  // remember the direction; false = dim down, true = dim up
  static bool fDirection = false;

  
  // fade in from min to max in increments of 5 points:
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH && fDirection == true) {
    // turn LED on:
    for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPin, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(100);
    }

    // done, change direction
    fDirection = false;
  }
  if (buttonState == LOW && fDirection == false) {
    // turn LED on:
    // fade out from max to min in increments of 5 points:
    for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPin, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(100);
    }
    // done, change direction
    fDirection = true;
  }
}

Note:
It's bad habit to use for loops with delays in your code. As an exercise, try to modify the code without using the for loop; instead use a static counter that you increment from 0 to 255 and decrement from 255 to 0 (in steps of 5).
If you get stuck, ask.

Thanks sterretje !
It worked !

I will post the code like you next time.

But another question :smiley:

If I have 3 buttons and 3rgb stripes can I use the static bool then ?
How do the arduino hold track if it is the 1 or 3 rgb that will dim up or down ?

The 3 buttons and RGB will have the same job as the code I first posted.

You can use three boolean variables. E.g. fDirectionRed, fDirectionGreen and fDirectionBlue.

Or use a variable and store the direction values in there. Maybe a bit more advanced

Or a struct; same principle as the variable but a little easier to use.

With the latter two options, you can save 2 bytes.

Okei , now is this nearly working is I want it.

The one problem I have now is that the lights doesn't turn on the same time. First the green dim up, then the red and then the blue. Same when they dim down to just opposite...

Does it have anything to do with the delay ? I want them all to dim up at the same time.

int ledPinGreen = 3;
int ledPinRed = 5;
int ledPinBlue = 6;
const int sensorPin = 8;     // the number of the pushbutton pin

int sensorState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(sensorPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  
  // remember the direction; false = dim down, true = dim up
  static bool fDirectionRed = false;
  static bool fDirectionBlue = false;
  static bool fDirectionGreen = false;
  {
 int sensorState = digitalRead(sensorPin);
  // print out the state of the button:
  Serial.println(sensorState);
  delay(10); 
  }
  
  /////////
  //GREEN
  /////////
  
  // fade in from min to max in increments of 5 points:
  sensorState = digitalRead(sensorPin);
  
  if (sensorState == HIGH && fDirectionGreen == true) {
    // turn LED on:
    for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinGreen, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }

    // done, change direction
    fDirectionGreen = false;
  }
  if (sensorState == LOW && fDirectionGreen == false) {
    // turn LED on:
    // fade out from max to min in increments of 5 points:
    for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinGreen, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }
    // done, change direction
    fDirectionGreen = true;
  }
  ///////////
  // RED
  //////////
 
  if (sensorState == HIGH && fDirectionRed == true) {
    // turn LED on:
    for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinRed, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }

    // done, change direction
    fDirectionRed = false;
  }
  if (sensorState == LOW && fDirectionRed == false) {
    // turn LED on:
    // fade out from max to min in increments of 5 points:
    for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinRed, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }
    // done, change direction
    fDirectionRed = true;
    }
    
    ////////////
    //BLUE
    ///////////
    
  if (sensorState == HIGH && fDirectionBlue == true) {
    // turn LED on:
    for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinBlue, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }

    // done, change direction
    fDirectionBlue = false;
  }
  if (sensorState == LOW && fDirectionBlue == false) {
    // turn LED on:
    // fade out from max to min in increments of 5 points:
    for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
      // sets the value (range from 0 to 255):
      analogWrite(ledPinBlue, fadeValue);
      // wait for 30 milliseconds to see the dimming effect
      delay(10);
    }
    // done, change direction
    fDirectionBlue = true;

}
}
[code]

I want them all to dim up at the same time.

Then don't use three different for loops.

You must learn to think in the smallest possible steps and execute them (basically) in parallel. So do one step red, one step green and one step blue. Do a delay once you have done one step for each color and loop() will take care of the rest.

void loop() {

  // remember the direction; false = dim down, true = dim up
  static bool fDirection = false;
  // femember the fade value
  static int fadeValue = 0;

  // fade in from min to max in increments of 5 points:
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH && fDirection == UP && fadeValue <= 250) {
    fadeValue += 5;
    analogWrite(ledPin, fadeValue);
  }

  if (fadeValue >= 255)
  {
    // done, change direction
    fDirection = false;
  }

  // fade in from min to max in increments of 5 points:
  if (buttonState == LOW && fDirection == DOWN && fadeValue >= 5) {
    fadeValue -= 5;
    analogWrite(ledPin, fadeValue);
  }

  if (fadeValue <= 0)
  {
    // done, change direction
    fDirection = true;
  }

  // now we can do the short delay
  delay(100);
}

The above code (not tested) should behave the same as the previous one I posted. You can modify to use the three different colors using three direction variables and three fade variables.

I've made one additional change; true and false don't mean much for a direction. Place the below at the tops of your code

#define UP true
#define DOWN false

Okei, thanks now its working !

I also want to have another button, if this button is presset I want for example the green light gradually go white, and when the button is released again I want it to go back to green again.

I have soldered so if OUTPUT 3 is active the RGB light is green and if OUTPUT 3 and 9 is activated the RGB lights white.

I know this is way over my head to make this, but maybe someone have some tips to make it easier ?

What is the best way to do this ?

Instead of doing an analogWrite to one pin, do an analogWrite to pin 3 immediately followed by an analogWrite to pin 9.

All right, now I have it like I want it, but i noticed a glitch.

If one of the ''buttons'' is released before the dimming is done the lights stop in the dimming position they are and wait a while before it start dimming up or down again.

Here is my code. (my longest code ever) :cold_sweat:

int ledPinGreen = 3;
int ledPinRed = 5;
int ledPinBlue = 6;

int ledPinWV = 9;
int ledPinWC = 10;
int ledPinWB = 11;

const int sensorPin = 8;  
const int vPin = 2;
const int cPin = 4;
const int bPin = 7;

#define UP true
#define DOWN false

int sensorState = 0;         // variable for reading the pushbutton status
int vState = 0;
int cState = 0;
int bState = 0;
void setup() {
 // initialize the pushbutton pin as an input:
  pinMode(sensorPin, INPUT);
  pinMode(vPin, INPUT);
  pinMode(cPin, INPUT);
  pinMode(bPin, INPUT);
}

void loop() {

  // remember the direction; false = dim down, true = dim up
  static bool fDirectionGreen = false;
  static bool fDirectionRed = false;
  static bool fDirectionBlue = false;
  static bool fDirectionWV = false;
  static bool fDirectionWC = false;
  static bool fDirectionWB = false;
  // femember the fade value
  static int fadeValueGreen = 0;
  static int fadeValueRed = 0;
  static int fadeValueBlue = 0;
  static int fadeValueWV = 0;
  static int fadeValueWC = 0;
  static int fadeValueWB = 0;

  sensorState = digitalRead(sensorPin);
  vState = digitalRead(vPin);
  cState = digitalRead(cPin);
  bState = digitalRead(bPin);
  ///// GREEN /////

  
  
  if (sensorState == HIGH && fDirectionGreen == UP && fadeValueGreen <= 250) {
    fadeValueGreen += 5;
    analogWrite(ledPinGreen, fadeValueGreen);
  }

  if (fadeValueGreen >= 255)
  {
    // done, change direction
    fDirectionGreen = false;
  }

  // fade in from min to max in increments of 5 points:
  if (sensorState == LOW && fDirectionGreen == DOWN && fadeValueGreen >= 5) {
    fadeValueGreen -= 5;
    analogWrite(ledPinGreen, fadeValueGreen);
  }

  if (fadeValueGreen <= 0)
  {
    // done, change direction
    fDirectionGreen = true;
  }

  // now we can do the short delay
  

  ////  RED  ////

  
  if (sensorState == HIGH && fDirectionRed == UP && fadeValueRed <= 250) {
    fadeValueRed += 5;
    analogWrite(ledPinRed, fadeValueRed);
  }

  if (fadeValueRed >= 255)
  {
    // done, change direction
    fDirectionRed = false;
  }

  // fade in from min to max in increments of 5 points:
  if (sensorState == LOW && fDirectionRed == DOWN && fadeValueRed >= 5) {
    fadeValueRed -= 5;
    analogWrite(ledPinRed, fadeValueRed);
  }

  if (fadeValueRed <= 0)
  {
    // done, change direction
    fDirectionRed = true;
  }

  // now we can do the short delay
  

  ////////// BLUE /////
   
  if (sensorState == HIGH && fDirectionBlue == UP && fadeValueBlue <= 250) {
    fadeValueBlue += 5;
    analogWrite(ledPinBlue, fadeValueBlue);
  }

  if (fadeValueBlue >= 255)
  {
    // done, change direction
    fDirectionBlue = false;
  }

  // fade in from min to max in increments of 5 points:
  if (sensorState == LOW && fDirectionBlue == DOWN && fadeValueBlue >= 5) {
    fadeValueBlue -= 5;
    analogWrite(ledPinBlue, fadeValueBlue);
  }

  if (fadeValueBlue <= 0)
  {
    // done, change direction
    fDirectionBlue = true;
  }


/////// GREEN W ////////
 
  if (vState == LOW && sensorState == HIGH && fDirectionWV == UP && fadeValueWV <= 250) {
    fadeValueWV += 5;
    analogWrite(ledPinWV, fadeValueWV);
  }

  if (fadeValueWV >= 255)
  {
    // done, change direction
    fDirectionWV = false;
  }

  // fade in from min to max in increments of 5 points:
  if (vState == HIGH && fDirectionWV == DOWN && fadeValueWV >= 5) {
    fadeValueWV -= 5;
    analogWrite(ledPinWV, fadeValueWV);
  }

  if (fadeValueWV <= 0)
  {
    // done, change direction
    fDirectionWV = true;
  }

   /////////// RED W ///////////
    if (cState == LOW && sensorState == HIGH && fDirectionWC == UP && fadeValueWC <= 250) {
    fadeValueWC += 5;
    analogWrite(ledPinWC, fadeValueWC);
  }

  if (fadeValueWC >= 255)
  {
    // done, change direction
    fDirectionWC = false;
  }

  // fade in from min to max in increments of 5 points:
  if (cState == HIGH && fDirectionWC == DOWN && fadeValueWC >= 5) {
    fadeValueWC -= 5;
    analogWrite(ledPinWC, fadeValueWC);
  }

  if (fadeValueWC <= 0)
  {
    // done, change direction
    fDirectionWC = true;
  }

  //////////BLUE/////////

   if (bState == LOW && sensorState == HIGH && fDirectionWB == UP && fadeValueWB <= 250) {
    fadeValueWB += 5;
    analogWrite(ledPinWB, fadeValueWB);
  }

  if (fadeValueWB >= 255)
  {
    // done, change direction
    fDirectionWB = false;
  }

  // fade in from min to max in increments of 5 points:
  if (bState == HIGH && fDirectionWB == DOWN && fadeValueWB >= 5) {
    fadeValueWB -= 5;
    analogWrite(ledPinWB, fadeValueWB);
  }

  if (fadeValueWB <= 0)
  {
    // done, change direction
    fDirectionWB = true;
  }
  // now we can do the short delay
  delay(100);
}
[code]
If I understand you correctly, you only want one presses to start the fading. In that case you need to remember the status of the button and check against the new status.

void loop()
{
  // rememner last button state
  static int vStatePrevious = LOW;
  // remember if v is running
  vool vRunning = false;

  vState = digitalRead(vPin);
  
  // there was a change
  if (vState != vStatePrevious)
  {
    vStatePrevious = vState;
    vRunning = true;
    
  }

  if(vRunning == true)
  {
    //fade the LED
    ...
    ...

    // if the fadeValue reaches the limmit, set vRunning to false
  }


}

Note: this is just to give you the idea.