Interrupt question

Greetings,

I used AttachInterupt and a tactile switch to cycle between several RGB LED sequences/fades. When the button is pressed the mode will change however it only changes after the full code of the current sequence completes. For instance if you press the button in during the fades two for statements the current sequence completes prior to moving to the next sequence, or the one after the next if you press the button twice.

Is there a way to have the program respond to a button press in real time?

Also I use a pot to control the speed of the fade in one of the sequences. Again I must wait till both for statements complete until the duration of the delay, controlled by the pot, is reassessed. Is it possible to have this value update in real time?

Thanks again.

what's the structure of your code ?

if you use the ISR to set a variable like "byte button_pressed=1" and "byte choose_function++" and then some if-s in your normal code to decide what to run, I guess you'll have to monitor button_pressed in your fader loops as well. if it is set, just exit the loops.

void setup() {
  volatile byte button_pressed=0;
  volatile byte choose_function=0;
  attachInterrupt(0, read_button, RISE);
}

void loop() {
  switch(choose_function) {
  
    case 0:
      fader_0();
    break;
  
    case 1:
      fader_1();
    break;
  
    case 2:
      fader_2();
    break;
  
    default:
}

void read_button(void) {
  button_pressed=1;
  if(choose_function<2) {
    choose_function++;
  }
  else {
    choose_function=0;
  }
}

void fader_0(void) {
  for( whatever ) {
    // whatever
    if(button_pressed=1) { // this should be in the outermost for loop, if you use nested for loops
      button_pressed=0;
      break; // exit the for loop, exit fader_0()
    }
  }
}

to make your code be more responsive to the pot settings, you could put more analogRead() calls into the fader functions for updating it more frequenctly, or read the pot with another interrupt like TIMER2_OVF_vect. the latter will currently not work with the attachInterrupt function, but you'd have to write your own code for it. it's not too hard, some stuff is in the playground too.

For starters, thanks for the info.

As for the pot input being more responsive, as soon as I read your response the fact that I should have put an analog read in each for statement became painfully obvious to me. I adjusted the code and it works great. I plan on looking into your second suggestion for this issue later just to expand my knowledge.

When next I get some free time I plan on adding code to monitor the button presses in the fades as suggested, I'll let you know how that turns out.

As far as the structure of my code, listed below is the hopefully not too poorly written sketch. I am slowly adding functionality as I go and troubleshooting as req'd.

/*
 *RGB LED LAMP PROJECT 
 *
 */
volatile int Mode = 0;

int fast = 0;

int redPotPin = 1;    // select the input pin for the potentiometer
int greenPotPin = 2; 
int bluePotPin = 3;

int redLedPin = 9;   // select the pin for the LED
int greenLedPin = 10; 
int blueLedPin = 11;

int redVal = 0;       // variable to store the value
int greenVal = 0;
int blueVal = 0;

void setup() {

  attachInterrupt(0, next, RISING); // Button attached to interrupt 0, digital pin 2, 
                                    // to trigger fuction next when button goes from low to high  
  Serial.begin(9600);

  pinMode(redLedPin, OUTPUT);  // declare the ledPin as an OUTPUT
  pinMode(greenLedPin, OUTPUT);
  pinMode(blueLedPin, OUTPUT);
}

void loop(){


  // Now do whatever the Mode indicates
  if (Mode == 0) { 
    redVal = analogRead(redPotPin);    // read the value from the sensor
    analogWrite(redLedPin, redVal/4);  // convert from 0-1023 to 0-255 and apply value to LED

    greenVal = analogRead(greenPotPin);   
    analogWrite(greenLedPin, greenVal/4);   

    blueVal = analogRead(bluePotPin);    
    analogWrite(blueLedPin, blueVal/4);   
  }

  if (Mode == 1) {
    { 
      analogWrite(greenLedPin, 0);
      analogWrite(redLedPin, 0);
      analogWrite(blueLedPin, 0);
      fast = analogRead(redPotPin)/50;
      fast = max(fast, 1);              // limits fast to a min. of 1 by selecting
    }                                   // The higher of the two values ,fast or 1,
                                        // and asigining it to fast.  
    for (int redVal=0; redVal<=255; redVal++) {
      analogWrite(redLedPin, redVal);
      fast = analogRead(redPotPin)/50;
      fast = max(fast, 1);  
      delay(fast);
    }
    for (int redVal=255; redVal>=0; redVal--) {
      analogWrite(redLedPin, redVal);
      fast = analogRead(redPotPin)/50;
      fast = max(fast, 1);  
      delay(fast);
    }
  }

  if (Mode == 2) {
    for (int greenVal=0; greenVal<=255; greenVal++) {
      analogWrite(greenLedPin, greenVal);
      delay(10);
    }
    for (int greenVal=255; greenVal>=0; greenVal--) {
      analogWrite(greenLedPin, greenVal);
      delay(10);
    }

  }
  if (Mode == 3)  { 
    for (int blueVal=0; blueVal<=255; blueVal++) {
      analogWrite(blueLedPin, blueVal);
      delay(10);
    }
    for (int blueVal=255; blueVal>=0; blueVal--) {
      analogWrite(blueLedPin, blueVal);
      delay(10);
    }

  }    
}

void next()
{
  if (Mode == 0) {          // 
    Mode = 1;               // 
  } 
  else {
    if (Mode == 1) {        // 
      Mode = 2;             // 
    } 
    else {
      if (Mode == 2) {      // 
        Mode = 3;           // 
      } 
      else {
        if (Mode == 3) { // above 3 it returnes to 0 
          Mode = 0;           // 
        }
      }
    }
  }
}

Any further input/suggestions are welcome.

Thanks again.

Done!
At lease with the frame of the sketch.
I added "if (Mode != 2) break;" to each for statement, adjusting the 2 to whatever the # Mode it was in obviously.

  if (Mode == 2) {
    reset();
    for (int greenVal=0; greenVal<=255; greenVal++) {
      analogWrite(greenLedPin, greenVal);
      if (Mode != 2) break;
      delay(10);
    }
    for (int greenVal=255; greenVal>=0; greenVal--) {
      analogWrite(greenLedPin, greenVal);
      if (Mode != 2) break;
      delay(10);
    }

That seems to have done the trick. Ironic how after reading you advice the next chapter in my C book explained continue, break, and switch case.
In any case thanks again.

It's looking a lot like the RGB controller I posted about here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213217295

I just ordered a PCB for the shield so hopefully I'll have a working protoyupe soon.