Non blocking fade triggered on time of day

I have wrote some code to do a non blocking fade

struct Leds {
unsigned long Interval;
unsigned long lastmillis;
int Start_Value;
int Current_Value;
int Finish_Value;
bool Direction;
bool Done;
};

Leds Led [16];

void SetFade (int x, int level, unsigned long fadetime ){

Led[x].Finish_Value = level;
Led[x].Start_Value=Led[x].Current_Value;
if (!(Led[x].Start_Value == Led[x].Finish_Value)){
Led[x].Interval=fadetime/(abs(Led[x].Start_Value - Led[x].Finish_Value));
if (Led[x].Start_Value < Led[x].Finish_Value){
Led[x].Direction = true;
}
else{
 Led[x].Direction = false; 
}
Led[x].Done=false;
}
}


void UpdateFade (int x){
unsigned long microo = micros();

if (!Led[x].Done){
if ((microo-Led[x].lastmillis) >= Led[x].Interval)
{
// check direction

  if (Led[x].Direction)
  { 
    Led[x].Current_Value++;
  } else {

    Led[x].Current_Value--;
  }
}
Led[x].lastmillis=micros();
}

if (Led[x].Current_Value == Led[x].Finish_Value)
{
Led[x].Done=true;
 }



}

inside the main loop()

I call the setled function to set the fade going
and the Updatefade() each time round the loop.

loop(){
if (Led[0].Done){SetFade (0,255,1000 );}
if ((Led[0].Done)&(Led[0].Current_Value==255))       {SetFade (0,0,50);}
//Serial.print(Led[0].Current_Value); Serial.print("  ");
//Serial.println(Led[0].Done);
UpdateFade(0);
driver.getPin(PCA9685_LED0).setValueAndWrite(LUT_1024[Led[0].Current_Value]); // set one of the pca9685 pwm led drivers to led 0's current value
}


//   do other stuff loop comes out at 146us

I cut out all the fluff , but theres lecd screen updating , temps , humidity ect ect

This works but it is slow , my loop is 146us (esp32)

Any ideas as tho why ?? I cant see a reason is shouldn't fade in fast with a 3mico iinterval

Isn't it simply the i2c Comms that are taking most of the time? You could try 400KHz speed.

Thanks PaulRB
I thought that too (tho i would have thought that would increase the loop time also as the calls to read are in functions called from loop() ).
but I have had it at wire.setclock(3400000); and made no difference :(.

Maybe it could be the OTA update code ?

I was thinking maybe I could pin the function to an interupt , but there are 16 led's worth of those structs to update , I though maybe pin the task to core2 , but again thats running wifi ect ,, so might cause issues there too ?

Madmanmav:
i would have thought that would increase the loop time also as the calls to read are in functions called from loop()

I don't understand. How do you know it is not affecting the time loop() takes to execute? It's hard for me to fit all the pieces of the puzzle in my head without the complete code. Is it still too large to post between code tags?

Thanks PaulRB

I think I have cracked it , I missed a catch in the loop and the one thing I skipped ,was the one thing taking 147ms ;lol

Reading a DS18B20 onewire probe

I have split the reads across N*loops , so not cured entirely (I get a slight glitch one any fade with an interval < 147ms ) but far better.

Thanks for the pointer though , made me dig again and spot it.

The full code probably wouldn't fit (lot of functions) , but the code posted works well as long as the loop time is less than the interval , in theory you could make the array any size I suppose (memory and cycles excluded ofcourse). In my case I am setting 16 pwm channels of a PCA9685 driving power Leds via 700ma buck drivers :slight_smile:

At the moment its just the one to prove the concept , i'll make an updateall() function to loop through the array with Update(x), then SetFade the same from another array loaded from flash , triggered on time of day from the RTC , but the guts shown does work :slight_smile:

I haven't done any C++ in ages, so its probably rubbish , but I can work on it in situ programming over WiFi

Thanks for taking the time to have a look , I am sure I will run into more hiccups.

I missed a catch in the loop and the one thing I skipped ,was the one thing taking 147ms ;lol

Reading a DS18B20 onewire probe

I cut out all the fluff , but theres lecd screen updating , temps

That's what I misunderstood. I though you were saying you cut out the updating of temps, but you didn't say that, only cutting out the "fluff" whatever that is...

That's what I misunderstood. I though you were saying you cut out the updating of temps, but you didn't say that, only cutting out the "fluff" whatever that is...

I meant the rest of the code in the loop just leaving what handled the LEDs.

struct Leds {
unsigned long Interval;
unsigned long lastmillis;
int Start_Value;
int Current_Value;
int Finish_Value;
bool Direction;
bool Done;
};



Leds Led [16];




void SetFade (int x, int level, unsigned long fadetime ){
Led[x].Finish_Value = level;
Led[x].Start_Value=Led[x].Current_Value;

if (!(Led[x].Start_Value == Led[x].Finish_Value)){
Led[x].Interval=fadetime/(abs(Led[x].Start_Value - Led[x].Finish_Value));
}

if (Led[x].Start_Value < Led[x].Finish_Value){
Led[x].Direction = true;
}

if (Led[x].Start_Value > Led[x].Finish_Value){
Led[x].Direction = false;
}

if (Led[x].Start_Value == Led[x].Finish_Value){
Led[x].Done = true;
}
else{
Led[x].Done=false;
}
}


void UpdateFade (){  
//int x=0;
for (int x =0 ; x <=15; x++){
unsigned long Mills = millis();
if (!Led[x].Done){ 
    if ((Mills-Led[x].lastmillis) >= Led[x].Interval)
{ 
// check direction

  if (Led[x].Direction){ 
    Led[x].Current_Value++;

if (Led[x].Current_Value >= Led[x].Finish_Value)
      { 
          Led[x].Done=true; 
      } 
  } 

  if (!Led[x].Direction)  { 
    Led[x].Current_Value--;

    if (Led[x].Current_Value <= Led[x].Finish_Value) { 
          Led[x].Done=true; 
      } 
  } 

Led[x].lastmillis=millis();
}
}
}
}

I cahnged the functions above to catch a couple of exceptions i was running into