Arduino制作流水灯

全篇共 3620 字。按500字/分钟阅读,预计用时 7.2 分钟。总访问 499 次,日访问 6 次。

最终效果

预备知识

这篇文章是我在上一篇 《Arduino硬件编程入门》 的基础上记录的。在上一篇文章中我主要记录了如何点亮第一颗 LED 灯以及点亮一排 LED 灯,包括如何使用面包板,以及学会了三个常用函数:pinMode()digitalWrite()delay()。这篇文章记录如何用一排 LED 制造流水灯效果,这种流水灯的效果在城市的街道上的很多招牌上很常见,在公园的夜晚景观中也常常可以看到流水灯效果。

布置电路

本着搞事情就要先从简单的开始搞起,再到复杂的原则,我不打算一开始就在面包板上插满一排 LED,一开始只需要布置三颗就足够了。除了三颗 LED 灯,再准备四根导线,其中一根作为接地线,其余三根分别连接引脚和 LED 灯,我这里选用11号、12号和13号引脚。最后再布置三个220V的电阻,因为 LED 的内部电阻很小,如果长时间使用 LED 就需要给每一个 LED 串联一个电阻,起限流的作用。

程序控制流水灯

先用笨办法写一遍程序。

void setup() {
  // 将11号、12号、13号引脚都设置为输出模式
  pinMode(13, OUTPUT);  
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() {
  // 新的一次循环开始
  
  // 连接13号引脚的 LED 亮
  digitalWrite(13, HIGH);
  // 连接12号引脚的 LED 灭
  digitalWrite(12, LOW);
  // 连接11号引脚的 LED 灭
  digitalWrite(11, LOW);
  // 保持半秒钟
  delay(500);
  
  //  连接13号引脚的 LED 灭
  digitalWrite(13, LOW);
  //  连接12号引脚的 LED 亮
  digitalWrite(12, HIGH);
  //  连接11号引脚的 LED 灭
  digitalWrite(11, LOW);
  // 保持半秒钟
  delay(500);
  
  //  连接13号引脚的 LED 灭
  digitalWrite(13, LOW);
  //  连接12号引脚的 LED 灭
  digitalWrite(12, LOW);
  //  连接11号引脚的 LED 亮
  digitalWrite(11, HIGH);
  // 保持半秒钟
  delay(500);
}

虽然我们能很容易理解上面的代码,但是这样的写法既浪费阅读和编码时间也浪费存储空间,因为它太不简洁了。所以就要用到 for(){} 循环结构。

void setup() {
  // 给13号、12号和11号引脚设置输出模式
  for(int i = 13; i <= 11; i--){
    pinMode(i, OUTPUT);
  }
}

void loop() {
  for(int i = 13; i >= 11; i--){
    // 点亮这一次循环中引脚 i 连接的 LED
    digitalWrite(i, HIGH);
    
    // 亮半秒
    delay(500);
    
    // 立即灭
    digitalWrite(i, LOW);
    
    // 立即点亮下一次循环的引脚 i+1 所连接的 LED
  }
}

明显减少了代码,却达到了相同的效果。然后你可以布置更多的 LED,让流水灯看起来更震撼,甚至可以考虑将 LED 围成一个圈或者其他任何有意义的效果,总之原理是相同的,创意应用是无限的。

下面两节回顾前面学过的关于Arduino的知识吧。

数字信号的输出与输入

以前总听说数字信号就是指0和1。但现在更准确地说,数字信号的本质是电路的通与断,或者高电平与低电平。在Arduino编程中有这样一些语句(下方代码段只是语句的罗列,不能直接放到程序中):

// 将2号引脚设置为输出模式
pinMode(2, OUTPUT);
// 将6号引脚设置为输出模式
pinMode(6, OUTPUT);

// 向2号引脚输出高电平
digitalWrite(2, HIGH);
// 向6号引脚输出低电平
digitalWrite(6, LOW);

其中,digitalWrite(2, HIGH)语句的含义就是将2号引脚设置为高电平;digitalWrite(6, LOW)语句的含义就是将6号引脚设置为低电平。输出高电平的意思就是该引脚能输出Arduino开发板的工作电压(比如我用的Arduino UNO的工作电压是5V)。输出低电平就是该引脚输出的的电压为0V。

在Arduino编程中HIGH是一个常量,也可以用1代表;LOW也是一个常量,也可以用0代表。所以,上边的代码段可以这样写:

pinMode(2, OUTPUT);
pinMode(6, OUTPUT);

digitalWrite(2, 1);
digitalWrite(6, 0);

所以,可以这样说。数字信号在Arduino编程中可以用数字1和0表示,也可以用HIGHLOW表示。数字信号在电路中可以使用电路的通与断表示。

一些参考书中说,HIGHLOW的可读性更好,可我觉得并不完全是这样。使用10表示,有时候更加简单直接,反而更便于理解。但不得不承认,HIGHLOW10更加语义化。OUTPUT 也可以使用1表示:

pinMode(2, 1);
pinMode(6, 1);

digitalWrite(2, 1);
digitalWrite(6, 0);

做过了几个Arduino开发实验。我发现,凡是模式设置为输出的引脚,都是用来写数字信号的;凡是模式设置为输入的引脚,都是用来读取信号的。正如上方代码写得那样,2号引脚和6号引脚的模式被设置为1(输出模式)。因此,才能使用digitalWrite()函数向2号引脚和6号引脚写入数字信号。设为输出模式的引脚会产生高/底电压。而输出的是一股接着一股的电流,电路的一通一断就是数字信号在变化的缘故。设为输出模式的引脚产生电压的变化,设为输入模式的引脚感应电压的变化。

感应电压变化的引脚用来读取输入数字信号。Arduino编程中使用digitalRead()函数读取输入电压。数字输入引脚将感应到的电压以某两个分界点判断属于高电平还是低电平。拿 Arduino UNO开发板为例,感应到低于1.5V的电压识别为低电平,感应到高于3V的电压就识别为高电平。digitalRead函数会返回数字1或者数字0,1和0就表示指定引脚的感应到的是高电平还是低电平。

我见过的几乎的影视包装效果,都擅于使用1010001001这样的符号形式表达信息化与数字化。但真正的电路中并没有1和0,只有电路的通和断。那只是媒体从业者用一种便于人们直观理解的可视化呈现手段。

输出PWM信号

如果把引脚设置为输出模式,输出高电平就输出5V,输出低电平就不输出电压(0V)。如果想要产生0-5V之间的电压,通过控制单位时间内通与断的占空比来模拟不同的电压值,当然了,单位时间内输出的0,1越多,控制的就越精确。这就叫PWM(Pulse Width Modulation)脉冲宽度调制,简称脉宽调制。

在引脚上输出模电电压,可以让LED时亮时暗,也可以让马达转速时快时慢。在Arduino编程中,使用analogWrite()函数输出模拟电压,引脚会产生稳定的方形波。如果1秒内让Arduino输出500个数字信号,如果500个全是高电平5V电压,则为高电平5V电压;如果全为低电平0V电压,则为低电平电压;如果一半高电平,则输出2.5V电压;以此类推。

也不是每个引脚都能输出PWM信号,比如我用的开发板支持输出PWM信号的引脚分别是3、5、6、9、10和11这六个,在开发板上也很容易找到它们,它们的数字前面有 “~” 符号,比如“~11”。

结语

我对还未达100%熟悉的事物,总是过一段时间就会抹掉关于它的琐碎记忆,完整的记忆被腐蚀的模糊不清,以至于不能仅靠残缺不全的记忆加上自以为是的猜想认为这就是记忆本身;如果能让学习到的知识深入骨髓那最好了,如果不能奢求这些,那就让回忆变得容易些吧。

创作者 » 陈帅华
版权声明 » 自由转载-保持署名-非商用-非衍生
发布日期 » 2019年7月25日 周四
陈帅华个站动态先知道,请关注一个教程。
一个教程微信个人订阅号
关键词