You said you wanted the light to fade like a wave, in this case you probably want to approach this a bit differently.
Think of the sin function. For some x value, it outputs a y value. We can think of this in terms of your program. In the case of your program, time is the x value. So, we can say that
brightness = sin(time)
However, if we want to put this into code, we have to take some considerations about how your program treats numbers.
First, you have different types of numbers. I see that you already know how to use the int type. The type that we will need is called float. A float type is just a decimal. If you want to deal with precision, you'll need floats. There are even more precise version of floats called double. We will be using double in this program.
Next, we need to know how to use the sin() function in code. Arduino makes this really easy, it's just sin(). Some programming languages make you call Math.sin() or something of that nature. You can forget all of that on Arduino. It's just sin().
The next part is time. In Arduino, we figure out the time by using millis(). This will give the total number of milliseconds since the Arduino was turned on.
Now, I'm going to throw a piece of code at you, don't panic.
brightness = (sin( ((double)millis()/1000.0f ) * 2.0f * 3.14159265f )/2 + 0.5) * 255
Here is the same code color-coded for easier explanation:
brightness = (sin(((double)millis()/1000.0f ) * 2.0f * 3.14159265f )/2 + 0.5) * 255
Okay, starting with the blue part:
(double)millis()/1000.0f
millis() is good, however if we feed only millis() into the sin() function, we will have a very rapidly blinking light, and that's not what we want. So, we are scaling it back by dividing by 1000. The whole of this piece of code will be outputting the number of seconds since startup. Not only that, but we also cast the millis() value to double. That what the (double) part is for. On top of that, the 1000 isn't just 1000. It says 1000.0f. That's telling the arduino to treat it as a float. All of this together means we get the number of seconds since startup in decimal seconds. Which gives us a lot of smoothness.
Next, the orange part:
2.0f * 3.14159265f
This is making the sin function normalized. The period is now 1 second instead of 2pi seconds. 2 pi doesn't really mean much to us, so normalizing this value is nice. This is basically like saying:
y = sin(x * 2 * pi)
You can also put another value in here like:
2.0f * 3.14159265f / period
This will directly affect the period and the period will be whatever number is in the "period" variable.
Now, we're onto the green part:
/2 + 0.5
So, this bit of code is dividing the output of the sin function by 2, so it goes from -0.5 to 0.5 and adds 0.5 to it so it goes from 0.0 to 1.0. Why did we do this? Well, that feeds into the next colored area.
The teal colored code:
* 255
This takes the output of the value from 0 to 1 and multiplies it by 255. This ensures that the value is always somewhere between 0 to 255. We do this because AnalogWrite can only take a value from 0 to 255. So now your code looks like this:
int ledPin = 9;
void setup() {
}
void loop() {
double fadeValue;
fadeValue = (sin( ((double)millis()/1000.0f ) * 2.0f * 3.14159265f )/2 + 0.5) * 255;
analogWrite(ledPin, fadeValue);
}
Great! Now we have a wave. But, if we ever use a delay in here, it will just stop. How do we make it stop every time it goes to 0? Well, 2 ways. The first way, we could just check if fade value is equal to 0 and delay. However, using delay() is generally frowned upon because it causes something called "busy waiting". Instead, we're going to find a way to continue running without changing the fade.
So, without getting way too complex with the math, we can do something like the following:
int ledPin = 9;
int startFade = 0;
double period = 1.0; //period in seconds
void setup() {
}
void loop() {
int fadeValue;
if(millis() >= startFade)
{
double fadeValue;
fadeValue = (cos( ((double)(millis() - startFade + (period/2.0f) * 1000)/1000.0f ) * 2.0f * 3.14159265f / period)/2 + 0.5) * 255;
analogWrite(ledPin, fadeValue);
if(millis() - startFade == period * 1000)
{
startFade = millis() + 1000;
analogWrite(ledPin, 0);
}
}
}
A couple things I did:
Changed the sin function to a cos function. It's just easier to work with because it peaks at 0. Then, I shifted the wave over by half of a period so it starts at 0, climbs to 1 by t = 0.5, and comes back to 0 at t = 1. I also added the code that can deal with adjusting the period length. However, the really important part is:
if(millis() - startFade == period * 1000)
startFade = millis() + 1000;
This part is saying that once the time is right about the time that the led should be off, turn it off and set a new time where the fade should start again. Before it becomes that time, the fading code just won't run at all. Then, once it does we make sure to start the cos() at 0 again with:
millis() - startFade + (period/2.0f) * 1000
This is saying, take the millis and subtract off the time we start at, so we start at 0. Then, make sure to shift over by half of a period so the cos() value starts at 0.
So, that was a huge mouthful. However, I hope it helps you a ton. Honestly, using delay() at all is probably a bad idea and it will make you use it as a crutch. Think creatively and try to avoid delay whenever possible.
Also, if my code doesn't work, please tell me. I simulated it, so it should work. No guarantees though.