极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 130081|回复: 49

arduino学习笔记7 - PWM控制LED实验 PWM讲解

  [复制链接]
发表于 2011-7-6 21:30:42 | 显示全部楼层 |阅读模式

本次实验通过PWM来控制一盏LED灯,让它慢慢变亮再慢慢变暗,如此循环。下面是接线图:



  1. /*
  2. 作者:www.geek-workshop.com
  3. 元件:控制板,led,导线,面包板
  4. 用途: 本次实验演示如何通过analogWrite()命令使连接9号端口的LED灯亮度逐渐变化
  5.   */
  6. int brightness = 0;    //定义整数型变量brightness与其初始值,此变量用来表示LED的亮度。
  7. int fadeAmount = 5;    //定义整数型变量fadeAmount,此变量用来做亮度变化的增减量。

  8. void setup()  {
  9.   
  10.   pinMode(9, OUTPUT);// 设置9号口为输出端口:
  11. }

  12. void loop()  {
  13.   
  14.   analogWrite(9, brightness);//把brightness的值写入9号端口

  15.   brightness = brightness + fadeAmount;//改变brightness值,使亮度在下一次循环发生改变
  16.   
  17.   if (brightness == 0 || brightness == 255) {
  18.     fadeAmount = -fadeAmount ; //在亮度最高与最低时进行翻转
  19.   }     
  20.   
  21.   delay(30); //延时30毫秒                       
  22. }
复制代码
本次实验效果如下:



analogWrite()

其作用是给端口写入一个模拟值(PWM波)。可以用来控制LED灯的亮度变化,或者以不同的速度驱动马达。当执行analogWrite()命令后,端口会输出一个稳定的占空比的方波。除非有下一个命令来改变它。PWM信号的频率大约为490Hz.

在使用ATmega168与ATmega328的arduino控制板上,其工作在3,5,6,9,10,11端口。Arduino Mega控制板,可以工作于2-13号端口。在更古老的基于ATmega8的arduino控制板上,analogWrite()命令只能工作于9,10,11号端口。在使用analogWrite()命令前,可以不使用pinMode()命令把端口定义为输出端口,当然如果定义了更好,这样利于程序语言规范。

语法
analogWrite(pin, value)

参数
pin:写入的端口
value:占空比:在0-255之间。

注释与已知问题
当PWM输出与5,6号端口的时候,会产生比预期更高的占空比。原因是PWM输出所使用的内部时钟,millis()与delay()两函数也在使用。所以要注意使用5,6号端口时,空占比要设置的稍微低一些,或者会产生5,6号端口无法输出完全关闭的信号。

PWM(Pulse-width modulation)脉宽调制

PWM是使用数字手段来控制模拟输出的一种手段。使用数字控制产生占空比不同的方波(一个不停在开与关之间切换的信号)来控制模拟输出。额~~这个说的太专业了,还是说的通俗点。
以本次实验来看,端口的输入电压只有两个0V与5V。如我我想要3V的输出电压怎么办。。。有同学说串联电阻,对滴,这个方法是正确滴。但是如果我想1V,3V,3.5V等等之间来回变动怎么办呢?不可能不停地切换电阻吧。这种情况下。。。就需要使用PWM了。他是怎么控制的呢,对于arduino的数字端口电压输出只有LOW与HIGH两个开关,对应的就是0V与5V的电压输出,咱本把LOW定义为0,HIGH定义为1.一秒内让arduino输出500个0或者1的信号。如果这500个全部为1,那就是完整的5V,如果全部为0,那就是0V。如果010101010101这样输出,刚好一半一半,输出端口就感觉是2.5V的电压输出了。这个和咱们放映电影是一个道理,咱们所看的电影并不是完全连续的,它其实是每秒输出25张图片,在这种情况下人的肉眼是分辨不出来的,看上去就是连续的了。PWM也是同样的道理,如果想要不同的电压,就控制0与1的输出比例控制就ok~当然。。。这和真实的连续输出还是有差别的,单位时间内输出的0,1信号越多,控制的就越精确。

在下图中,绿线之间代表一个周期,其值也是PWM频率的倒数。换句话说,如果arduino PWM的频率是500Hz,那么两绿线之间的周期就是2毫秒。 analogWrite() 命令中可以操控的范围为0-255, analogWrite(255)表示100%占空比(常开), analogWrite(127)占空比大约为50%(一半的时间)。




传统方法实现PWM

除了使用analogWrite()命令实现PWM,还可以通过传统方法来控制电平的开关时间来设置。
请看如下代码
  1. void setup()
  2. {
  3.   pinMode(13, OUTPUT);//设定13号端口为输出
  4. }

  5. void loop()
  6. {
  7.   digitalWrite(13, HIGH);
  8.   delayMicroseconds(100); // 大约10%占空比的1KHz方波
  9.   digitalWrite(13, LOW);
  10.   delayMicroseconds(900);
  11. }
复制代码
这种方法的的优点是他可以使用任意数字端口做输出端口。而且可以自己随意设定占空比与频率。一个主要的缺点是任何中断都会影响时钟,这样就会导致很大的抖动,除非你禁用中断。第二个却就是CPU在处理输出的时候,就无法做其他事情了。

上面的代码用到了一个新的命令

delayMicroseconds()

其作用是产生一个延时,计量单位是微秒,1000微秒=1毫秒。目前delayMicroseconds()最大值为16383。如果值大于1000,推荐使用delay() 命令。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2011-8-26 23:49:19 | 显示全部楼层
偶是谁 发表于 2011-7-11 17:59
昨天把上叙实验做了,继续请教老师
int fadeAmount = 5;    //定义整数型变量fadeAmount,问:fadeAmount  ...

就这个问题..........当然弘毅说的是没错,的确是因为3不能被255整除所导致的问题。

但是有很简单的解决方法:
把状态反转语句当中的 "=="改成"<="和">="(注意,0侧是"<=";255侧是">=".不能互换位置)亮度渐变就可以完成循环了。

其实你注意看如果用"==" PWM导致的亮度渐变还是会产生的,只不过只在Arduino刚刚RESET以后进行了一次,也就是因为状态不能反转所以如果brightness > 255以后这个程序就变成没有意义了.......

另外如此改发程序也不完美,因为在反转状态的时候LED会灭一下。这个~~~~主要只是为了说清楚这个问题所以也懒得仔细考虑逻辑。
回复 支持 2 反对 0

使用道具 举报

发表于 2011-7-10 17:37:03 | 显示全部楼层
if (brightness == 0 || brightness == 255) 懂了,条件成立时,执行翻转,条件不成立执行brightness ++5
实现渐变
回复 支持 0 反对 1

使用道具 举报

发表于 2012-1-21 13:12:47 | 显示全部楼层
弘毅 发表于 2012-1-18 19:57
额。。。完全一样的电路连接方法和代码?

恩恩是的
回复 支持 1 反对 0

使用道具 举报

发表于 2011-7-10 13:20:24 | 显示全部楼层
程序看不懂,void loop()  {

  

  analogWrite(9, brightness);//把brightness的值写入9号端口   这里LED=0



  brightness = brightness + fadeAmount;//改变brightness值,使亮度在下一次循环发变                                     这里是brightness =0+5吗
  

  if (brightness == 0 || brightness == 255) {              这里不懂,求解释

    fadeAmount = -fadeAmount ; //在亮度最高与最低时进行翻转

  }     

回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-10 13:38:34 | 显示全部楼层
偶是谁 发表于 2011-7-10 13:20
程序看不懂,void loop()  {

  


是滴,这里是brightness=0+5


  1.   if (brightness == 0 || brightness == 255) {
  2.     fadeAmount = -fadeAmount ; //在亮度最高与最低时进行翻转
  3.   }     
复制代码
这里的0与255是pwm的最大值与最小值(也意味着亮度的最大与最小),意思是brightness达到0或者255的时候,fadeAmount值从5变为-5或者是-5变为5.
回复 支持 反对

使用道具 举报

发表于 2011-7-10 17:42:56 | 显示全部楼层
谢谢,又学一招。
叹。。。看都看不懂,什么时候能像老师一样应用自如呢
回复 支持 反对

使用道具 举报

发表于 2011-7-10 18:27:15 | 显示全部楼层
刚看了视频,很有早先流行的呼吸灯的味道,不知道电脑上的是不是也是类似程序
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-10 21:28:51 | 显示全部楼层
偶是谁 发表于 2011-7-10 18:27
刚看了视频,很有早先流行的呼吸灯的味道,不知道电脑上的是不是也是类似程序

是滴,那种呼吸灯也是一样的原理。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-10 21:31:58 | 显示全部楼层
偶是谁 发表于 2011-7-10 17:42
谢谢,又学一招。
叹。。。看都看不懂,什么时候能像老师一样应用自如呢

其实偶也是现学现卖了。。。偶发现写教程是最好的学习方法
回复 支持 反对

使用道具 举报

发表于 2011-7-11 17:59:38 | 显示全部楼层
昨天把上叙实验做了,继续请教老师
int fadeAmount = 5;    //定义整数型变量fadeAmount,问:fadeAmount = X;
X=3时,好像可以实现渐变,为什么,brightness不可能 == 255
设X=6,7,8时,程序渐变异常,为什么会产生这种异常情况

if (brightness == 0 || brightness == 255)   设brightness == 200程序渐变也变异常
问:整数型变量fadeAmount和整数型变量brightness,如何设置数值,才能控制渐变量之间长短
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-11 20:28:30 | 显示全部楼层
偶是谁 发表于 2011-7-11 17:59
昨天把上叙实验做了,继续请教老师
int fadeAmount = 5;    //定义整数型变量fadeAmount,问:fadeAmount  ...


if (brightness == 0 || brightness == 255)这个条件下,5可以渐变,3也可以渐变,但是6,7,8不可以,原因是因为6,7,8不能整除255。255/5=51,255/3=85。5和3都可以整除255。

如果是int fadeAmount = 5这个条件下,设if (brightness == 0 || brightness == 200) 是可以的,因为5可以整除200。

fadeAmount一定要求可以整除brightness的最大值,整除的结果越大,渐变实验越久,整除的结果越小,渐变时间越短。如果无法整除,就无法达到设定条件来进行翻转,也就无法实现渐变。

假设if (brightness == 0 || brightness == 255),分别设置int fadeAmount = 1,int fadeAmount = 5,int fadeAmount = 15.可以发现,渐变速度15>5>1.
回复 支持 反对

使用道具 举报

发表于 2011-7-12 09:34:36 | 显示全部楼层
是的啊,255/3=85  小学没上好,,谢谢老师回复
回复 支持 反对

使用道具 举报

发表于 2011-8-26 23:34:38 | 显示全部楼层
嘿嘿~~~~教程不错哦!!!
回复 支持 反对

使用道具 举报

发表于 2011-8-26 23:51:34 | 显示全部楼层
另外还有~~~~~关于
brightness = brightness + fadeAmount;
的写法可以这样:
brightness += fadeAmount;
当然,这两者除了写法上的区别别的似乎也没什么区别了(有可能有,反正我也不知道).........
回复 支持 反对

使用道具 举报

发表于 2011-9-25 10:39:51 | 显示全部楼层
坏鸟大哥是高手,谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 13:19 , Processed in 0.048408 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表