Go Down

Topic: RGB Crossfader with touchbuttons to control fading, brighness and On/Off (Read 275 times) previous topic - next topic

nighteagle19

Hello,

im new on the forum and not so confirm with arduinio like a real coder. I make something like small project only for hobby.

Now for our kitchen i want to create a touchsensor-control RGB-LED-Stripe. And i want to use normaly 5050 LEDs and not some digital ones. I drive each color with a mosfet and pwm and want to control brightness, color and on/off functions with buttons - no bluetooth and also no remote with a app or something like this. I want to have buttons hard install on the wall to control the LED-Stripe.

I have looked around on the web and find some projects with RGB-Crossfader - most of them only for remote or bluetooth. Many of them use a loop to count the steps for the colors. I play around with it sinse 2 days and have functional brighness and on/off - but with the fading im blind or dont see the tress because of the forest...

In Detail

Working so far thes two functions:
I have one button for on/off is a momentary switch and one touch is on and another touch is off the LEDs.
Next i have two buttons also momentary switch with one is pressed brighness go down and the other button is pressed brighness go up.

Not working function:
I have another two buttons - one for fade (crossfade) from actually color to next in the rgb or hsv model and another buttons for fade from actually color backwards.

Like the brighness-function but with colors. If you want a nice smooth color and you dont know which - then you fade forward by pressing one button and if you find your color you can stop or go backwards in fading. Hope is clear what simple function i mean...?

For me is these the simplest function like a color wheel from a remote but with two buttons. I think after you have found your color i will count a timer and after a time x i will save the actually color into the eeprom so if i have power off and later on like the power switch in the kitchen on the wall the i have the same color as before and if i press the color control buttons it beginns to fade from these color.

So for this after power one i have to read the eeprom and use this color as startcolor for fading forward and backward. If is not any color in the eeprom i will set in settings first a specific color. The eeprom routine is not the problem i have use this often and on the actually project not implemented yet - is for later if all the function work correctly - for now is only for you to understand what i want to do.

So if you go into your kitchen - you switch on the Lights and your color is on the LEDs - if you want to change it you have little touchsensors behind glas to controll color, brighness, on/off the LEDs.

So simple but for an newbie complicated - i have found a project to build on my idea - is with an remote but i have deactivate it in the code.

My problem is now how i fade with pressing a button forward and also backward. I have the color-fading loop  and i think i have to store the actually color first and by pressing button to set the color in the fading loop and fade from there in one direction. I think i need also two different loops - one for forward fading and one  for backward fading.

If you have some ideas to modify my actually project the please tell me i will do my best... :-)

Do you think the best idea is first to build two different loops for forward and backward or use one loop and depending from the button add or subtract the counts for the led-colors R, G and B?

Whats the best algorithm for these idea?

1. Read actually color from EEprom > if not then set xR, xG, and xB and write in color (Only one time of the program - later is some color in eeprom all the time)
2. Write actually color read from EEprom into the color-variables.
3. Check buttons pressed
4. Check which button is pressed
5a. Forward fading Button pressed - start from actually color fading forward "add" counts of the crossfader
5b. Backward fading Button pressed - start from actually color fading backward "substract" counts of the crossfader
6. Check released button
7. Stop Fading Loop
8. After time x (round about 1 minute) and no button is pressed after last button-pressed event store actually color in EEprom (Only one time after the color is changed, not every time x - because  the EEprom can not have unlimited write-operations)


What do you think about it?

Regards,

Boris

nighteagle19

Code: [Select]
#include <TimerOne.h>
//#include <IRremote.h>
#include <RGBMood.h>

//int RECV_PIN = 2;  // IR-Receiver PIN
//int led = 11;       // Satus-LED PIN
int modus;          // Modus for Interrupt-Querry
int ledr = 10;       // RGB LED red PIN
int ledg = 9;       // RGB LED green PIN                       
int ledb = 11;       // RGB LED blue PIN
int SerialBuffer = 0;
int c[3];

// Input Touchsensors
const int buttonPin_A = 3;
const int buttonPin_B = 4;
const int buttonPin_C = 5;
const int buttonPin_D = 6;

// Input Buttonstates
int buttonstate_A = 0;
int buttonprevious_A = 0;
int buttonstate_B = 0;
int buttonprevious_B = 0;
int buttonstate_C = 0;
int buttonprevious_C = 0;
int buttonstate_D = 0;
int buttonprevious_D = 0;


//RGB Pins Array
int CH[3] = {9, 10, 11};
int val[3] = {0, 0, 0}; // led brightness 0-255


RGBMood m(ledr, ledg, ledb);

int timerwert = 10;   // Timer time for Interrupt in ms

String readString;

// Color arrays
int black[3]  = { 0, 0, 0 };
int white[3]  = { 255, 255, 255 };
int red[3]    = { 255, 0, 0 };
int green[3]  = { 0, 255, 0 };
int blue[3]   = { 0, 0, 255 };
int yellow[3] = { 40, 95, 0 };
int dimWhite[3] = { 30, 30, 30 };

int brightness = 255;    // how bright the LED is on Startup
int fadeAmount = 1;    // how many points to fade the LED by

// etc.

// Set initial color
int redVal = black[0];
int grnVal = black[1];
int bluVal = black[2];

int wait = 2;      // 10ms internal crossFade delay; increase for slower fades
int hold = 1;       // Optional hold when a color is complete, before the next crossFade
int brighthold = 1000;
int DEBUG = 0;      // DEBUG counter; if set to 1, will write values back via serial
int loopCount = 60; // How often should DEBUG report?
int repeat = 0;     // How many times should we loop before stopping? (0 for no stop)
int j = 0;          // Loop counter for repeat

int state = 0;

// Initialize color variables
int prevR = redVal;
int prevG = grnVal;
int prevB = bluVal;

#define ON                1
#define OFF               2
#define BRIGHTNESS_UP     3
#define BRIGHTNESS_DOWN   4
#define FLASH             5
#define STROBE            6
#define FADE              7
#define SMOOTH            8

#define RED               9
#define GREEN             10
#define BLUE              11
#define WHITE             0x16DBBEE3

#define ORANGE            0xFFB04F
#define YELLOW_DARK       0xFFA857
#define YELLOW_MEDIUM     0xFF9867
#define YELLOW_LIGHT      0xFF8877

#define GREEN_LIGHT       0XFF30CF
#define GREEN_BLUE1       0XFF28D7
#define GREEN_BLUE2       0XFF18E7
#define GREEN_BLUE3       0XFF08F7

#define BLUE_RED          0XFF708F
#define PURPLE_DARK       0XFF6897
#define PURPLE_LIGHT      0XFF58A7
#define PINK              0XFF48B7
#define MAX 255

//IRrecv irrecv(RECV_PIN);
//decode_results results;

void setup()
{

  // Buttons
  pinMode(buttonPin_A, INPUT);
  pinMode(buttonPin_B, INPUT);
  pinMode(buttonPin_C, INPUT);
  pinMode(buttonPin_D, INPUT);

 
  pinMode(ledr, OUTPUT); // Set RGB LED Pins as Output
  pinMode(ledg, OUTPUT); // Set RGB LED Pins as Output
  pinMode(ledb, OUTPUT); // Set RGB LED Pins as Output
  //pinMode(led, OUTPUT); // set Status-LED as Output
 //initiate rgb pins output
    for (int i=0; i<3; i++)
  {
    pinMode(CH[i], OUTPUT);
  }

  m.setMode(RGBMood::RANDOM_HUE_MODE);  // Automatic random fade.
  m.setHoldingTime(4000);  // Keep the same color for 4 seconds before fading again.
  m.setFadingSteps(150);   // Fade with 150 steps.
  m.setFadingSpeed(50);    // Each step last 50ms. A complete fade takes 50*150 = 7.5 seconds
  m.setHSB(random(359), 255, 255);

Serial.begin(9600);

  //irrecv.enableIRIn(); // Start of IR-Recive

  Timer1.initialize(timerwert); // Initialisation of Timer-Interrupts
  Timer1.attachInterrupt(leseButtons); // IR-Read from Interrupt




}


void leseButtons(){

  int buttonread_A;
  int buttonread_B;
  int buttonread_C;
  int buttonread_D;
  buttonread_A = digitalRead(buttonPin_A);
  buttonstate_A=buttonread_A;
  buttonread_B = digitalRead(buttonPin_B);
  buttonstate_B=buttonread_B;
  buttonread_C = digitalRead(buttonPin_C);
  buttonstate_C=buttonread_C;
  buttonread_D = digitalRead(buttonPin_D);
  buttonstate_D=buttonread_D;

nighteagle19

Code: [Select]

            if(buttonstate_A )
            {
              if(!buttonprevious_A)
              {
              state = 1;
              buttonprevious_A=1;
              leseIR();
              }
              else
              {
              state = 2;
              buttonprevious_A=0;
              leseIR();
              }
            }


            


          
          if(!buttonstate_A && buttonstate_B && !buttonstate_C && !buttonstate_D)
          {
          state = 7;
          leseIR();
          }
          
          if(!buttonstate_A && !buttonstate_B && buttonstate_C && !buttonstate_D)
          {
          state = 3;
          leseIR();
          }
          
          if(!buttonstate_A && !buttonstate_B && !buttonstate_C && buttonstate_D)
          {
          state = 4;
          leseIR();
          }


//Serial.println(state);

}



void leseIR(){
  //if (irrecv.decode(&results)){
     //irrecv.resume();  // Receive the next value





//Serial.println(buttonstate_B);  
      
    switch (state)  {

      case FADE: // Modus Fade (DIY 4)
        modus = 1;  
      break;

      case 0xFF906F: // Modus pcambi (DIY 5)
        modus = 2;  
      break;

      case ON:  //Power
       modus = 0;
        crossFade(white);         // RGB LEDs ON
      break;
      case OFF:  //Power
       modus = 0;
        crossFade(black);         // RGB LEDs Off
      break;

      case BLUE:  //Blau 0,0,255
        modus = 0;
      crossFade(blue);
      break;

      case RED: //Rot
        modus = 0;
        crossFade(red);
      break;

      case GREEN://Grün
        modus = 0;
        crossFade(green);
      break;  

      case WHITE: //Weiss
        modus = 0;
        crossFade(white);
      break;

      case BRIGHTNESS_UP: //DIMMING UP
        modus = 0;
    brightness += 1;
    if (brightness > 255) brightness = 255;
    c[0] = prevR; c[1] = prevG; c[2] = prevB;
    analogWrite(ledr, redVal * brightness / 255 );   // Write current values to LED pins
    analogWrite(ledg, grnVal * brightness / 255 );      
    analogWrite(ledb, bluVal * brightness / 255 );
    state = 0;
    Serial.println(brightness);
    delay(brighthold);
      break;

       case BRIGHTNESS_DOWN: //DIMMING DOWN
         modus = 0;
    brightness -= 1;
    if (brightness < 10) brightness = 10;
    c[0] = prevR; c[1] = prevG; c[2] = prevB;
    analogWrite(ledr, redVal * brightness / 255);   // Write current values to LED pins
    analogWrite(ledg, grnVal * brightness / 255);      
    analogWrite(ledb, bluVal * brightness / 255);
    state = 0;
    Serial.println(brightness);
    delay(brighthold);
      break;

      case 0xFFAA55://Grün mitrtel
        modus = 0;
      break;  

      case 0xFF926D: //blau mittel
        modus = 0;

      break;

      case 0xFF12ED: //rosa
        modus = 0;

      break;      


     }             // Switch END

 // }              
}                  

void loop() {




  
if(modus==1){    // Querry pb Modus:1
m.tick();
}
if(modus==2){    // Querry pb Modus:1

}
        //Serial.println(prevR);
        //Serial.println(prevG);
        //Serial.println(prevB);
//      Serial.println(results.value, HEX);
//      Serial.println(DEC);
//      Serial.println(DEC);
//      Serial.println(DEC);
//      Serial.print("channel 1,2,3 values:");              // sends  brightness values to the serial monitor
    //  for(int i=0; i<3; i++){                             // every time the remote is pressed
    //  Serial.print(CH[i]);
//      Serial.print("   ");
    // }

    
  }


  int calculateStep(int prevValue, int endValue) {
  int step = endValue - prevValue; // What's the overall gap?
  if (step) {                      // If its non-zero,
    step = 1020/step;              //   divide by 1020
  }
  return step;
}

/* The next function is calculateVal. When the loop value, i,
*  reaches the step size appropriate for one of the
*  colors, it increases or decreases the value of that color by 1.
*  (R, G, and B are each calculated separately.)
*/

int calculateVal(int step, int val, int i) {

  if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
    if (step > 0) {              //   increment the value if step is positive...
      val += 1;          
    }
    else if (step < 0) {         //   ...or decrement it if step is negative
      val -= 1;
    }
  }
  // Defensive driving: make sure val stays in the range 0-255
  if (val > 255) {
    val = 255;
  }
  else if (val < 0) {
    val = 0;
  }
  return val;
}

/* crossFade() converts the percentage colors to a
*  0-255 range, then loops 1020 times, checking to see if  
*  the value needs to be updated each time, then writing
*  the color values to the correct pins.
*/

void crossFade(int color[3]) {
  // Convert to 255 to 100 %
  //int R = (color[0] * 255) / 100;
  //int G = (color[1] * 255) / 100;
  //int B = (color[2] * 255) / 100;

  int R = color[0];
  int G = color[1];
  int B = color[2];

  
Serial.println(R);

  int stepR = calculateStep(prevR, R );
  int stepG = calculateStep(prevG, G );
  int stepB = calculateStep(prevB, B );

  for (int i = 0; i <= 1020; i++) {
    redVal = calculateVal(stepR, redVal, i);
    grnVal = calculateVal(stepG, grnVal, i);
    bluVal = calculateVal(stepB, bluVal, i);

    analogWrite(ledr, redVal * brightness / 255);   // Write current values to LED pins
    analogWrite(ledg, grnVal * brightness / 255);      
    analogWrite(ledb, bluVal * brightness / 255);

    delay(wait); // Pause for 'wait' milliseconds before resuming the loop


  }
  // Update current values for next loop
  prevR = redVal;
  prevG = grnVal;
  prevB = bluVal;
  delay(hold); // Pause for optional 'wait' milliseconds before resuming the loop
}

What about doing a color table with the differrnt colors you want to fade between. Then the two fade buttons steps and index up and down in the table.

nighteagle19

Hello,

thanks for the answer - you mean all the possible colors of the three channels?
I calculate 1020 steps*1020steps*1020steps  thats over i billion colors...  but the idea looks simpler than i think... if i use 256steps is over 16million colors - okay most of them we can shorten but if i use only 64 steps than there also over 200.000 colors for the table.
To many values to write a table?

Hello,

thanks for the answer - you mean all the possible colors of the three channels?
I calculate 1020 steps*1020steps*1020steps  thats over i billion colors...  but the idea looks simpler than i think... if i use 256steps is over 16million colors - okay most of them we can shorten but if i use only 64 steps than there also over 200.000 colors for the table.
To many values to write a table?
No I mean the color targets you can step between, then you fade to the selected color in some steps.
A simple way to fade is to increment/decrement 1 one each of RGB toward the selected target each cycle, where a cycle can be maybe 0.1 second (That would make the longest fade take 25.5 seconds). If you want to maintain brightness when fading you can either scale the target value with the brightness or always keep the actual color as full values and only scale it with brightness when writing it to the pwm registers.

That would mean variables like this:

ActualColor
TargetColor
Brightness


ActualColor is then scaled with brightness before being written to PWM registers:

analogWrite(Brightness*ActualColor.red/255);  // Assuming brightness is 0..255


The fading between colors is done with for each color:

if (ActualColor.red>TargetColor.red ) ActualColor.red--;
else if (ActualColor.red<TargetColor.red ) ActualColor.red++;










nighteagle19

Hello,

thanks for the answer - but have you read the code i post?
It increment the steps for each color... and  i have the brightness function here modified now.

So for that i don't need a table?

So for that i don't need a table?
Done the correct way a table will make the code easier to read and modify.
Your code has a lot of magic numbers inside the code like "case 0xFF926D", that is not very nice programming.

nighteagle19

Hello,

the HEX-Numbers are from the ifrared-Remote-Controll and is the control-adress from the library it received the codes. Each Code represent an special button on the remote...
You can ignore all these hex-numbers - because i don't want to use the remote.

Go Up