A Cool Arduino Controlled Dual Dimmable Light Array

by kevinjpower in Circuits > Arduino

1073 Views, 5 Favorites, 0 Comments

A Cool Arduino Controlled Dual Dimmable Light Array

Title.jpg

Make an Arduino controlled light array that alternatively dims and lights LED diodes with a compensated voltage to create a charming visual display.

To be truthful, this project started on a whim. The question was: how can a MC74HC14A Hex Schmitt-Trigger Inverter be combined with an Arduino to do something? This is the result. Of course, it has no practical application other than it looks cool.

Supplies

  1. Arduino Uno
  2. MC74HC14A Hex Schmitt-Trigger Inverter
  3. 6 x 220 Ohm Resistor
  4. 6 x Colored LED’s
  5. Breadboard

MC74HC14A Hex Schmitt-Trigger Inverter

Before launching into this project, some background on the chip in the heart of the action.

The Schmitt trigger inverter is used to output square waves of the correct voltage to power an LED array. By cascading the gates, alternating square waves can be produced. A Schmitt trigger circuit includes hysteresis which ensures precise transitions from HIGH to LOW and from LOW to HIGH in a digital signal.

Link to a data sheet

https://www.mouser.com/datasheet/2/308/MC74HC14A-D-601265.pdf

If you are interested in the theory behind a Schmitt trigger inverter, there are numerous articles on the internet describing their operation.

Dimming and Lighting LEDS With PWM

PWM.png

A little more theory.

This project uses the PWM capabilty of the Arduino UNO to alternatively light up and dim down an LED. Refer to the picture and the explanation below:

PWM relies on the UNO outputting a square wave with a variable duty cycle. At low duty cycle, the outputted square wave is of short duration and the average voltage of the resulting wave is low because most of the time 0V is been output. At high duty cycles, the outputted square wave is of long duration and the average voltage of the resulting wave is high because most of the time it is near 5V.

Refer to https://docs.arduino.cc/learn/microcontrollers/analog-output for a far better explanation.

Because the output frequency is high, an LED reacts to the average voltage only. Therefore – low duty cycle = dim LED, high duty cycle = bright LED.

The relevant Arduino instructions are:

pinMode(ledPin, OUTPUT);


analogWrite(ledPin, fadeValue);


fadeValue is an integer between 0 and 255. A fadeValue of 0 represents no output voltage and a value of 255 represents a steady 5V output.

The Circuit

Schematic.png
IMG_3697.JPG
IMG_3758.JPG

The attachment shows a schematic of the circuit.

Pin 9 is used as a PWM output.

The output of each Schmitt trigger gate is inverted from its input. In the circuit, the six Schmitt triggers are connected in series. As a result of this, LED 1 sees a PWM signal which is the inverse of the signal output by pin 9. LED2 sees a signal identical to that output by Pin 9 (double inversion = original), LED3 sees an inverse, LED4 sees an identical and so on.

Therefore for max output voltage on pin 9, LED2, LED4 and LED6 will be brightly lit and LED1, LED3 and LED5 will be off. Min output from pin 9 will result in the opposite.

Use a breadboard and Arduino to build the circuit. You can use the picture with help laying the circuit out.

Some Mathematics

Equation.png
Compensation.png

Before uploading the code and getting the array to work, a small diversion into mathematics.

In the Arduino IDE, there is a simple example of how to brighten and fade an LED. See File > Examples > 01.Basics > Fade

This example uses a linear voltage ramp up; for each time increment the voltage increment is proportional. The aesthetic problem with this method is that the LED brightness does not increase and decrease in a linear manner. Rather, the LED brightness initially increases quickly and then tends to saturate to max brightness after about halfway along the voltage ramp up.

If you refer to the graph above, the voltage is following the linear y=x graph (orange), but the LED brightness is following something like the yellow curve.

To get the LED brightness to ramp up in a more linear fashion, the applied voltage must follow a ramp up something like the Compensated Voltage (Blue) shown in the graph.

So how is this achieved? The equation above allows for a compensated voltage.

  • y is the output voltage
  • m is a constant. As m increases, the amount of deviation away from the linear curve increases.
  • X is a value between 0 and 1

The 255 multiplier is required to produce a result that can be used in the analogWrite(ledPin, fadeValue); Arduino function. This requires a value between 0 and 255.

Armed with this equation, we can code up a compensated voltage output that gives a better LED brightness ramp and down.

The Code

In the variable initialization section, float mValue = 6.0; sets up the constant m. This can be changed to achieve differing LED dimming and brightening effects.

In the setup loop, the Arduino pin that is connected to the initial input of the Hex Schmitt trigger is defined.

The main loop consists of two for loops, one for increasing from 0 to max brightness and one for decreasing from max to no brightness. The loops count from 0 to 1 in increments of 0.05.

The compensation function is applied to the loop counter and multiplied by 255 to get a value.

This value is converted to an integer and used to output a voltage at the analog pin which connects to the circuit.

Adjusting the delay times and the m value will give differing effects.

/*
  Fading

  This example shows how to fade two LED arrays alternatively using the analogWrite() function
  and the MC74HC14 Hex Schmitt Trigger Inverter

  The circuit:
  - Digital pin 9 attached to input to first Schmitt Trigger
  - First LED attached to output of first Schmitt Trigger through 220 Ohmn resistor
  - Output also connected to input of second Schmitt Trigger
  - Second LED attached to output of second Schmitt Trigger
  - And so on...

  Generate numbers that more closly follow LED dimming and lighting cycle

  Use numbers between 0 and 255 that have been fitted to curve
  (m^x -1)/(m-1)

*/

int ledPin = 9;  // MC74HC14 connected to digital pin 9
float mValue = 6.0;
float factor;
float result;
int fadeValue;

void setup() {
  // Serial.begin(115200);
  pinMode(ledPin, OUTPUT);  // Set the pin as output
}

void loop() {
  // fade in from min to max in increments of 0.05 points:
  for (float x = 0.0; x <= 1.01; x += 0.05) {
    factor = (pow(mValue,x)-1)/(mValue-1); // apply compensation formula
    result = factor*255.0;
    // convert float variable to integer
    fadeValue = int(result);
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 80 milliseconds to see the brightning effect
    delay(80);
  }
  delay(800);

  // fade out from max to min in increments of 0.05 points:
  for (float x = 1.0; x >= -0.01; x -= 0.05) {
    factor = (pow(mValue,x)-1)/(mValue-1); // apply compensation formula
    result = factor*255.0;
    // convert float variable to integer
    fadeValue = int(result);
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 80 milliseconds to see the dimming effect
    delay(80);
  }
  delay(900);

}


Once the code is uploaded to the Arduino, the LED array will brighten and dim - Enjoy the show!

And if anyone can think of a practical use for this arrangement, please leave a comment.