Cosine fading of more leds - without delay

Hi,

I have quite newbie question: I want to get rid of the delay() in my code, but I cant figure how to write the same working code with millis. Please can anyone give me some advice.
I want to use it for fading more leds at same time. I use metro for timing the fading events and
fading itself is some cosine function that I´ve found here on the forum.
Thank you very much!!!
here is the important part of the code:

if (ledMetro1.check() == 1) { // check if the metro has passed it's interval .     
         for(int i=0; i<255; i++)
         {
         state1 = abs(-127+127*cos(4*PI/500*i));		
         analogWrite(LED1, state1);           
         [color=red] delay(2);[/color]
         }
       }

I want to get rid of the delay() in my code

Why?

Yes, I know we harp on people that want to use delay(), because it is easy, but still want to do something else.

In your case, a 2 millisecond delay hardly seems worth worrying about.

Even doing that 2 millisecond delay 255 times will only take half a second.

Because I am using 9 fading leds at the same time. With delay() the fading is interrupted and not working well. ...and some of the leds has much longer delay( 50-250ms ).
thats is the reason...

Because I am using 9 fading leds at the same time. With delay() the fading is interrupted and not working well. ...and some of the leds has much longer delay( 50-250ms ).
thats is the reason...

here is the important part of the code:

So that wasn't the important part of the code.

You need to use millis() to record what time a LED changed state. On each pass through loop, you need to see if it is time to change state again. If so, then you figure out what the new state is, make that the new state, and record the time.

Doing this, in conjunction with the Metro library, is going to be an exercise in frustration. It would be best to get rid of the Metro library and do all the state change stuff yourself, using millis().

even:

state1 = 255*cos(PI/125*i));      // or even 255*cos(0.025132741 * i);
analogWrite(LED1, state1);

but this works only if state1 is a byte I think (not tried);

I wonder if you can really see the difference with just a linear fading as it all happens within half a second.

without the delay and 9 leds you get something like this ... (just a snippet to get the idea, not tested)

int LED[9] = {....};

unsigned long previousTime[9] = {....}; // probably all 0 but other values possible
long threshold[9] = {...}; probably all the same value but ....
uint8_t ii[9];

void loop()
{
  for (int led=0; led< 9 led++)
  {
    if (millis() - previousTime[led] > threshold[led])
    {
      previousTime[led] = millis();
      ii[led]++;  // auto wraps after 255 to 0 as it is a byte 
      analogWrite(LED[led], 255 * cos(PI/125* ii[led]) );
    }
  }

  // do other things here 
}

Thanks all of you for advice!

PaulS:
Doing this, in conjunction with the Metro library, is going to be an exercise in frustration. It would be best to get rid of the Metro library and do all the state change stuff yourself, using millis().

why? are there some unwanted intreferencies between metro library and millis()?
I ´ve never worked with metro...
I can imagine how to do it just with millis() the same things, i hope..

to robtillaart: thanks a lot, i will test it how it works and let know

robtillaart:
I wonder if you can really see the difference with just a linear fading as it all happens within half a second.

in this speed not, but in slower speeds the difference is really visible.
...to be honest I dont exactly understand what the function state1 = 255cos(PI/125i)); really do :~, but the resulting led fading is ok for me :slight_smile:

255cos(PI/125i);

with an increasing i you get the familiar cosine wave which returns a value between -1 and 1.
The factor (PI/125) defines the stepsize (speed) whcih can be increased or decreased.

multiplying the cos() with 255 gives a value between -255 and 255,
by assigning this value to a byte the value will allways be between 0 and 255 and following more or less a cos() curve. // -1 == 255 , -2 == 254 etc

but in slower speeds the difference is really visible

OK That I can imagine..

The original version is correct, sorry, my mistake, I removed a post.

Code:
state1 = 255*cos(PI/125*i));      // or even 255*cos(0.025132741 * i);
analogWrite(LED1, state1);

First of all it would return +0.255 and -0..255. Even if robtillaart is right, and we will get only positive values 0..255, bridge rectified cos would be at the output, which is not the same as cos, and poor form to drive leds.

  for (int led=0; led< 9 led++)

An int for 0 to 9, huh?

An int for 0 to 9, huh?

optimized typing iso type :wink:

robtillaart:
even:

state1 = 255*cos(PI/125*i));      // or even 255*cos(0.025132741 * i);

analogWrite(LED1, state1);

robtillaart:
this function is producing not smooth fading. there are two drops.
I dont know why(...) but this is the result that I see on led when I ve uploaded this sketch.
So I am using the function I´ve posted here in the beginnig.
Ideally I would like to use ramp function that I can define its curve. From linear to exponential...
The using of array is smart.
Now I will try to get rid of metro. Delay is fortunately out of game...

Hi JuraJ,

Just saw an improvement upon an earlier post which seems to be removed by now, I did not check the function from your code, my error :frowning:

retry:

abs(-127+127cos(4PI/500i)); ==> abs(-127+127cos(PI/125*i)); // remove multiply

as cos() is symmetric the abs() can be removed too

==> 127 + 127*cos(PI/125 * i); // function and negation less

Yeah this is different from my optimization, sorry :blush:

please give it a try,