Hi all,
I am trying to use millis() to create a fade in and fade out effect with the led. I developed the code below, which creates only the fade in, and misteriously enters in in fade_out() function but the timing seems to be completely ignored.
I really can't spot the error. Or there is something that I don't get with the use of millis()?
int LED_pin = 3;
unsigned long current_millis = 0; // stores the value of millis() in each iteration of loop()
unsigned long fade_in_timer_duration = 150;
unsigned long fade_in_timer = 0;
unsigned long fade_out_timer_duration = 150;
unsigned long fade_out_timer = 0;
int fade_in_value = 0; //initial value for fade in
int fade_out_value = 255; //initial value for fade out
bool fade_in_enabled = true;
bool fade_out_enabled = false;
void fade_in_millis() {
if ((current_millis - fade_in_timer) >= fade_in_timer_duration) {
if (fade_in_value <= 255) {
analogWrite(LED_pin, fade_in_value);
fade_in_value += 5;
Serial.print("fade_in_value ");
Serial.println(fade_in_value);
} else {
fade_in_value = 0;
fade_out_enabled = true;
fade_in_enabled = false;
}
fade_in_timer += fade_in_timer_duration;
}
}
void fade_out_millis() {
if ((current_millis - fade_out_timer) >= fade_out_timer_duration) {
if (fade_out_value >= 0) {
analogWrite(LED_pin, fade_out_value);
fade_out_value -= 5;
} else {
fade_out_value = 255;
fade_in_enabled = true;
fade_out_enabled = false;
}
fade_out_timer += fade_out_timer_duration;
}
}
void setup() {
pinMode(LED_pin, OUTPUT);
fade_in_timer = fade_out_timer = millis();
}
void loop() {
current_millis = millis();
if(fade_in_enabled){
fade_in_millis();
} else if(fade_out_enabled){
fade_out_millis();
}
}
unsigned long current_millis = 0; // stores the value of millis() in each iteration of loop()
So, why is this global? If a variable is used only in one function, and is assigned a value every time the function is called, the variable does not need to be global.
if ((current_millis - fade_in_timer) >= fade_in_timer_duration) {
The value in fade_in_timer is a time, not a timer. The variable name sucks.
fade_out_timer += fade_out_timer_duration;
Adding times is not guaranteed to work. Subtracting is, unless the difference exceeds the value that the variable type can hold.
What do your Serial.print()s tell you is happening?
There is one led (regardless of what that led is doing), therefor I would use one millis timer and one variable for the brightness.
The millis timer should be fast enough to make it look smooth to the human eye.
Within that millis timer I would use math to make the led fade in and out. It is also possible to send a command to fade in, and later send a command to fade out.
Do you want to change the PWM value with 5 every 150 ms ? Then you could also change the PWM with 1 every 30 ms ?
When using math, it is possible to make a soft pulsating led, or even a heartbeat led.
This is only for special occasions:
fade_in_timer += fade_in_timer_duration;
fade_out_timer += fade_out_timer_duration;
You should not use that, unless you know what they do.
When you change from fade-in to fade-out, you forget to update the fade_out_timer.
When you change from fade-out to fade-in, you forget to update the fade_in_timer.
That would be less of a problem if you assign current_millis to those variables.
You can make the sketch work with:
- Add Serial.begin(9600) to setup.
- Use: fade_in_timer = current_millis; instead of the += ...
- And: fade_out_timer = current_millis; instead of the += ...
Then it works, but it is still not perfect.
If you explain precisely what you want, then I could alter the soft pulsating led for you.
Thanks a lot, I applied your suggestion and it works, I used :
fade_in_timer = current_millis; instead of the += ...
- And: fade_out_timer = current_millis; instead of the += ...
frodojedi:
but the timing seems to be completely ignored.
I think when the state changes you also need to initilize the start time for the other state - something like this
} else {
fade_in_value = 0;
fade_out_enabled = true;
fade_in_enabled = false;
fade_out_timer = currentMillis; // <-------------- NEW
}
I also think that fade_out_timer is a poor choice of variable name which may have contributed to the confusion. IMHO fade_out_start_time would be more meaningful
...R
Nothing wrong with writing code yourself, especially if you learn from it. But if you want easy you can grab the FadeLed library. Also comes with gamma correction to make the fade look better to the human eye.