Problems with Boolean and Interrupts

I’m at my wits in troubleshooting two problems I have with the code below. The project is a control program for a string of TM1809 controlled LED lights.

The main program is a loop that picks that pattern to run and calls the pattern. That part works as expected. Most of the patterns work as expected. I’m having problems with the Sparkle() and Crossfade() functions. They have a Boolean variable dir that tells them if they should be starting on the right and moving left or starting on the left and moving right. The problem is the dir variable is not updating correctly. I stuck a serial print line in the code to see what the value of dir is before and after each function call. It increments to a random number every time the function is called. The first time it will run correctly based on what is defined in the variable declaration at the beginning of the program. After that it is completely random. It will be 64, then 614, then 1208, then 0, then 50. I don’t see how it is possible for a value that should be 0 or 1. I’m also getting random characters in the serial stream occasionally.

Due to size issues, I only have a single button to change the pattern. Some of the patterns take a long time to run. I wanted to be able to change patterns anytime without waiting for the end of the pattern to poll the button. I decided to use an interrupt. That part works well, but I can’t seem to debounce the interrupt. I want it to do a single increment per push, but it will jump 1, 5, 8 or increments per push.

If anyone has any insight I would appreciate it.

   #include <FastLED.h>
    #include <Arduino.h>
    
    
    #define NUM_LEDS 48
    #define DATA_PIN 5
    #define SELECT_PIN 3
    #define NOT_AN_INTERRUPT -1
    
    const byte interruptPin = 2;
    CRGB leds[NUM_LEDS];
    int Bottles=16;
    volatile int pattern=5;
    int maxpattern=8;
    boolean dir=0;
    int leftcolor=135;
    int rightcolor=255;
    long debouncing_time = 500; //Debouncing Time in Milliseconds
    volatile unsigned long last_micros;
    
void setup() 
{ 
       FastLED.addLeds<TM1809, DATA_PIN>(leds, NUM_LEDS);
       pinMode(interruptPin, INPUT_PULLUP);
     attachInterrupt(digitalPinToInterrupt(interruptPin), SetPattern, FALLING);
       Serial.begin(9600);
} 

void SetPattern(){
   detachInterrupt(digitalPinToInterrupt(interruptPin));
   if((long)(micros() - last_micros) >= debouncing_time * 1000) {
           if (pattern < maxpattern){
                pattern=pattern+1;
                }
          else{
            pattern=1;
            }
         last_micros = micros();
   }
   
  attachInterrupt(digitalPinToInterrupt(interruptPin), SetPattern, FALLING);

}
  
void loop() {
  if (pattern ==1){
    Patriotic();
      }
    if (pattern ==2){
    Solid();
      }
    if (pattern ==3){
    ChaseGreen();
      }
    if (pattern ==4){
    ChaseRandom();
      }        
    if (pattern ==5){
    Fade();
      } 
    if (pattern ==6){
    ChaseRed();
      }  
    if (pattern ==7){
    CrossFade();
      } 
    if (pattern ==8){
    Sparkle();
      }           


 }

 
 
 
 void Sparkle(){
            if(dir){
                   Serial.println("I should be going left"); 
                  dir = 0;
                   for(int Bottle = 0; Bottle < Bottles; Bottle++) {
                   
                  int H= random(0,255);
                  int S = 250;
                  int I = 250;
                  int Ilow=150; 
                   
                   
                   
                  leds[Bottle*3] = CHSV(H,S,I);
                  leds[Bottle*3+1] = CHSV(H,S,I);
                  leds[Bottle*3+2] = CHSV(H,S,I);
                  FastLED.show();
                  
                  delay(400);
                  leds[Bottle*3] = CHSV(H,S,Ilow);
                  leds[Bottle*3+1] = CHSV(H,S,Ilow);
                  leds[Bottle*3+2] = CHSV(H,S,Ilow);
                  FastLED.show();
                   }
                   
            }
            
            if(!dir){ 
                  Serial.println("I should be going right");
                  dir=1;
                  for(int Bottle = Bottles; Bottle > 0; Bottle--) { 
                  int H= random(0,255);
                  int S = 250;
                  int I = 250;
                  int Ilow=150; 
                   
                   
                   
                  leds[Bottle*3] = CHSV(H,S,I);
                  leds[Bottle*3+1] = CHSV(H,S,I);
                  leds[Bottle*3+2] = CHSV(H,S,I);
                  FastLED.show();
                  
                  delay(400);
                  leds[Bottle*3] = CHSV(H,S,Ilow);
                  leds[Bottle*3+1] = CHSV(H,S,Ilow);
                  leds[Bottle*3+2] = CHSV(H,S,Ilow);
                  FastLED.show();
                   }
            }
         Serial.print("DirectionIn function =");
         Serial.println(dir);    
            
 }
 
 
 void CrossFade(){
     int stepsize=0;
     int S = 250;
     int I = 250;   
   
   if (dir){
           int H=leftcolor;  
           rightcolor=random(0,255);
           stepsize=abs(rightcolor-leftcolor)/Bottles;
         for(int Bottle = 0; Bottle < Bottles; Bottle++) {
                  leds[Bottle*3] = CHSV(H,S,I);
                  leds[Bottle*3+1] = CHSV(H,S,I);
                  leds[Bottle*3+2] = CHSV(H,S,I);
                  FastLED.show();
                  delay(600);
                  if (rightcolor>leftcolor){
                    H=H+stepsize;
                  }
                  if (rightcolor<leftcolor){
                    H=H-stepsize;
                  }
             }
       dir=!dir;
   }
     if(!dir){
     int H=rightcolor;  
     leftcolor=random(0,255);
     stepsize=abs(rightcolor-leftcolor)/Bottles;
   for(int Bottle = Bottles; Bottle > 1; Bottle--) {
            leds[Bottle*3] = CHSV(H,S,I);
            leds[Bottle*3+1] = CHSV(H,S,I);
            leds[Bottle*3+2] = CHSV(H,S,I);
            FastLED.show();
            delay(600);
            if (rightcolor>leftcolor){
              H=H+stepsize;
            }
            if (rightcolor<leftcolor){
              H=H-stepsize;
            }
         }
         dir=!dir;
     }
     
 
 }
 
 
 
 void Fade(){
       int H=random(0,255);
       int S=255;
   
       for (int i=0; i<NUM_LEDS; i++){
          leds[i]=CRGB::Black;
         }
         for (int I=0; I<250; I++){
         
           for (int i=0; i<NUM_LEDS; i++){
           leds[i]=CHSV(H,S,I);
           }
           FastLED.show();
           delay(100);
         }
        for (int I=250; I>0; I--){
           for (int i=0; i<NUM_LEDS; i++){
           leds[i]=CHSV(H,S,I);
           }
           FastLED.show();
           delay(20);
         }
}
         
 
 void ChaseRandom(){
           for(int Bottle = 0; Bottle < Bottles; Bottle++) { 
            int H= random(0,255);
            int S = 250;
            int I = 250; 
             
             
             
            leds[Bottle*3] = CHSV(H,S,I);
            leds[Bottle*3+1] = CHSV(H,S,I);
            leds[Bottle*3+2] = CHSV(H,S,I);
            FastLED.show();
            // clear this led for the next time around the loop
            delay(300);
            leds[Bottle*3] = CRGB::Black;
            leds[Bottle*3+1] = CRGB::Black;
            leds[Bottle*3+2] = CRGB::Black;
        }
}
  
 
 
 void ChaseGreen(){
           for(int Bottle = 0; Bottle < Bottles; Bottle++) { 
            leds[Bottle*3] = CRGB::Green;
            leds[Bottle*3+1] = CRGB::Green;
            leds[Bottle*3+2] = CRGB::Green;
            FastLED.show();
            // clear this led for the next time around the loop
            delay(300);
            leds[Bottle*3] = CRGB::Black;
            leds[Bottle*3+1] = CRGB::Black;
            leds[Bottle*3+2] = CRGB::Black;
        }
}

 




}
    #define NUM_LEDS 48
...    
    CRGB leds[NUM_LEDS];
    int Bottles=16;
...
                  for(int Bottle = Bottles; Bottle > 0; Bottle--) {
...                  
                  leds[Bottle*3] = CHSV(H,S,I);
                  leds[Bottle*3+1] = CHSV(H,S,I);
                  leds[Bottle*3+2] = CHSV(H,S,I);

Bottle will start off at 16, you multiply by 3 and add 2. That is 50. That exceeds the bounds of your array by 3. That will corrupt nearby variables, possibly "dir".

Since CRGB is a struct which is 3 bytes in size, that means you have exceeded the array by 9 bytes. It looks to me that "dir" is about 6 bytes away.

You don't need to detach and re-attach the interrupt in the ISR. Interrupts are off there anyway.

That makes sense. I knew it had to be something simple, but it has been kicking my but for three days.

Thank you!!

Now if I can sort out the interrupt debouncing this project will be done.

gte718p: Now if I can sort out the interrupt debouncing this project will be done.

It might be easier to fix the led code to be non-blocking so you can just poll your button in loop.

Delta_G: It might be easier to fix the led code to be non-blocking so you can just poll your button in loop.

I'm not sure I understand that. Other then adding the polling code to every sub function I don't see how to unblock it. I guess it would be effective, but not necessarily elegant to just keep calling a polling function at random place in each function.

There are some functions that I didn't include that are really long for loops. You would have to know where in the code you were ignored to time the button push. I have a very similar LED project that I did that way and was never happy with it. In some places the polling statement was called very quickly in others there was a long time between pollings.

  1. Don't use delay anywhere
  2. Get rid of the long for loops

One of the harder concepts for beginners is to get away from the idea of coding the whole procedure as a set of steps and into the mindset of coding as a set of conditionals. Write your functions so they check to see if it is time for the next step and take one small step at a time and then exit only to be called again after some short time to take the next step.

The problem with the interrupts appears to have been a chip issue. I loaded the program on a new Nano and it is working perfectly.