4. Arduino与PWM控制LED灯的亮暗连续变化 4.1 问题描述:如何用Arduino控制LED灯的亮暗连续变化 在前面的实例当中,咱们都是用基于Arduino主板来控制LED灯的亮或者暗的变化。从电压的角度解释就是只有高、低两种电平,从数字模拟的角度就是只有1和0两个数值。但是不能是LED的电压在高到低的变化,中间过程没有得到体现。但有时要有,比如在歌舞厅或演唱会上,为了达到很好的灯光效果,有时要使灯的亮暗变化是个渐渐的过程,即是个连续变化的过程。为了实现这个目的,必须使Arduino能控制输出一个连续变化的电压,这就用到我们这一章要用到的新概念PWM(Pulse Width Modulation),脉冲宽度调制,简称脉宽调制。这种调制技术广泛应用在控制舵机连续运转,音乐播放,功率控制等具体实例中。 4.2 所需材料 这章所需材料非常简单,和第一章的一样。只不过在Arduino主板上采用的端口不一样,不能随便接入,如表4‐1所示。 表4-1:所需材料序号名称数量作用备注1Arduino软件1套提供IDE环境最新版本1.052ArduinoUNO开发板1块控制主板各种版本均可3USB线1条烧录程序随板子配送4杜邦线若干条连接组件可选5发光二极管(LED)1个LED闪烁可选6电阻220欧限流可选7面包板可选所需材料的实物如图4‐5所示。 4.3 实验原理 在陈述实验原理之前,给出与实验相关的概念。 数字信号:是指幅度取值离散的,其值被限制在有限域范围内,如二进制码就是一种离散信号。其特点是抗干扰能力强,易于数字信号处理。现在很多信号基本上都是数字信号,如手机信号,计算机处理信息等等。 模拟信号:是指其信号波形是连续变化的,咱们可以在任意的瞬间取值。由于模拟信号易受干扰影响,不容易处理,一般都是先将模拟信号离散成数字信号,以便处理。两者的区别如图4‐1所示。 图4‐1 数字信号与模拟信号的区别 PWM,脉宽调制:即通过一系列脉冲的宽带来调制(或控制)来等效得到所需要的波形(包括形状和幅值),比如图4‐2中,咱们可以通过很多脉冲来恢复得到正弦波形。这也可以从高中所学积分的面积等效的原理解释。比如第1个脉冲所围的面积,等于第一个脉冲前由正弦波形围成的面积。通过改变方波的占空比,就可以改变等效的输出电压波形。试想一下,如果每个脉冲的宽度相等,则所等效的波形为一条直线,也即为直流电压信号。PWM调制广泛应用与电机调速和阀门控制中。比如现在的电动车就是通过PWM调速的。 图4‐2 PWM调制得到正弦波形 实验原理:在Arduino中,只有数字输出端口。所有的端口都可以输出数字信号。所以咱们在前面的实验中,可以任意的数字端口中输出信号,使得LED灯在亮与暗之间切换,也即只有高、低两种电平,或0V和5V。那咱们要通过Arduino控制一个电机的运行怎么办呢?因为这是一条连续的波形。别急,Arduino的功能非常强大。它可以通过端口3,5,6,9,10,11来实现。注意到这些端口的数字标号前面都有一个“~”符号加以区别。这主要是通过PWM技术来实现的。比如,在本实验中,9端口是数字端口,但它具有PWM的功能,当我将数字信号加载至此端口时,9端口通过PWM技术将输入的数字信号转变成模拟信号输出。这是一个连续波形,所以可以将其应用到电机的调速当中。注:实际上得到的值还是离散的,只不过脉冲间隔非常小,咱们无法用肉眼看出来。就好比电影一样,其实电影也是由无数多张离散的图片(数据帧)组成的。 图4‐3 占空比示意图 理论上,通过PWM技术,我们可以得到0~5V之间任意数字的电压值,而不仅仅是0V和5V。这主要是通过Arduino语句analogWrite(pin,value)命令来实现的,意思是输出模拟电压,其中pin表示输出的端口号是多少,本实验是从9号端口输出,value是数字信号的输出值,其范围在0~255。不同的数值value表示不同的占空比,在图4‐3中,analogWrite(9,255)表示在端口9输出连续的5V电压,analogWrite(9,64)在9号端口输出多少呢?这时输出的电压U=64/255*5V=1.25V,其中64/255表示占空比为25%。那我要输出任意值的电压怎么计算呢?比如咱们要得到U=1.8V的电压,那么用数字信号表示的数值value=U*255/5V=51U(V)。所以,当U=1.8V时,value=91.8。通过analogWrite(9,91.8)即可在9号端口输出1.8V的连续电压值。此外,占空比指的是占用与空闲的比值,图4‐3中很形象地表示出来了。值得指出的是,analogWrite(pin,value)中value的范围是0~255,每单位的电压为5V/255,而analogRead(pin)读入返回值的范围是0~1024,每个单位的电压值为5V/1024。 4.4 实验与代码 在前面我们已经陈述过,这个电路的原理非常简单。跟第1个例子很类似,只不过本实验中对与连接LED灯的输出端口有限制,只能是Arduino主板上的3,5,6,9,10,11。当然用其他方法另当别论。其原理,电路实现分别如图4‐4,4‐5所示。 图4‐4 实验原理图 图4‐5 实验实现图 代码分析 01 / Program 4: 用Arduino和PWM技术实现LED灯由亮到暗的连续变化 02 int brightness = 0; //定义整数型变量brightness与其初始值,此变量用来表示LED的亮度。 03 int fadeAmount = 5; //定义整数型变量fadeAmount,此变量用来做亮度变化的增减量。 04 05 void setup() { 06 07 pinMode(9, OUTPUT);// 设置9号口为输出端口: 08 } 09 10 void loop() { 11 12 analogWrite(9, brightness);//把brightness的值写入9号端口 13 14 brightness = brightness + fadeAmount;//改变brightness值,使亮度在下一次循环发生改变 15 16 if (brightness == 0 || brightness == 255) { 17 fadeAmount = ‐fadeAmount ; //在亮度最高(5V)与最低(0V)时进行转换 18 } 19 20 delay(50); //延时50毫秒,即保持brightness+fadeAmount状态50ms 21 } 4.5 要点总结 1)虽然数字信号比模拟信号更有优越性,比如抗干扰等方面,但是在某些地方必须用模拟信号来控制,如电机的转速,音乐播放等。 2)analogWrite(pin,value)中value的范围为0~255。要理清占空比与输出电压之间的关系。 3)Arduino主板上有2种端口。其中的有些端口才能作为模拟信号的输出端口。