RGB lamp error

Hey all

I'm doing a fairly simple RGB style lamp with several modes,
anyway I've managed to do most of the hard stuff and its working the way I want it to, but there is an issue with when I want to change modes.
so in the void loop there is code to change the mode from 1 to 0 depending on its previous state and whether I have pressed the momentary switch or not.
well the mode changes from mode 0 to mode 1 no problem but I cant change it back, I'm guessing the RGB pattern cycle programmed is interfering with reading the input of the switch. An interesting thing to note is when I remove this from the main loop:

if (mode==1){
    crossFade(red);
    crossFade(green);
    crossFade(blue);
    crossFade(yellow);
  }

The button works perfectly but naturally the RGB pattern cycle code is broken. Any help would be appreciated, many thanks

Chris.

//RED ints
int REDpot = 0;    // select the input pin for the potentiometer
int REDpin = 9;   // select the pin for the RED LED (9)
int REDval = 0;       // variable to store the value coming from the sensor;
int REDcount = 200;
//GREEN ints
int GREENpot = 1;    // select the input pin for the potentiometer
int GREENpin = 10;   // select the pin for the GREEN LED(10)
int GREENval = 0;       // variable to store the value coming from the sensor
int GREENcount = 200;
//BLUE ints
int BLUEpot = 5;    // select the input pin for the potentiometer
int BLUEpin = 11;   // select the pin for the BLUE LED(11)
int BLUEval = 0;       // variable to store the value coming from the sensor
int BLUEcount = 200;
//Encoder Pins these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;
int count = 200;
volatile int lastEncoded = 0;
volatile long brightness = 0;
long lastbrightness = 0;
int lastMSB = 0;
int lastLSB = 0;
//pattern ints
  int mode=0;
  const int modebutton=4;
  int modestate=0;
  // Color arrays
  int black[3]  = { 0, 0, 0 };
  int white[3]  = { 100, 100, 100 };
  int red[3]    = { 100, 0, 0 };
  int green[3]  = { 0, 100, 0 };
  int blue[3]   = { 0, 0, 100 };
  int yellow[3] = { 40, 95, 0 };
  int dimWhite[3] = { 30, 30, 30 };
  // etc.
  
  // Set initial color
  int redVal = black[0];
  int grnVal = black[1]; 
  int bluVal = black[2];
  
  int wait = 10;      // 10ms internal crossFade delay; increase for slower fades
  int hold = 0;       // Optional hold when a color is complete, before the next crossFade
  int DEBUG = 1;      // 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
  
  // Initialize color variables
  int prevR = redVal;
  int prevG = grnVal;
  int prevB = bluVal;

  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;
  }
  int calculateVal(int step, int val, int i) {
    if (mode==1){
      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;
    }
  }
//end of pattern ints


void setup() {
  pinMode(REDpin, OUTPUT);
  pinMode(GREENpin, OUTPUT);
  pinMode(BLUEpin, OUTPUT);
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  pinMode(modebutton, INPUT);
  digitalWrite(encoderPin1, HIGH);
  digitalWrite(encoderPin2, HIGH);
  digitalWrite(modebutton, HIGH);
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);
  Serial.begin(9600);//9600
  Serial.flush();
}
//Encoder Update
void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
  if (brightness < 99){
    if(sum == 0b1101 && brightness < 100) brightness ++;
  }
    if (brightness > 1){
  if(sum == 0b1110 && brightness > 0) brightness --;
  }

  lastEncoded = encoded; //store this value for next time
}

void loop() {
   //mode state
  modestate=digitalRead(modebutton);
  if (modestate == HIGH && mode==0){
    mode=1;
    Serial.print("mode 1");
    delay (500);
  }
  else if (modestate == HIGH && mode==1){
    mode=0;
    Serial.print("mode 0");
    delay (500);
  }
  if (mode==1){
    crossFade(red);
    crossFade(green);
    crossFade(blue);
    crossFade(yellow);
  }
  else if (mode==0){
    //RED pot loop
    REDval = round((analogRead(REDpot))/4.05)-brightness*2.6;    // read the value from the sensor
    if (REDval<0){
      REDval=0;
    }
    analogWrite(REDpin, REDval);  // turn the ledPin on
    if (REDcount != REDval){
      Serial.print("Red pot value=");
      Serial.println(REDval);
      REDcount = REDval;
    }
    //GREEN pot loop
    GREENval = round((analogRead(GREENpot))/10.23)-brightness*1.03;    // read the value from the sensor
      if (GREENval<0){
      GREENval=0;
    }
    analogWrite(GREENpin, GREENval);  // turn the ledPin on
    if (GREENcount != GREENval){
    Serial.print("Green pot value=");
    Serial.println(GREENval);
    GREENcount = GREENval;
    }
    //BLUE pot loop
    BLUEval = round((analogRead(BLUEpot))/8.1)-brightness*1.3;    // read the value from the sensor
      if (BLUEval<0){
      BLUEval=0;
    }
    analogWrite(BLUEpin, BLUEval);  // turn the ledPin on
    if (BLUEcount != BLUEval){
    Serial.print("pot value=");
    Serial.println(BLUEval);
    BLUEcount = BLUEval;
    }
    //Encoder
    if (count != brightness){
    Serial.print("encoder possition=");
    Serial.println(brightness);
    count=brightness;
    }
  }  
}

void crossFade(int color[3]) {
  if (mode==1){
    if (repeat) { // Do we loop a finite number of times?
      j += 1;
      if (j >= repeat) { // Are we there yet?
        exit(j);         // If so, stop.
      }
    }
    // Convert to 0-255
    int R = (color[0] * 255) / 100;
    int G = (color[1] * 255) / 100;
    int B = (color[2] * 255) / 100;
  
    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(REDpin, redVal);   // Write current values to LED pins
      analogWrite(GREENpin, grnVal);      
      analogWrite(BLUEpin, bluVal); 
      
  
      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
  }
}

Yes those calls contain delays and take time to compleat soy our button is not looked at very often. Try holding it down.
If you want the button to act instintainously then you can't use those calls you will have to write your own.

thanks, have you got any suggestions? I have no idea what to replace them with, also holding the button down didn't fix the issue.

  Serial.begin(9600);//9600
  Serial.flush();

Open the serial port. Immediately block until all pending data (none) has been sent. Why?

        exit(j);         // If so, stop.

You should never need to call exit() in an Arduino sketch. That simply puts the Arduino into an "ignore everything, even interrupts, and do nothing" loop.

also holding the button down didn't fix the issue.

How long did you hold it? That loop can take more than 10 seconds to complete.

I have no idea what to replace them with

Look at the blink without delay example. You will have to completely, and I do mean completely, overhaul your sketch when you understand and are ready to embrace the blink without delay philosophy.

haha I guess i'm just not ready to embrace it. I fixed the problem by forcing the code to check if the input was low or high before assigning a delay.

i have also since added more functions, anyway its not pretty but it does the job:

#include "EEPROM.h"
//RED ints
int REDpot = 0;    // select the input pin for the potentiometer
int REDpin = 9;   // select the pin for the RED LED (9)
int REDval = 0;       // variable to store the value coming from the sensor;
int REDcount = 200;
//GREEN ints
int GREENpot = 1;    // select the input pin for the potentiometer
int GREENpin = 10;   // select the pin for the GREEN LED(10)
int GREENval = 0;       // variable to store the value coming from the sensor
int GREENcount = 200;
//BLUE ints
int BLUEpot = 5;    // select the input pin for the potentiometer
int BLUEpin = 11;   // select the pin for the BLUE LED(11)
int BLUEval = 0;       // variable to store the value coming from the sensor
int BLUEcount = 200;
//Encoder Pins these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;
int count = 200;
volatile int lastEncoded = 0;
volatile long brightness = 0;
long lastbrightness = 0;
int lastMSB = 0;
int lastLSB = 0;
//Encoder ints for speed
int count2 = 200;
volatile int lastEncodedspeed = 0;
volatile long wait = 10;
int waiteeprom;
long lastwait = 0;
int lastMSBspeed = 0;
int lastLSBspeed = 0;
//pattern
int mode=0;
const int modebutton=4;
int modestate=0;
int modestateprev;
// Color arrays
int black[3]  = { 0, 0, 0 };
int white[3]  = { 100, 100, 100 };
int red[3]    = { 100, 0, 0 };
int green[3]  = { 0, 100, 0 };
int blue[3]   = { 0, 0, 100 };
int yellow[3] = { 40, 95, 0 };
int dimWhite[3] = { 30, 30, 30 };
// etc.

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

int hold = 0;       // Optional hold when a color is complete, before the next crossFade
int DEBUG = 1;      // 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

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


void setup() {
  pinMode(REDpin, OUTPUT);

  pinMode(GREENpin, OUTPUT);
  pinMode(BLUEpin, OUTPUT);
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  pinMode(modebutton, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);
  Serial.begin(9600);//9600
  Serial.flush();
}
//Encoder Update
void updateEncoder(){
  //brightness
if (mode ==0){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
  if (brightness < 99){
    if(sum == 0b1101 && brightness < 100) brightness ++;
  }
    if (brightness > 1){
  if(sum == 0b1110 && brightness > 0) brightness --;
  }
  lastEncoded = encoded; //store this value for next time
}
else if (mode == 1){
  if (EEPROM.read(waiteeprom)!=wait){
    wait=EEPROM.read(waiteeprom);
  }
  //speed
  int MSBspeed = digitalRead(encoderPin1); //MSB = most significant bit
  int LSBspeed = digitalRead(encoderPin2); //LSB = least significant bit
  int encodedspeed = (MSBspeed << 1) |LSBspeed; //converting the 2 pin value to single number
  int sum  = (lastEncodedspeed << 2) | encodedspeed; //adding it to the previous encoded value
  if(sum == 0b1101 &&  wait < 50) {
    wait ++;
    EEPROM.write(waiteeprom, wait);
    Serial.println(wait);
  }
  if(sum == 0b1110 && wait > 1) {
    wait --;
    EEPROM.write(waiteeprom, wait);
    Serial.println(wait);
  }

  lastEncodedspeed = encodedspeed; //store this value for next time
  
}
}

//pattern
  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;
  }
  
  int calculateVal(int step, int val, int i) {
  if (mode==1){
      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;
    }
  }
  
void crossFade(int color[3]) {// Convert to 0-255
  if (mode==1){
    int R = (color[0] * 255) / 100;
    int G = (color[1] * 255) / 100;
    int B = (color[2] * 255) / 100;
  
    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(REDpin, redVal);   // Write current values to LED pins
      analogWrite(GREENpin, grnVal);      
      analogWrite(BLUEpin, bluVal); 
      if (digitalRead(modebutton) == LOW){
        modestateprev=2;
        delay(wait); // Pause for 'wait' milliseconds before resuming the loop

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

void loop() {
   //mode state
    modestate=digitalRead(modebutton);
  if (modestate == HIGH && mode==0 && modestateprev != 1){
    mode=1;
    modestateprev = 1;
    Serial.print("mode 1");
    
  }
  else if (modestate == HIGH && mode==1 && modestateprev != 1){
    mode=0;
    modestateprev = 1;
    Serial.print("mode 0");
  }
  if (digitalRead(modebutton) == LOW){
        modestateprev=2;
  }  
  //pattern
  crossFade(red);
  crossFade(green);
  crossFade(blue);
  crossFade(yellow);

  if (repeat) { // Do we loop a finite number of times?
    j += 1;
    if (j >= repeat) { // Are we there yet?
      exit(j);         // If so, stop.
    }
  }
  //RED loop
  REDval = round((analogRead(REDpot))/4.05)-brightness*2.6;    // read the value from the sensor
  if (REDval<0){
    REDval=0;
  }
  analogWrite(REDpin, REDval);  // turn the ledPin on
  if (REDcount != REDval){
    REDcount = REDval;
  }
  //GREEN loop
  GREENval = round((analogRead(GREENpot))/10.23)-brightness*1.03;    // read the value from the sensor
    if (GREENval<0){
    GREENval=0;
  }
  analogWrite(GREENpin, GREENval);  // turn the ledPin on
  if (GREENcount != GREENval){
  GREENcount = GREENval;
  }
  //BLUE loop
  BLUEval = round((analogRead(BLUEpot))/8.1)-brightness*1.3;    // read the value from the sensor
    if (BLUEval<0){
    BLUEval=0;
  }
  analogWrite(BLUEpin, BLUEval);  // turn the ledPin on
  if (BLUEcount != BLUEval){
  BLUEcount = BLUEval;
  }
  //Encoder
  if (count != brightness){
  Serial.print("encoder possition=");
  Serial.println(brightness);
  count=brightness;
  }
  
}

thanks for all your help guys.

I guess i'm just not ready to embrace it.

Now that you have something that works, it would be a good idea to revisit that decision. Learning how to write non-blocking code is a good thing. What happens if you want the fading to slow way down. Say one step per minute. You'd increase the delay time, and you'd increase the time that you need to hold the switch down to let the code know that a change was needed.

With the blink without delay paradigm, the code would know nearly instantaneously.