0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

来教教大家如何花式点亮一排灯

h1654155971.7688 来源:未知 作者:李倩 2018-03-23 09:07 次阅读

在上一期的“教你花式点灯”中,我们已经教会了大家如何将一颗灯点到极致。而点灯到这里还没有完哦,这次给大家来点进阶的小课程,来教教大家如何花式点亮一排灯。快快上车,老司机准备起飞了!

最简单的一个 LED 的实验之后,自然是增加几个 LED,咱排成一排来玩吧。最后,再把一排的 LED 排成一个 8 字来玩——七段数码管

流水灯一—— 跑马灯

第一个出场的肯定是经典的流水灯,也叫跑马灯

流水灯二—— 端口整体操作

再试流水灯,这里换一个端口整体操作,感受到更简洁没?

流水灯三—— 74HC959 扩展 IO 口

又是流水灯!这次使用 74HC595 来扩展 IO 口。对于 arduino 来说,IO 口资源是很紧张的,迟早会遇到不够用的时候,这时候就需要扩展。使用 74HC595 是一种比较常见的方案。

雨滴拖尾效果流水灯

不好意思,还是流水灯。这次模拟得更真实一点,加上水滴的拖尾效果。

首先是简单的方法,使用 uno 的六个 pwm 口来实现。

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

2.// raindropLEDS.ino

3.//

4.// Created 2015-06-04

5.// By seesea

6.//

7.// 雨滴流动效果

8.// 雨滴流动效果与流水灯(跑马灯)的区别在于雨滴流水效果有拖尾效果,即亮过的灯是慢慢熄灭的

9.//

10.// 使用 UNO 的六个 PWM 引脚实现雨滴流动的效果

11.// UNO 的六个 PWM 引脚为 pin 3 5 6 9 10 11,这几个脚分别接 6 个 LED 正极,LED 负极接 GND

12.//

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

14.

15.const unsigned char pins[] = { 3, 5, 6, 9, 10, 11 }; // 六个 pwm 引脚

16.const unsigned char initPwm= 240; // 最亮的灯的 pwm 值,即移动的时候在最头一个灯的亮度

17.const unsigned char deltaPwm = 10; // 灯慢慢熄灭的 pwm 值,后一个灯比前一个灯暗多少。这相当于是一个等差队列。等差的亮度感觉不大好,所以引入下一个等比的因素

18.const unsigned char deltaPercent = 30; // 后一个灯比前一个灯暗,其亮度是前一个灯的百分之几。相对于前面的递减,这个相当于是等比级数

19.const unsigned long delayMs= 100; // 移动延迟,单位 ms

20.const unsigned char pinNum = sizeof(pins) / sizeof(pins[0]);// 引脚数量,即 LED 个数

21.

22.unsigned char ledPwm[pinNum]; // 存放运行时每一个 LED 的亮度 PWM 值

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. // 每一次进入 loop() 函数都对所有的灯亮度进行处理

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. // 移动水滴头

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

54.

55. // 延时

56. delay(delayMs);

57.}

雨滴拖尾效果流水灯二——数字 IO 口模拟

前面只有 6 个 PWM 口实在是不过瘾啊,来,我们把所有的 IO 口都用上,包括模拟口,它也是可以作为数字 IO 口使用的。

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

2.// digitalRaindropLEDS.ino

3.//

4.// Created 2015-06-04

5.// By seesea

6.//

7.// 数字引脚实现的雨滴流动效果

8.// 雨滴流动效果与流水灯(跑马灯)的区别在于雨滴流水效果有拖尾效果,即亮过的灯是慢慢熄灭的

9.//

10.// 使用 UNO 的所有引脚用模拟 PWM 实现雨滴流动的效果,包括模拟输入口也可以用做数字输出

11.// 各引脚接 LED 正极,LED 负极接 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 }; // 所有的引脚按 LED 接线顺序排列

15.const unsigned int maxPwm = 100; // 手工模拟 PWM,可以自己定义最大的 PWM 值是多少,所以定义一个整百整千的数比较方便计算

16.const unsigned int initPwm = 100; // 最亮的灯的 pwm 值,即移动的时候在最头一个灯的亮度

17.const unsigned int deltaPwm = 1; // 灯慢慢熄灭的 pwm 值,后一个灯比前一个灯暗多少。这相当于是一个等差队列。等差的亮度感觉不大好,所以引入下一个等比的因素

18.const unsigned int deltaPercent = 70; // 后一个灯比前一个灯暗,其亮度是前一个灯的百分之几。相对于前面的递减,这个相当于是等比级数

19.const unsigned long delayMs = 70; // 移动延迟,单位 ms

20.const unsigned char ledNum = sizeof(leds) / sizeof(leds[0]);// 引脚数量,即 LED 个数

21.

22.unsigned int ledPwm[ledNum]; // 存放运行时每一个 LED 的亮度 PWM 值

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; // 声明外部变量 timer0_millis 以便在程序中使用,其实就是 millis() 的返回值——程序运行的毫秒数

34.void loop()

35.{

36. static unsigned char head = 0;

37. static unsigned long lastTick = timer0_millis;

38. unsigned int i, j;

39.

40. // 先亮灯,等占空比到切换点的时候灭灯

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

42. {

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

44. continue;

45.

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

47. }

48.

49. // 水滴头是最亮的

50. ledPwm[head] = initPwm;

51.

52. // 这里就是数字口模拟的 PWM 程序了

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. // 如果延时时间还没到,先跳出,不进行水滴的移动

65. // 由于是用数字口模拟的 PWM,程序要不停的跑,不能使用 delay() 来延时,会卡住的

66. if (timer0_millis - lastTick < delayMs)

67. return;

68.

69. lastTick = timer0_millis;

70.

71. // 处理每一个灯的亮度

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. // 移动水滴头

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

86.}

POV摇摇棒是时候舞起来了,摇起来吧。

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

2.// povLEDS.ino

3.//

4.// Created 2015-05-31

5.// By seesea

6.//

7.// 摇摇棒

8.//

9.// pin 0 - 7 接 LED 正极,LED 负极接 GND

10.// pin 8 接水银开关一脚,水银开关另一脚接 GND

11.// 水银开关水平于摇动方向固定放置。如果实际效果与预想效果水平相反,只要把水银开关两脚的接线互换就可以了

12.// 注意:由于 pin 0 1 通过 LED 接地了,下载的时候需要断开才能下载成功

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

14.

15.const unsigned char key = 8; // 水银开关

16.const unsigned char delayTimeMs = 2; // 扫描时LED的点亮延时

17.

18.// 取模软件使用纵向8点上高位的方式取模

19.unsigned char col[] =

20.{

21. // 心

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

23.

24. // I 心 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) // 摇动方向由右向左的时候

51. {

52. // 这里可以尝试两种方案

53. // 一种是向左扫的时候熄灭所有灯

54. // 另一种是反向点亮各列,从而由于方向也是反的,显示就变回正的

55. // 根据需要,把 if 条件改成 0 或 1 可以选择不同的方案

56. // 第一种方案的优点是不容易有重影,但缺点是亮度低

57. // 第二种方案的优缺正好相反

58. if (0)

59. {

60. // 向左摇熄灭所有灯

61. i = 0;

62. PORTD = 0x00;

63.

64. // 如果选择这种方案就不需要继续下面的扫描了,return掉即可

65. return;

66. }

67. else

68. {

69. delta = -delta;

70. }

71. }

72.

73. if (delta == 1)

74. {

75. // 向右摇的时候

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

77. {

78. PORTD = col[i];

79. delay(delayTimeMs);

80. }

81. }

82. else

83. {

84. // 向左摇的时候

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

86. {

87. PORTD = col[i];

88. delay(delayTimeMs);

89. }

90. }

91.}

接线图我觉得得上一下,效果图嘛,从几百张照片里挑个好看的来:

静态数码管显示

总站成一排多无聊,是时候改改造行了。现在排成 8 字吧。先点亮一个 8 字,用静态显示方法。

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

2.// static7segLEDS.ino

3.//

4.// Created 2015-06-06

5.// By seesea

6.//

7.// 静态七段数码管

8.// 使用 PORTD 静态显示七段数码管,循环显示 0 - F

9.//

10.// 这里使用的是共阳七段数码管,如果使用共阴的,只要把段码表取反即可

11.// 数码管段的顺序按如下标示排列

12.//

13.// A

14.// ---

15.//F| G |B

16.// ---

17.//E| D |C

18.// ---. DP

19.//

20.// 然后根据需要显示的数字生该段点亮输出 1,可以制作段码表。这种方式做出来的是共阴的,所以使用的时候取反即为共阳的段码

21.// +---+--+--+--+--+--+--+--+--+-----+

22.// | | A| B| C| D| E| F| G|DP| 段码|

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.// 共阳段码表 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; // PORTD 设置为输出

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.}

动态数码管显示

上面是一位数码管的显示,可以使用静态,如果要显示多位,那可得动起来了。

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

2.// dynamic7segLEDS.ino

3.//

4.// Created 2015-06-06

5.// By seesea

6.//

7.// 动态七段数码管

8.// 动态显示七段数码管,从 0000 开始计数,9999 后回 0

9.//

10.// 使用 PORTD 进行段选,使用 pin 8 9 10 11 进行位选

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

12.

13.#define COM_ON HIGH// 共阳数码管启用的公共端电平

14.#define COM_OFF LOW // 共阳数码管禁用的公共端电平

15.

16.// 共阳段码表 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 }; // 位选管脚,按从低位到高位的排列

24.const unsigned intinitNum= 0; // 计数初始值

25.const unsigned intmaxNum = 9999; // 最大计数

26.const unsigned char com_num= sizeof(pinPos) / sizeof(pinPos[0]);// 公共端的数量,用于确定有几位

27.const unsigned long delayMs= 50; // 动态扫描延迟时间

28.

29.void setup()

30.{

31. DDRD = 0xFF; // PORTD 设置为输出

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

33. {

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

35. }

36.}

37.

38.// 于七段数码管上显示数字 num

39.// 将 num 数字的个十百千等各位的数字一位一位分离出来显示到每一位数码管上

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); // 传说中的消隐,避免发生重影

53. }

54.}

55.

56.void loop()

57.{

58. static unsigned long lastTick = millis();

59. static unsigned intnum = initNum;

60.

61. display7segLED(num);

62.

63. // 动态扫描,不能用 delay 阻塞式的延迟哦,前面试验过的这种用法现在派上用场了

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

65. return;

66.

67. lastTick = millis();

68. ++num;

69. if (num >= maxNum)

70. num = initNum;

71.}

都学会了嘛~还没看过瘾?!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    240

    文章

    23134

    浏览量

    658385
  • 流水灯
    +关注

    关注

    21

    文章

    432

    浏览量

    59634
  • 74HC595
    +关注

    关注

    7

    文章

    191

    浏览量

    30793

原文标题:Arduino点灯玩成这样,也是没谁了

文章出处:【微信号:weixin21ic,微信公众号:21ic电子网】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    做个器件,用一排二极管显示电流的大小,如何实现?...

    本人想做个器件,就是用一排二极管显示电流的大小。该支路电流大,则二极管亮的个数多,支路电流小,则二极管亮的个数少。请问各位大侠,如何实现此功能,需要用芯片么?
    发表于 01-13 20:16

    想做个用MSP430控制的花式,用什么元件比较好呢?

    想做个用MSP430控制的花式、、
    发表于 04-30 10:51

    LCD1602为什么显示一排黑格???

    大家好,我是个单片机初学者。最近在做个多功能电子万年历。我在网上已经用PROTUES仿真成功了,但是用面包板连好硬件图之后LCD1602上只是第二行显示一排黑色的小方格,请问
    发表于 11-09 16:56

    哪位大虾告诉我,这个按键板上的这一排是什么电子元件?

    哪位大虾告诉我,这个按键板上的这一排是什么电子元件?
    发表于 08-10 18:34

    从TQFP144测试座引出引脚,中间那一排引脚不知道如何处理?

    `我需要从IC201-1444-026-2中引出线出来,但是位置却不够走线,这种情况可以怎么处理,我将外面的一排设置成单面的孔,让中间一排的从孔之间的位置出来可以么?`
    发表于 03-19 15:15

    Altium中这一排孔怎么做到让1,2孔的距离是固定值?

    一排孔,我怎么做到让1,2孔的距离是固定值,其他过孔的间距和这两个
    发表于 08-16 03:26

    怎么快速选中Altium中这一排引脚?

    Altium这一排引脚我怎么快速选中
    发表于 09-10 05:35

    请问AD元件统一排放位置快捷键是什么?

    AD元件统一排放位置快捷键是多少
    发表于 09-30 04:30

    采用STM32上个GPIO口控制对应的个LED点亮和熄灭

    STM32F103RB芯片的NANO版本,通过编写软件,用GPIO端口控制LED闪烁。1.3系统设计1.3.1硬件设计本设计采用STM32上其中个GPIO口控制对应的个LED
    发表于 12-15 06:08

    个LED点亮过程的本质是什么

    不知道你是否想过,个LED点亮过程的本质是什么。当你是个小白的时候,点亮个LED
    发表于 02-17 06:58

    点亮个闪亮led

    单片机点亮
    发表于 03-28 14:26 1次下载

    教教大家如何花式点亮一排

    又是流水灯!这次使用 74HC595 扩展 IO 口。对于 arduino 来说,IO 口资源是很紧张的,迟早会遇到不够用的时候,这时候就需要扩展。使用 74HC595 是种比较常见的方案。
    的头像 发表于 05-02 09:05 1.7w次阅读
    <b class='flag-5'>教教</b><b class='flag-5'>大家</b>如何<b class='flag-5'>花式</b><b class='flag-5'>点亮</b><b class='flag-5'>一排</b><b class='flag-5'>灯</b>

    教教大家如何花式点亮一排,老司机准备起飞了!

    又是流水灯!这次使用 74HC595 扩展 IO 口。对于 arduino 来说,IO 口资源是很紧张的,迟早会遇到不够用的时候,这时候就需要扩展。使用 74HC595 是种比较常见的方案。
    的头像 发表于 11-26 14:28 4586次阅读
    <b class='flag-5'>教教</b><b class='flag-5'>大家</b>如何<b class='flag-5'>花式</b><b class='flag-5'>点亮</b><b class='flag-5'>一排</b><b class='flag-5'>灯</b>,老司机准备起飞了!

    51单片机——点亮个LED

    51单片机——点亮个LED文章目录51单片机——点亮个LED
    发表于 11-23 18:06 16次下载
    51单片机——<b class='flag-5'>点亮</b><b class='flag-5'>一</b>个LED<b class='flag-5'>灯</b>

    鸿蒙上点亮LED

    篇我们成功的在鸿蒙开发板上输出了 Hello World!这篇将带大家点亮 LED
    的头像 发表于 01-16 10:28 2020次阅读