Advanced Arduino LED Lighting Techniques

Advanced Arduino LED Lighting TechniquesSource: 21ic WeChat Official Account

In the last issue of “Teaching You to Light Up in Style,” we taught everyone how to maximize the lighting of a single LED. But the lighting fun doesn’t stop there! This time, we have a more advanced course to teach you how to stylishly light up a row of LEDs. Buckle up, the experienced driver is ready to take off!

After the simplest LED experiment, naturally, we will increase the number of LEDs and arrange them in a row. Finally, let’s arrange the row of LEDs into the shape of the number 8 — a seven-segment display.

Running Light 1 — Marquee Light

The first to appear is the classic running light, also known as the marquee light.

Advanced Arduino LED Lighting Techniques

Advanced Arduino LED Lighting Techniques

Running Light 2 — Overall Port Operation

Let’s try the running light again, this time using an overall port operation. Does it feel simpler?

Advanced Arduino LED Lighting Techniques

Advanced Arduino LED Lighting Techniques

Running Light 3 — 74HC595 IO Expansion

Another running light! This time, we use the 74HC595 to expand the IO ports. For Arduino, the IO port resources are quite limited, and sooner or later, you will encounter situations where there aren’t enough. This is when expansion is necessary. Using the 74HC595 is a common solution.

Advanced Arduino LED Lighting TechniquesAdvanced Arduino LED Lighting Techniques

Advanced Arduino LED Lighting Techniques

Raindrop Trail Effect Running Light

Sorry, it’s still a running light. This time we simulate a more realistic effect with a raindrop trailing effect.

First, we will use six PWM ports of the UNO to achieve this.

1. // —————————————————————————-

2. // raindropLEDS.ino

3. //

4. // Created 2015-06-04

5. // By seesea <seesea2517#gmail#com>

6. //

7. // Raindrop Flow Effect

8. // The difference between the raindrop flow effect and the running light is that the raindrop effect has a trailing effect, meaning the lights that have been on gradually extinguish.

9. //

10. // Using the six PWM pins of the UNO to achieve the raindrop flow effect

11. // The six PWM pins of the UNO are pin 3, 5, 6, 9, 10, 11, these pins connect to the positive terminals of six LEDs, and the negative terminals connect to GND.

12. //

13. // —————————————————————————-

14.

15. const unsigned char pins[] = { 3, 5, 6, 9, 10, 11 }; // Six PWM pins

16. const unsigned char initPwm = 240; // The PWM value of the brightest light, which is the brightness of the first light when moving

17. const unsigned char deltaPwm = 10; // The PWM value at which the light gradually extinguishes, how much darker the next light is compared to the previous one. This is equivalent to an arithmetic sequence. The arithmetic brightness feels not very good, so we introduce the next geometric factor.

18. const unsigned char deltaPercent = 30; // The next light is darker than the previous light, its brightness is a percentage of the previous light. Compared to the previous decrement, this is equivalent to a geometric series.

19. const unsigned long delayMs = 100; // Movement delay, in ms

20. const unsigned char pinNum = sizeof(pins) / sizeof(pins[0]); // Number of pins, i.e., number of LEDs

21.

22. unsigned char ledPwm[pinNum]; // Store the PWM value of each LED during operation

23.

24. void setup()

25. {

26. for (char i = 0; i < pinNum; ++i)

27. {

28. pinMode(pins[i], OUTPUT);

29. ledPwm[i] = 0;

30. }

31. }

32.

33. void loop()

34. {

35. static unsigned char head = 0;

36.

37. // Every time we enter the loop() function, we process the brightness of all the lights

38. for (unsigned char i = 0; i < pinNum; ++i)

39. {

40. ledPwm[i] = ledPwm[i] * deltaPercent / 100;

41. if (ledPwm[i] <= deltaPwm)

42. ledPwm[i] = 0;

43. else

44. ledPwm[i] -= deltaPwm;

45.

46. if (i == head)

47. ledPwm[i] = initPwm;

48.

49. analogWrite(pins[i], ledPwm[i]);

50. }

51.

52. // Move the raindrop head

53. head = (head + 1) % pinNum;

54.

55. // Delay

56. delay(delayMs);

57. }

Advanced Arduino LED Lighting Techniques

Raindrop Trail Effect Running Light 2 — Digital IO Simulation

Having only six PWM ports is not enough, let’s use all the IO ports, including the analog ports, which can also be used as digital IO ports.

1. // —————————————————————————-

2. // digitalRaindropLEDS.ino

3. //

4. // Created 2015-06-04

5. // By seesea <seesea2517#gmail#com>

6. //

7. // Raindrop flow effect implemented with digital pins

8. // The difference between the raindrop flow effect and the running light is that the raindrop effect has a trailing effect, meaning the lights that have been on gradually extinguish.

9. //

10. // Using all pins of the UNO to implement the raindrop flow effect with simulated PWM, including analog input ports that can also be used for digital output

11. // Each pin connects to the positive terminal of an LED, and the negative terminal connects to GND

12. // —————————————————————————-

13.

14. const unsigned char leds[] = { A5, A4, A3, A2, A1, A0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; // All pins arranged in the order of LED connections

15. const unsigned int maxPwm = 100; // Manually simulated PWM, you can define the maximum PWM value, so it’s convenient to calculate with round numbers

16. const unsigned int initPwm = 100; // The PWM value of the brightest light, which is the brightness of the first light when moving

17. const unsigned int deltaPwm = 1; // The PWM value at which the light gradually extinguishes, how much darker the next light is compared to the previous one. This is equivalent to an arithmetic sequence. The arithmetic brightness feels not very good, so we introduce the next geometric factor.

18. const unsigned int deltaPercent = 70; // The next light is darker than the previous light, its brightness is a percentage of the previous light. Compared to the previous decrement, this is equivalent to a geometric series.

19. const unsigned long delayMs = 70; // Movement delay, in ms

20. const unsigned char ledNum = sizeof(leds) / sizeof(leds[0]); // Number of pins, i.e., number of LEDs

21.

22. unsigned int ledPwm[ledNum]; // Store the PWM value of each LED during operation

23.

24. void setup()

25. {

26. for (char i = 0; i < ledNum; ++i)

27. {

28. pinMode(leds[i], OUTPUT);

29. ledPwm[i] = 0;

30. }

31. }

32.

33. extern volatile unsigned long timer0_millis; // Declare external variable timer0_millis for use in the program, which is actually the return value of millis() — the number of milliseconds the program has been running

34. void loop()

35. {

36. static unsigned char head = 0;

37. static unsigned long lastTick = timer0_millis;

38. unsigned int i, j;

39.

40. // First, turn on the lights, and when the duty cycle reaches the switching point, turn off the lights

41. for (i = 0; i < ledNum; ++i)

42. {

43. if (ledPwm[i] == 0)

44. continue;

45.

46. digitalWrite(leds[i], HIGH);

47. }

48.

49. // The raindrop head is the brightest

50. ledPwm[head] = initPwm;

51.

52. // Here is the digital pin simulated PWM program

53. for (i = 0; i < maxPwm; ++i)

54. {

55. for (j = 0; j < ledNum; ++j)

56. {

57. if (i == ledPwm[j])

58. digitalWrite(leds[j], LOW);

59. }

60.

61. delayMicroseconds(1);

62. }

63.

64. // If the delay time has not yet elapsed, exit without moving the raindrop

65. // Since this is a digital pin simulated PWM, the program must keep running, and cannot use delay() for blocking, or it will get stuck

66. if (timer0_millis – lastTick < delayMs)

67. return;

68.

69. lastTick = timer0_millis;

70.

71. // Process the brightness of each light

72. for (i = 0; i < ledNum; ++i)

73. {

74. ledPwm[i] = ledPwm[i] * deltaPercent / 100;

75. if (ledPwm[i] <= deltaPwm)

76. ledPwm[i] = 0;

77. else

78. ledPwm[i] -= deltaPwm;

79.

80. if (i == head)

81. ledPwm[i] = initPwm;

82. }

83.

84. // Move the raindrop head

85. head = (head + 1) % ledNum;

86. }

Advanced Arduino LED Lighting Techniques

POV Wand is Time to Dance, Let’s Shake It!

1. // —————————————————————————-

2. // povLEDS.ino

3. //

4. // Created 2015-05-31

5. // By seesea <seesea2517#gmail#com>

6. //

7. // POV Wand

8. //

9. // pin 0 – 7 connect to the positive terminal of the LED, and the negative terminal connects to GND

10. // pin 8 connects to one leg of the mercury switch, the other leg connects to GND

11. // The mercury switch is fixed horizontally in the direction of shaking. If the actual effect is opposite to the expected effect, just swap the connections of the two legs of the mercury switch.

12. // Note: Since pin 0 and 1 are grounded through the LED, they need to be disconnected during download for successful downloading.

13. // —————————————————————————-

14.

15. const unsigned char key = 8; // Mercury switch

16. const unsigned char delayTimeMs = 2; // Delay for LED lighting during scanning

17.

18. // The software uses the high position of the vertical 8 points for modeling

19. unsigned char col[] =

20. {

21. // Heart

22. // 0x30,0x48,0x44,0x22,0x44,0x48,0x30,0x00

23.

24. // I heart U

25. 0x82,0xFE,0xFE,0x82,0x00,0x30,0x78,0x7C,

26. 0x3E,0x7C,0x78,0x30,0x00,0xFC,0xFE,0x02,

27. 0x02,0xFE,0xFC,0x00,0x00,0x00

28.

29. /* 1 2 3

30. 0x00,0x42,0xFE,0x02,0x00,0x00,0x00,0x00,

31. 0x46,0x8A,0x92,0x92,0x62,0x00,0x00,0x00,

32. 0x84,0x82,0x92,0xB2,0xCC,0x00

33. */

34. };

35.

36. unsigned char cols = (sizeof(col) / sizeof(col[0]));

37.

38. void setup()

39. {

40. DDRD = 0xFF;

41. pinMode(key, INPUT_PULLUP);

42. }

43.

44. void loop()

45. {

46. char i = 0;

47. char keyValue = digitalRead(key);

48. char delta = 1;

49.

50. if (keyValue == 1) // When shaking from right to left

51. {

52. // Here you can try two schemes

53. // One is to turn off all lights when sweeping to the left

54. // The other is to light up each column in reverse, so the direction is also reversed, and the display returns to normal.

55. // Depending on your needs, you can change the if condition to 0 or 1 to choose different schemes

56. // The advantage of the first scheme is that it is less likely to have ghosting, but the disadvantage is low brightness

57. // The advantages and disadvantages of the second scheme are exactly the opposite

58. if (0)

59. {

60. // Turn off all lights when shaking to the left

61. i = 0;

62. PORTD = 0x00;

63.

64. // If you choose this scheme, you don’t need to continue with the scanning below, just return;

65. return;

66. }

67. else

68. {

69. delta = -delta;

70. }

71. }

72.

73. if (delta == 1)

74. {

75. // When shaking to the right

76. for (i = 0; i < cols; ++i)

77. {

78. PORTD = col[i];

79. delay(delayTimeMs);

80. }

81. }

82. else

83. {

84. // When shaking to the left

85. for(i = cols – 1; i >= 0; –i)

86. {

87. PORTD = col[i];

88. delay(delayTimeMs);

89. }

90. }

91. }

Here’s a wiring diagram I think should be included, a visual effect, picked from hundreds of photos:

Advanced Arduino LED Lighting TechniquesAdvanced Arduino LED Lighting Techniques

Advanced Arduino LED Lighting TechniquesAdvanced Arduino LED Lighting Techniques

Static 7-Segment Display

It’s so boring to line them all up, it’s time to modify it. Now let’s arrange them into the shape of the number 8. First, light up an 8 using static display methods.

1. // —————————————————————————-

2. // static7segLEDS.ino

3. //

4. // Created 2015-06-06

5. // By seesea <seesea2517#gmail#com>

6. //

7. // Static 7-Segment Display

8. // Using PORTD to statically display the 7-segment display, cycling through 0 – F

9. //

10. // This uses a common anode 7-segment display, if using a common cathode, just invert the segment code table.

11. // The order of the segments of the display is arranged as follows

12. //

13. // A

14. // —

15. // F| G |B

16. // —

17. // E| D |C

18. // — . DP

19. //

20. // Then create a segment code table based on the numbers to be displayed, which can be produced by outputting 1 for the segments to be lit. This method produces a common cathode, so invert it for common anode.

21. // +—+–+–+–+–+–+–+–+–+—–+

22. // | | A| B| C| D| E| F| G|DP| Segment Code|

23. // +—+–+–+–+–+–+–+–+–+—–+

24. // | 0 | 1| 1| 1| 1| 1| 1| 0| 0| 0xFC|

25. // +—+–+–+–+–+–+–+–+–+—–+

26. // | 1 | 0| 1| 1| 0| 0| 0| 0| 0| 0x60|

27. // +—+–+–+–+–+–+–+–+–+—–+

28. // | 2 | 1| 1| 0| 1| 1| 0| 1| 0| 0xDA|

29. // +—+–+–+–+–+–+–+–+–+—–+

30. // | 3 | 1| 1| 1| 1| 0| 0| 1| 0| 0xF2|

31. // +—+–+–+–+–+–+–+–+–+—–+

32. // | 4 | 0| 1| 1| 0| 0| 1| 1| 0| 0x66|

33. // +—+–+–+–+–+–+–+–+–+—–+

34. // | 5 | 1| 0| 1| 1| 0| 1| 1| 0| 0xB6|

35. // +—+–+–+–+–+–+–+–+–+—–+

36. // | 6 | 1| 0| 1| 1| 1| 1| 1| 0| 0xBE|

37. // +—+–+–+–+–+–+–+–+–+—–+

38. // | 7 | 1| 1| 1| 0| 0| 0| 0| 0| 0xE0|

39. // +—+–+–+–+–+–+–+–+–+—–+

40. // | 8 | 1| 1| 1| 1| 1| 1| 1| 0| 0xFE|

41. // +—+–+–+–+–+–+–+–+–+—–+

42. // | 9 | 1| 1| 1| 1| 0| 1| 1| 0| 0xF6|

43. // +—+–+–+–+–+–+–+–+–+—–+

44. // | A | 1| 1| 1| 0| 1| 1| 1| 0| 0xEE|

45. // +—+–+–+–+–+–+–+–+–+—–+

46. // | B | 0| 0| 1| 1| 1| 1| 1| 0| 0x3E|

47. // +—+–+–+–+–+–+–+–+–+—–+

48. // | C | 0| 0| 0| 1| 1| 0| 1| 0| 0x1A|

49. // +—+–+–+–+–+–+–+–+–+—–+

50. // | D | 0| 1| 1| 1| 1| 0| 1| 0| 0x7A|

51. // +—+–+–+–+–+–+–+–+–+—–+

52. // | E | 1| 0| 0| 1| 1| 1| 1| 0| 0x9E|

53. // +—+–+–+–+–+–+–+–+–+—–+

54. // | F | 1| 0| 0| 0| 1| 1| 1| 0| 0x8E|

55. // +—+–+–+–+–+–+–+–+–+—–+

56. // —————————————————————————-

57.

58. // Common anode segment code table 0 – F

59. const unsigned char segTable[] = {

60. ~0xFC, ~0x60, ~0xDA, ~0xF2, ~0x66, ~0xB6,

61. ~0xBE, ~0xE0, ~0xFE, ~0xF6, ~0xEE, ~0x3E,

62. ~0x1A, ~0x7A, ~0x9E, ~0x8E

63. };

64.

65. void setup()

66. {

67. DDRD = 0xFF; // Set PORTD as output

68. }

69.

70. void loop()

71. {

72. for (char i = 0; i < sizeof(segTable) / sizeof(segTable[0]); ++i)

73. {

74. PORTD = segTable[i];

75. delay(500);

76. }

77. }

Advanced Arduino LED Lighting Techniques

Dynamic 7-Segment Display

The above shows a single-digit display, which can be static; however, to display multiple digits, we need to make it dynamic.

1. // —————————————————————————-

2. // dynamic7segLEDS.ino

3. //

4. // Created 2015-06-06

5. // By seesea <seesea2517#gmail#com>

6. //

7. // Dynamic 7-Segment Display

8. // Dynamically display the 7-segment display, counting from 0000 to 9999 and then back to 0

9. //

10. // Using PORTD for segment selection, using pin 8, 9, 10, 11 for digit selection

11. // —————————————————————————-

12.

13. #define COM_ON HIGH // Common anode display common terminal enable level

14. #define COM_OFF LOW // Common anode display common terminal disable level

15.

16. // Common anode segment code table 0 – F

17. const unsigned char segTable[] = {

18. ~0xFC, ~0x60, ~0xDA, ~0xF2, ~0x66, ~0xB6,

19. ~0xBE, ~0xE0, ~0xFE, ~0xF6, ~0xEE, ~0x3E,

20. ~0x1A, ~0x7A, ~0x9E, ~0x8E

21. };

22.

23. const unsigned char pinPos[] = { 8, 9, 10, 11 }; // Digit selection pins, arranged from low to high

24. const unsigned int initNum = 0; // Initial counting value

25. const unsigned int maxNum = 9999; // Maximum count

26. const unsigned char com_num = sizeof(pinPos) / sizeof(pinPos[0]); // Number of common terminals, used to determine how many digits

27. const unsigned long delayMs = 50; // Dynamic scanning delay time

28.

29. void setup()

30. {

31. DDRD = 0xFF; // Set PORTD as output

32. for (char i = 0; i < sizeof(pinPos) / sizeof(pinPos[0]); ++i)

33. {

34. pinMode(pinPos[i], OUTPUT);

35. }

36. }

37.

38. // Display number num on the 7-segment display

39. // Separate the digits of num into units, tens, hundreds, and thousands for display on each digit

40. void display7segLED(unsigned int num)

41. {

42. unsigned int digital;

43. for (unsigned char i = 0; i < com_num; ++i)

44. {

45. digital = num % 10;

46. num /= 10;

47.

48. PORTD = segTable[digital];

49. digitalWrite(pinPos[i], COM_ON);

50.

51. delayMicroseconds(10);

52. digitalWrite(pinPos[i], COM_OFF); // The legendary ghosting avoidance

53. }

54. }

55.

56. void loop()

57. {

58. static unsigned long lastTick = millis();

59. static unsigned int num = initNum;

60.

61. display7segLED(num);

62.

63. // Dynamic scanning, cannot use delay for blocking delays, the previous experiments have shown that this method is useful now

64. if (millis() – lastTick < delayMs)

65. return;

66.

67. lastTick = millis();

68. ++num;

69. if (num >= maxNum)

70. num = initNum;

71. }

Advanced Arduino LED Lighting Techniques

Have you all learned it? Still not satisfied?!

This article is reprinted from the internet, copyright belongs to the original author. If you feel it is not good, please contact us to delete it!

Advertisement

About Lichuang Mall

Lichuang Mall (WWW.SZLCSC.COM) is a one-stop online procurement self-operated mall for electronic components, with over 10,000 self-operated warehouses and more than 190,000 kinds of stock. Guaranteeing 100% original and genuine products, and has achieved lightning delivery within 4 hours! The group’s electronic full industry chain self-operated services cover online EDA (LCEDA), PCB prototyping, component mall, stencil manufacturing, SMT placement, electronic design education, and solutions.

Leave a Comment

×