Switch case not running PWM functions properly

Hello and thank you

Right now I am working on fading in and out two channels on a TLC5940 using a switch case statement.
The statement switches cases after a decided time.
Eventually I will have a few switch case statements fading multiple channels/RGBs.

The switch case statement itself is sound, I used it for another project.
The fade functions work on their own outside of the switch case.
Yet when I put the fade functions in the switch case they do not fade. Each time the case switches they are either instantly turned on or turned off.

This (knock on wood) is one of my last hurdles for this project.

Any insight or help would be much appreciated.

#include "Tlc5940.h"  //Tlc5940 library   https://code.google.com/p/tlc5940arduino/


//--------Fade Variables----------------------

long previousMillis = 0;        
long inter = 10;           //Fade increase/decreases by 10 each pass       
int fadeValueOn = 0;       // Initial value for fading on 
int fadeValueOff = 4095;   // Initail value for fading off

//-----------Switch Case/Count Variables----------------------

int led1State = 0;
long int led1time = 10UL;
unsigned long count1 = 0;


boolean timeout(unsigned long *marker, unsigned long interval) {   //Switches cases after decided time
  if (millis() - *marker >= interval) { 
    *marker += interval;    
    return true;       
  } 
  else return false;
}

void setup(){
  
  Serial.begin(9600);
  Tlc.init();         //initialize tlc5940
  led1time = 1UL;
  led1State = 0;
       
}

void loop() {

rgbFades();

}


//========================Switch Case===================

  void rgbFades(){ 
   
   if (timeout(&count1, led1time )) {
    switch (led1State) {
    case 0: 
      {           
        
        led1State = 1;               
        led1time = 5000UL; 
        Serial.println("Case0");        
        fadeOn();
        break; 
      }

    case 1: 
      {
        
        led1State = 2;               
        led1time = 7000UL; 
        Serial.println("Case1");        
        fadeOff();
        break; 
      }

    case 2: 
      {
        
        led1State = 3;
        led1time = 5000UL;
        Serial.println("Case2");
        fadeOn();
        break; 
      }

    case 3: 
      {
        Serial.println("Case3");
        led1State = 0;
        led1time = 3000UL;
        fadeOff();
        break; 
      }
    }
   }
  }


//============Fade Functions=========================


  
void fadeOn(){  
   unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;   

if(fadeValueOn <= 4095, fadeValueOn +=5) {
    
    Tlc.set(21, fadeValueOn);                //  21 = tlc channel
    Tlc.set(22, fadeValueOn);                //  22 = tlc channel
} 
          
    Tlc.update(); 
   }
  }


void fadeOff(){ 
   
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;
    if(fadeValueOff >=0, fadeValueOff -=5){
      Tlc.set(21, fadeValueOff);              // 21 = tlc channel
      Tlc.set(22, fadeValueOff);              // 22 = tlc channel
 Tlc.update(); 
   }
   }
}

Hi 1rulon1

The statement switches cases after a decided time.

It looks like the state changes on the first pass through each case ...

    case 0: 
      {                   
        led1State = 1;               
        led1time = 5000UL; 
        Serial.println("Case0");        
        fadeOn();
        break; 
      }

Each call to fadeOn() sets the channel value and increments that value, but needs to be called repeatedly to achieve the fade, I guess? However the switch statement does not execute again until the 5000UL timeout has expired and, when it does, the state has changed.

Maybe you need two timers: one to set the interval between each step in the fades, and a second to control changing states. Alternatively, make the state change dependent on completing the fade.

Regards

Ray

Awesome, Thank you Ray,

I like the idea of changing the state after the fade is done. I may yet need a little help.

I put a

boolean next = false;

in the beginning
and put it at the end of my fade function

void fadeOn(){  
   unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;   

if(fadeValueOn <= 4095, fadeValueOn +=5) {
    
    Tlc.set(21, fadeValueOn);                //  21 = tlc channel
    Tlc.set(22, fadeValueOn);                //  22 = tlc channel
} 
if(fadeValueOn == 4095)(
next = true;
  }
          
    Tlc.update(); 
   }
  }

The part I am a little confused on is how to change the switch case boolean operator function:

boolean timeout(unsigned long *marker, unsigned long interval) {   //Switches cases after decided time
  if (millis() - *marker >= interval) { 
    *marker += interval;    
    return true;       
  } 
  else return false;
}

and

 if (timeout(&count1, led1time )) {

Thanks again.

If you use the boolean next to control when you change state, you should remove ...

if (timeout(&count1, led1time )) {

and this ...

        led1time = 5000UL;

You want to execute the switch statement each time you call rgbFades(). Your fade functions have their own timer based on inter to control how quickly the fade steps happen.

This will have the effect of making each fade have the same overall duration. If this is NOT what you want, you can change the value of inter depending on which state you are in.

But either way you also need to change your case statements to use the boolean variable to move to the next state. For example ...

    case 0: 
      {                   
        Serial.println("Case0");        // this will print every 10ms :-)
        fadeOn();
        if (next)
        {
            next = false;
            led1State = 1;
        break; 
      }

Again Ray, Thank you

I am pretty excited, I have it pretty close.

I think there is something wrong with my true/falses.

The first fadeOn() fades in normally but then the sequential fadeOn()s turn on quickly. The fadeOff()s seem to fade evenly.

This is what I have:

#include "Tlc5940.h"  //Tlc5940 library   https://code.google.com/p/tlc5940arduino/


//--------Fade Variables----------------------

long previousMillis = 0;        
long inter = 10;           //Fade increase/decreases by 10 each pass       
int fadeValueOn = 0;       // Initial value for fading on 
int fadeValueOff = 4095;   // Initail value for fading off

//-----------Switch Case Variables----------------------

int led1State = 0;
boolean next = false;

void setup(){
  
  Serial.begin(9600);
  Tlc.init();         //initialize tlc5940
  led1State = 0;
       
}

void loop() {

rgbFades();

}


//========================Switch Case===================

  void rgbFades(){ 
    
    switch (led1State) {
       case 0: 
        {                 
        fadeOn();
        if (next){
            next = false;
            led1State = 1;
        }
        break; 
      }
      
      
    case 1: 
        {                 
        fadeOff();
        if (next){
            next = false;
            led1State = 2;
        }
        break; 
      }


    case 2: 
         {         
        fadeOn();
        if (next){
            next = false;
            led1State = 3;
        }
        break; 
      }


    case 3: 
      {                           
        fadeOff();
        if (next){
            next = false;
            led1State = 0;
        }
        break; 
      } 
      }
    }
       
      
   
  


//============Fade Functions=========================


  
void fadeOn(){  
   unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;   

if(fadeValueOn <= 4095, fadeValueOn +=5) {
    
    Tlc.set(21, fadeValueOn);                //  21 = tlc channel
    Tlc.set(22, fadeValueOn);                //  22 = tlc channel
}
 Tlc.update(); 
   }
if(fadeValueOn >= 4095){
next = true;
  }  
 }
  


void fadeOff(){ 
   
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;
    if(fadeValueOff >=0, fadeValueOff -=5){
      Tlc.set(21, fadeValueOff);              // 21 = tlc channel
      Tlc.set(22, fadeValueOff);              // 22 = tlc channel
    }
 Tlc.update();
    } 
 if(fadeValueOn <= 0){
next = true;
  }
 }

Your fade functions use two different variables to set the value: fadeValueOn and fadeValueOff.

Sounds like you may need to check where these are being initialised, how they stand when you go from fade on to fade off etc, and look at how you decide when to set next.

Maybe you only need one variable?

As always, Thank you Ray

I think I got it.

Here is the code for anyone else who might like it.

#include "Tlc5940.h"  //Tlc5940 library   https://code.google.com/p/tlc5940arduino/


//--------Fade Variables----------------------

long previousMillis = 0;        
long inter = 10;           //Fade increase/decreases by 10 each pass       
int fadeValue = 0;       // Initial value for fading on 
  

//-----------Switch Case Variables----------------------

int led1State = 0;
boolean next = false;

void setup(){
  
  Serial.begin(9600);
  Tlc.init();         //initialize tlc5940
  led1State = 0;
       
}

void loop() {

rgbFades();

}


//========================Switch Case===================

  void rgbFades(){ 
    
    switch (led1State) {
       case 0: 
        {                 
        fadeOn();
        if (next){
            next = false;
            led1State = 1;
        }
        break; 
      }
      
      
    case 1: 
        {                 
        fadeOff();
        if (next){
            next = false;
            led1State = 2;
        }
        break; 
      }


    case 2: 
         {         
        fadeOn();
        if (next){
            next = false;
            led1State = 3;
        }
        break; 
      }


    case 3: 
      {                           
        fadeOff();
        if (next){
            next = false;
            led1State = 0;
        }
        break; 
      } 
      }
    }
       
      
   
  


//============Fade Functions=========================


  
void fadeOn(){  
   unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;   

if(fadeValue <= 4095, fadeValue +=5) {
    
    Tlc.set(21, fadeValue);                //  21 = tlc channel
    Tlc.set(22, fadeValue);                //  22 = tlc channel
}
 Tlc.update(); 
   }
if(fadeValue >= 4095){
next = true;
  }  
 }
  


void fadeOff(){ 
   
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > inter) { 
    
    previousMillis = currentMillis;
    if(fadeValue >=0, fadeValue -=5){
      Tlc.set(21, fadeValue);              // 21 = tlc channel
      Tlc.set(22, fadeValue);              // 22 = tlc channel
    }
 Tlc.update();
    } 
 if(fadeValue <= 0){
next = true;
  }
 }