In the previous video we used analogWrite() to dim a LED (strip). We can make a fade effect when we gradually increase or decrease the analog output, step by step, with an interval time. A fade is nice for many applications … kitchen counter light, model railway overhead lighting (to gradually shift from night to day or vice versa) and even a red/green track signal has just that little extra eye candy with a short fade.
Read on below the video …
Let’s use a toggle switch for on/off and use the potentiometer to change the target brightness, declared as byte. The intermediate steps on the way to the target we’ll call current, also a byte.
#define SWITCH_PIN 2 // input for toggle switch #define POTM_PIN A0 // potmeter analog input #define LIGHTS_PIN 6 // output to FET module #define LED_PIN A5 // output to LED on switch panel #define FADE_INTERVAL 100 // [ms] time between fade steps byte target, current; // target and current pwm value unsigned long time_for_fadestep; void setup() { pinMode(SWITCH_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); Serial.begin(9600); } void loop() { if (digitalRead(SWITCH_PIN) == 0) { // toggle switch ON digitalWrite(LED_PIN, HIGH); target = map(analogRead(POTM_PIN), 0, 1024, 0, 256); } else { // toggle switch OFF digitalWrite(LED_PIN, LOW); target = 0; } if (millis() > time_for_fadestep) { time_for_fadestep = millis() + (unsigned long)FADE_INTERVAL; if (current < target) current++; // shorthand for current = current + 1 if (current > target) current--; // shorthand for current = current - 1 analogWrite(LIGHTS_PIN, current); Serial.print(target); Serial.print(" "); Serial.println(current); } }
Note the notation of current++ … it is shorthand for current = current + 1. Likewise current– is short for current = current – 1.
When we toggle the switch, the LEDs start to fade towards the target brightness, which can be changed with the potentiometer … yes, it works fine.
Of course we can play with the FADE_INTERVAL to determine how fast the fading takes place. For kitchen cabinet lighting you’d probably want it to reach the setpoint in just a couple of seconds … with a model railway day / night cycle simulation we probably like the fading to take half a minute or even more. And with a railway red/green signal we probably like it to take about a second. To fine tune such short fades, the steps of the millis() clock may even be too course. If so, we can use the micros() clock in stead. That is done in this example of a red/green signal change with a 1200 microseconds fade interval.
#define SWITCH_PIN 2 // input for toggle switch #define RED_PIN 5 #define GREEN_PIN 6 #define FADE_INTERVAL 1200 // [us] time between fade steps byte target_red, current_red; byte target_green, current_green; unsigned long last_fade_time; void setup() { pinMode(SWITCH_PIN, INPUT_PULLUP); pinMode(RED_PIN, OUTPUT); pinMode(GREEN_PIN, OUTPUT); } void loop() { if (digitalRead(SWITCH_PIN) == LOW) { // switch to GREEN target_red = 0; if (current_red == 0) target_green = 150; } else { // switch to RED if(current_green == 0) target_red = 255; target_green = 0; } if (micros() - last_fade_time > FADE_INTERVAL) { // no issue after 70 min last_fade_time = micros(); if (current_red < target_red) current_red++; if (current_red > target_red) current_red--; if (current_green < target_green) current_green++; if (current_green > target_green) current_green--; analogWrite(RED_PIN, current_red); analogWrite(GREEN_PIN, current_green); } }
Note that a micros() timer overflows every 70 minutes. That’s why the timer is used with a subtraction … in stead of check if micros() > time_to_fade … we check if micros() – last_fade_time > FADE_INTERVAL. It’s a little less intuitive to read, and also it’s no big deal if once every hour a fade behaves a bit strange, but still … this subtraction is the way to get rid of any timer overflow issue.
Click here if you like to see more of the kitchen lighting project.
The next video will be the start of a new project … we’re going to build a model railway crossing. We’ll use a couple of the techniques we have seen before like LEDs blinking (we know how to do that!) and we’ll include some new ones, like train detection and a servo motor that closes the gate. And we’ll find a nice way to easily write code for a system that changes between the states it can be in, depending on events that take place.
— 0 —
Hello Rudy,
with great pleasure I follow your Arduino Fun videos. They are at least as helpful and imaginative as your EEPX videos, which I have always followed.
At the moment I have also devoted myself to microcontroller and Arduino. My goal is to create a SmartHome system based on openHAB and microcontrollers.
Here your video Fun with Arduino 16 LED (Strip) fading came just right.
However, I modified it a bit to make the fading a bit gentler.
For this I found an interesting website, where you can create a table of values for a pwmfading matrix:
http://www.aaabbb.de/JNumberTableMaker/pwm_sine_function_table_maker.php
I then included them in your Arduino sketch see it below.
I’m looking forward to further episodes of your series.
Greetings from Erftstadt near Cologne
Andreas
#define SWITCH_PIN 2 // input for toggle switch
#define POTM_PIN A0 // potmeter analog input
#define LIGHTS_PIN 9 // output to FET module
#define LED_PIN 13 // output to LED on switch panel
#define FADE_INTERVAL 10 // [ms] time between fade steps
int pwmtab[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //Table of a fading characteristic
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //generated via the link above
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6,
7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13,
13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 21,
22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 31, 31, 32, 33,
34, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 49,
50, 51, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 65, 66, 67, 69,
70, 71, 73, 74, 76, 77, 78, 80, 81, 83, 84, 86, 87, 89, 91, 92, 94,
96, 97, 99, 101, 103, 104, 106, 108, 110, 112, 113, 115, 117, 119,
121, 123, 125, 127, 129, 131, 133, 136, 138, 140, 142, 144, 147, 149,
151, 154, 156, 158, 161, 163, 166, 168, 171, 173, 176, 178, 181, 183,
186, 189, 191, 194, 197, 200, 203, 205, 208, 211, 214, 217, 220, 223,
226, 229, 232, 236, 239, 242, 245, 248, 252, 255};
byte target, current; // target and current pwm value
unsigned long time_for_fadestep;
void setup() {
pinMode(SWITCH_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (digitalRead(SWITCH_PIN) == 0) { // toggle switch ON
digitalWrite(LED_PIN, HIGH);
target = map(analogRead(POTM_PIN), 0, 1024, 0, 256);
}
else { // toggle switch OFF
digitalWrite(LED_PIN, LOW);
target = 0;
}
if (millis() > time_for_fadestep) {
time_for_fadestep = millis() + (unsigned long)FADE_INTERVAL;
if (current target) current = current – 1; // shorthand for current = current – 1 current–
analogWrite(LIGHTS_PIN, pwmtab[current]);
Serial.print(target);
Serial.print(” “);
Serial.println(pwmtab[current]);
}
}
LikeLike