Files

copied
Last update 2 years 9 months by eddyluursema
FilesArduinoCourseArduinoCoursePart2
..
09_BrightnessStart
10_BrightnessWithoutDelay
11_BrightnessWithoutDelay4LEDs
12_FadingWithoutDelay
13_FadingWithoutDelayMicro
14_FadingWithoutDelay4LEDs
README.md
README.md

English flagEnglish

In this course a universal DCC decoder for signals and switches is build step by step. This course is to encourage everyone to start loving the Arduino platform to be used in model railroad automation. This is part 2 of the course containing examples of LED fading. These are the examples (work in progress):

09_BrightnessStart

Fading is a lot more complex. In these cases it is wise to start with a smaller example instead of trying to extend the previous example.

Dimming a LED is done through pulse width modulation. At a speed invisible for the human eye the LED is switched on during a certain period and off. The ratio on-off will give the impression that the LED is dimmed.

This example has one LED. Experiment with the values of HIGHTIME and LOWTIME. The sum of HIGHTIME and LOWTIME is the PWM cycle period. In the example this is 20 msec so the LED will flicker at 50 Hz. Lower frequencies are irritating to the eye. Setting the brightness to 1 msec on and 19 msec off is still visible. Flickering at 50 Hz can be made visible in two ways: turn your head fast while looking at the LED and using the camera of a mobile phone.

09_BrightnessStart.ino

```c++ const int SIGNALPIN = 13; const int HIGHTIME = 1; const int LOWTIME = 19;

void setup() { // initialize digital pin as an output. pinMode(SIGNALPIN, OUTPUT); }

// the loop function runs over and over again forever void loop() { digitalWrite(SIGNALPIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(HIGHTIME); // wait for HIGHTIME msec digitalWrite(SIGNALPIN, LOW); // turn the LED off by making the voltage LOW delay(LOWTIME); // wait for LOWTIME msec }

TOP

10_BrightnessWithoutDelay

Now we rewrite the example above to get rid of the delay function. The smallest time division is one step in the PWM cycle. The LED is switched on at the beginning of the cycle and switched off at the moment the cycle reaches the presetted brightness (ledBrightness) of the LED. If ledBrightness = 0 the LED is always off (we need this in a later example).

SignalControl.ino

```c++ const int SIGNALPIN = 13;

const int PWMTIME = 20; // time in msec for one PWM cycle. const int PWMINCREASE = 1; // each PWM cycle is divided into steps of PWMINCREASE msec int pwmCycle; // each PWM cycle this starts with 1 and increases each PWMINCREASE msec up to PWMTIME

unsigned long previousMillis; // will store last time PWM cycle was updated int ledBrightness; // will store brightness as the PWM width value between 0 and PWMTIME

void SignalControl_Init() { // initialize digital pin 13 as an output. pinMode(SIGNALPIN, OUTPUT); pwmCycle = 1; ledBrightness = 2; // lowest brightness for this experiment }

void SignalControl_Blink() { unsigned long currentMillis = millis(); // current time if (currentMillis - previousMillis >= PWMINCREASE) { // PWMINCREASE msec have passed since last time previousMillis = currentMillis; // wait for next moment pwmCycle = pwmCycle + PWMINCREASE; // next PWMINCREASE msec within one PWM cycle if (pwmCycle > PWMTIME) { // if one PWM cycle is completed, repeat by starting at 1 pwmCycle = 1; }; int ledState; if (ledBrightness >= pwmCycle) { // switch LED on or off during one cycle at the moment the setting of the brightness is reached ledState = HIGH; // HIGH means set LED on } else { ledState = LOW; // LOW means set LED off } digitalWrite(SIGNALPIN, ledState); //set output according to ledState } }

10_BrightnessWithoutDelay.ino

```c++ void setup() { // initialize signal output SignalControl_Init(); }

// the loop function runs over and over again forever void loop() { SignalControl_Blink(); }

TOP

11_BrightnessWithoutDelay4LEDs

The example above is extended to four ledState

SignalControl.ino ```c++ const int NUMBEROFPINS = 4; const int SIGNALPINS[NUMBEROFPINS] = {13, 12, 10, 9};

const int UP = 1; // increase brightness const int DOWN = -1; // decrease brightness const int PWMTIME = 20; // time in msec for one PWM cycle. 20 msec means 50 Hz cycle. const int PWMINCREASE = 1; // each PWM cycle is divided into steps of PWMINCREASE msec int pwmCycle; // each PWM cycle starts with 1 and increases each PWMINCREASE msec up to PWMTIME int brightCycle; // count PWM cycles int ledBrightness[NUMBEROFPINS] ; // will store brightness as the PWM width value between 0 and PWMTIME int ledDimOrBright[NUMBEROFPINS]; // should led get brighter so UP (+1) of must it dimm DOWN (-1)

const int BRIGHTINCREASECYCLES = 2; // after BRIGHTINCREASECYCLES times a complete PWM cycle brightness is increased or decreased

unsigned long previousMillis; // will store last time PWM cycle was updated

void SignalControl_Init() { // initialize digital pin 13 as an output. for (int i = 0; i < NUMBEROFPINS; i++) { pinMode(SIGNALPINS[i], OUTPUT); ledDimOrBright[i] = UP; } ledBrightness[0] = 1; // some brightness for this experiment ledBrightness[1] = 6; // some brightness for this experiment ledBrightness[2] = 11; // some brightness for this experiment ledBrightness[3] = 17; // some brightness for this experiment pwmCycle = 1; brightCycle = 0; }

void SignalControl_Blink() { unsigned long currentMillis = millis(); // current time if (currentMillis - previousMillis >= PWMINCREASE) { // PWMINCREASE msec have passed since last time previousMillis = currentMillis; // wait for next moment pwmCycle = pwmCycle + PWMINCREASE; // next PWMINCREASE msec within one PWM cycle if (pwmCycle > PWMTIME) { // if one PWM cycle is completed, repeat by starting at 1 pwmCycle = 1; brightCycle ++; // increase cycle number if (brightCycle > BRIGHTINCREASECYCLES) { // it is time to increase or decrease brightness brightCycle = 0; for (int i = 0; i < NUMBEROFPINS; i++) { ledBrightness[i] = ledBrightness[i] + ledDimOrBright[i]; // increase or decreas brightness depening on direction if (ledBrightness[i] == PWMTIME) { // if at maximum, for now invert to dimming ledDimOrBright[i] = DOWN; }; if (ledBrightness[i] == 1) { // if at minimum, for now invert to more bright. ledBrightness = 0 is used for the state off ledDimOrBright[i] = UP; }; }; }; }; for (int i = 0; i < NUMBEROFPINS; i++) { digitalWrite(SIGNALPINS[i], (ledBrightness[i] >= pwmCycle) ? (HIGH) : (LOW)); //set output according to the position in the cycle }; }; }

11_BrightnessWithoutDelay4LEDs.ino

```c++ void setup() { // initialize signal output SignalControl_Init(); }

// the loop function runs over and over again forever void loop() { SignalControl_Blink(); }

TOP

12_FadingWithoutDelay

Now the example above is extended to get a fading effect.The brightness is slowely increased until maximum and then decreased at the same speed until minimum.

SignalControl.ino

```c++ const int SIGNALPIN = 13;

const int UP = 1; // increase brightness const int DOWN = -1; // decrease brightness const int PWMTIME = 20; // time in msec for one PWM cycle. 20 msec means 50 Hz cycle. const int PWMINCREASE = 1; // each PWM cycle is divided into steps of PWMINCREASE msec int pwmCycle; // each PWM cycle starts with 1 and increases each PWMINCREASE msec up to PWMTIME int brightCycle; // count PWM cycles int ledBrightness; // will store brightness as the PWM width value between 0 and PWMTIME int ledDimOrBright; // should led get brighter so UP (+1) of must it dimm DOWN (-1)

const int BRIGHTINCREASECYCLES = 2; // after BRIGHTINCREASECYCLES times a complete PWM cycle brightness is increased or decreased

unsigned long previousMillis; // will store last time PWM cycle was updated

void SignalControl_Init() { // initialize digital pin 13 as an output. pinMode(SIGNALPIN, OUTPUT); ledBrightness = 1; ledDimOrBright = UP; pwmCycle = 1; brightCycle = 0; }

void SignalControl_Blink() { unsigned long currentMillis = millis(); // current time if (currentMillis - previousMillis >= PWMINCREASE) { // PWMINCREASE msec have passed since last time previousMillis = currentMillis; // wait for next moment pwmCycle = pwmCycle + PWMINCREASE; // next PWMINCREASE msec within one PWM cycle if (pwmCycle > PWMTIME) { // if one PWM cycle is completed, repeat by starting at 1 pwmCycle = 1; brightCycle ++; // increase cycle number if (brightCycle > BRIGHTINCREASECYCLES) { // it is time to increase or decrease brightness brightCycle = 0; ledBrightness = ledBrightness + ledDimOrBright; // increase or decreas brightness depening on direction if (ledBrightness == PWMTIME) { // if at maximum, for now invert to dimming ledDimOrBright = DOWN; }; if (ledBrightness == 1) { // if at minimum, for now invert to more bright. ledBrightness = 0 is used for the state off ledDimOrBright = UP; }; }; }; digitalWrite(SIGNALPIN, (ledBrightness >= pwmCycle) ? (HIGH) : (LOW)); //set output according to the position in the cycle } }

The big change between this code and the previous example starts after pwmCycle = 1; Also note the improvement at the bottom with a so called 'conditional assignment'. Use this program to experiment with fade timing.

12_FadingWithoutDelay.ino

```c++ void setup() { // initialize signal output SignalControl_Init(); }

// the loop function runs over and over again forever void loop() { SignalControl_Blink(); }

## 13_FadingWithoutDelayMicro

On observing the fading of the LEDs in the previous example it is obvious that the incremental brightness steps are not garnular enough. The human eye can see the 20 steps in which we divide the increment in intensity of the LED. In another example the granularity is much smaller. So the next step will be to divide the 20 msec into X steps of Y &mu;s each. We will increase X until it is not visible by the human eye.

Also we will set an output pin to 1 when entering the big piece of code setting and clearing the LED and to 0 when we are done. In this way we hope to see how much processing time is spend in that code using an oscilloscope.

TOP

14_FadingWithoutDelay4LEDs

Now we extend as previously done the example over 4 LEDs.

SignalControl.ino

```c++ const int NUMBEROFPINS = 4; const int SIGNALPINS[NUMBEROFPINS] = {13, 12, 10, 9};

const int UP = 1; // increase brightness const int DOWN = -1; // decrease brightness const int PWMTIME = 20; // time in msec for one PWM cycle. 20 msec means 50 Hz cycle. const int PWMINCREASE = 1; // each PWM cycle is divided into steps of PWMINCREASE msec int pwmCycle; // each PWM cycle starts with 1 and increases each PWMINCREASE msec up to PWMTIME int brightCycle; // count PWM cycles int ledBrightness[NUMBEROFPINS] ; // will store brightness as the PWM width value between 0 and PWMTIME int ledDimOrBright[NUMBEROFPINS]; // should led get brighter so UP (+1) of must it dimm DOWN (-1)

const int BRIGHTINCREASECYCLES = 2; // after BRIGHTINCREASECYCLES times a complete PWM cycle brightness is increased or decreased

unsigned long previousMillis; // will store last time PWM cycle was updated

void SignalControl_Init() { // initialize digital pin 13 as an output. for (int i = 0; i < NUMBEROFPINS; i++) { pinMode(SIGNALPINS[i], OUTPUT); ledDimOrBright[i] = UP; } ledBrightness[0] = 1; // some brightness for this experiment ledBrightness[1] = 6; // some brightness for this experiment ledBrightness[2] = 11; // some brightness for this experiment ledBrightness[3] = 17; // some brightness for this experiment pwmCycle = 1; brightCycle = 0; }

void SignalControl_Blink() { unsigned long currentMillis = millis(); // current time if (currentMillis - previousMillis >= PWMINCREASE) { // PWMINCREASE msec have passed since last time previousMillis = currentMillis; // wait for next moment pwmCycle = pwmCycle + PWMINCREASE; // next PWMINCREASE msec within one PWM cycle if (pwmCycle > PWMTIME) { // if one PWM cycle is completed, repeat by starting at 1 pwmCycle = 1; brightCycle ++; // increase cycle number if (brightCycle > BRIGHTINCREASECYCLES) { // it is time to increase or decrease brightness brightCycle = 0; for (int i = 0; i < NUMBEROFPINS; i++) { ledBrightness[i] = ledBrightness[i] + ledDimOrBright[i]; // increase or decreas brightness depening on direction if (ledBrightness[i] == PWMTIME) { // if at maximum, for now invert to dimming ledDimOrBright[i] = DOWN; }; if (ledBrightness[i] == 1) { // if at minimum, for now invert to more bright. ledBrightness = 0 is used for the state off ledDimOrBright[i] = UP; }; }; }; }; for (int i = 0; i < NUMBEROFPINS; i++) { digitalWrite(SIGNALPINS[i], (ledBrightness[i] >= pwmCycle) ? (HIGH) : (LOW)); //set output according to the position in the cycle }; }; }

14_FadingWithoutDelay4LEDs.ino

```c++ void setup() { // initialize signal output SignalControl_Init(); }

// the loop function runs over and over again forever void loop() { SignalControl_Blink(); } ```

TOP

Fading on transition from one aspect to another

On receiving a command the lights of the current aspect must be dimmed during a dimming period and the lights of the new aspect must get brighter during a dimming period.

Report a bug