查看: 91697|回复: 100

按键控制LED实验

  [复制链接]

该用户从未签到

发表于 2017-12-18 00:25 | 显示全部楼层 |阅读模式
本文节选自《Arduino程序设计基础》


我们要结合数字输入输出功能,制作一个可控制的LED。实现按住按键时,点亮LED,放开按键后,熄灭LED的效果。
实验中我们将用到按键或者按键模块,常见的有2脚按键和4脚按键,其内部如图2-25所示。当按下按键时,就会接通按键两端,放开时,两端会再次断开。
aa.jpg

所需材料
Arduino、面包板、LED一个、按键一个、220Ω电阻一个、10KΩ电阻一个

连接示意图
aaaaa.png

原理图
aaaaaa.png

如上图所示,我们使用了两个电阻。LED的一端,我们使用了220Ω的电阻,按键一端,我们使用了10K的电阻,两个电阻的作用分别如下:

------------------------------------------------------------
限流电阻
一般LED的最大能承受的电流为25mA,如若直接将LED连接到电路中,当其点亮时,如果电流过大,很容易烧毁。如图2-24所示,我们在LED一端串联了一个电阻R2,这样做可以控制流过LED的电流,防止损坏LED。这个电阻我们称之为限流电阻。

下拉电阻
在Arduino的2号引脚到GND之前,连接了一个阻值10K的电阻。如果没有该电阻,当未按下按键时,2号引脚会一直处于悬空 状态,此时使用digitalRead() 读取2号引脚状态,会得到一个不稳定的值(可能是高,也可能是低)。添加这个R1电阻到地就是为了稳定引脚的电平,当引脚悬空时,就会识别为低电平。而这种将某节点通过电阻接地的做法,叫做下拉,这个电阻叫做下拉电阻。
------------------------------------------------------------

实现方法分析
当未按下按键时,2号引脚检测到的输入电压为低电平;当按下按键时,会导通2号引脚和VCC,此时2号引脚检测到的输入电压为高电平。通过判断按键是否被按下,来控制LED的亮灭。

示例程序
你可以在 Arduino IDE菜单>文件>示例>02.Digital>Button 中找到以下程序:

  1. /*
  2.   Button

  3. 通过2号引脚连接的按键,控制13号引脚连接的LED

  4. 备注:大多数Arduino的13号引脚上都连接了名为L的LED.
  5. created 2005
  6. by DojoDave <<a href="http://www.0j0.org" target="_blank">http://www.0j0.org</a>>
  7. modified 30 Aug 2011
  8. by Tom Igoe

  9. This example code is in the public domain.

  10. <a href="http://www.arduino.cc/en/Tutorial/Button" target="_blank">http://www.arduino.cc/en/Tutorial/Button</a>
  11. */

  12. // 设置各引脚别名
  13. const int buttonPin = 2;     // 连接按键的引脚
  14. const int ledPin =  13;      // 连接LED的引脚

  15. // 变量定义
  16. int buttonState = 0;         // 存储按键状态的变量

  17. void setup() {
  18.   // 初始化LED引脚为输出状态
  19.   pinMode(ledPin, OUTPUT);      
  20.   // 初始化按键引脚为输入状态
  21.   pinMode(buttonPin, INPUT);     
  22. }

  23. void loop(){
  24.   // 读取按键状态并存储在变量中
  25.   buttonState = digitalRead(buttonPin);

  26.   // 检查按键是否被按下
  27.   // 如果按键按下,那buttonState应该为高电平
  28.   if (buttonState == HIGH) {     
  29.     // 点亮LED
  30.     digitalWrite(ledPin, HIGH);  
  31.   }
  32.   else {
  33.     // 熄灭LED
  34.     digitalWrite(ledPin, LOW);
  35.   }
  36. }
复制代码


编译并上传该程序后,按下按键,你会观察到LED会被点亮,松开按键,LED又会熄灭。


项目进阶
对于在以上项目,我们还可以做如下修改。

连接示意图
bb.png

如上,我们去掉了原来电路中2号引脚连接的下拉电阻,并将按键的一端连接到GND;

原理图
bbb.png

同时,我们需要将原程序setup() 部分中的
  1. pinMode(buttonPin,INPUT);
复制代码

修改为
  1. pinMode(buttonPin,INPUT_PULLUP);
复制代码


这样能使能该引脚上的内部上拉电阻,等效于在该引脚到VCC之间连接一个外部上拉电阻。

-----------------------------------------------------
上拉电阻
同下拉电阻一样,可以稳定I/O口电平,不同的是电阻连接到VCC,将引脚稳定在高电位。这种电阻叫做上拉电阻。
-----------------------------------------------------

这里使用的是内部上拉电阻,也可以使用外部上拉电阻替代。稳定悬空引脚的电平所用电阻应该选择合适的阻值,例如10K。

示例程序
修改后的程序代码如下:

  1. /*
  2. 按键控制LED - 1
  3. <a href="http://www.arduino.cn/" target="_blank">http://www.arduino.cn/</a>
  4. */

  5. int buttonPin = 2;
  6. int ledPin = 13;
  7. int buttonState = 0;

  8. void setup()
  9. {
  10.   // 初始化I/O口
  11.   pinMode(buttonPin,INPUT_PULLUP);
  12.   pinMode(ledPin,OUTPUT);
  13. }

  14. void loop()
  15. {
  16.   buttonState = digitalRead(buttonPin);
  17.   // 按住按键时,点亮LED;放开按键后,熄灭LED。
  18.   if(buttonState==HIGH)
  19.   {
  20.     digitalWrite(ledPin,LOW);
  21.   }
  22.   else
  23.   {
  24.     digitalWrite(ledPin,HIGH);
  25.   }
  26. }
复制代码



接下来我们要对控制程序做一个升级,完成一个新的控制效果。按一下按键,点亮LED;再按一下按键,熄灭LED。

程序代码如下:

  1. /*
  2. 按键控制LED - 2
  3. <a href="http://www.arduino.cn/" target="_blank">http://www.arduino.cn/</a>
  4. */

  5. int buttonPin = 2;
  6. int ledPin = 13;
  7. boolean ledState=false;  // 记录LED状态
  8. boolean buttonState=true;  // 记录按键状态

  9. void setup()
  10. {
  11. // 初始化I/O口
  12.   pinMode(buttonPin, INPUT_PULLUP);
  13.   pinMode(ledPin,OUTPUT);
  14. }

  15. void loop()
  16. {
  17. // 等待按键按下
  18. while(digitalRead(buttonPin)==HIGH){}

  19.   // 当按键按下时,点亮或熄灭LED
  20.   if(ledState==true)
  21.   {
  22.     digitalWrite(ledPin,LOW);
  23.     ledState=!ledState;
  24.   }
  25.   else
  26.   {
  27.     digitalWrite(ledPin,HIGH);
  28.     ledState=!ledState;
  29.   }
  30.   delay(500);
  31. }
复制代码



编译并上传该程序后,每按一下按键,LED状态都会改变。以上程序中,使用了
  1. while( digitalRead(buttonPin)==HIGH ) { }
复制代码


因为在初始化时,我们已经将buttonPin引脚设为了输入上拉状态。如果没有按下按键,使用digitalRead(buttonPin) 读出的值始终为高电平,这个循环也将一直运行;当你按下按键后,digitalRead(buttonPin) 读出了低电平,while循环的判断条件为假,程序会退出这个循环,并开始运行此后的语句。这样我们就实现了一个等待用户按下按键的效果。

程序末尾有一个delay(500) 的延时,它在这里是极其重要的。可以尝试删去这个延时操作,再上传程序到Arduino。你会发现按键经常出现控制失灵的情况。这是因为程序运行的非常快,没有了延时操作,你按下按键到放开按键的间隔时间虽然极短,但loop中的语句可能已经运行了很多次,很难确定你放开按键时正在运行的loop() 循环是点亮还是熄灭LED。正是这样的原因,程序变得不那么好用了。
上面程序中,我们使用延时操作来使两次按键间产生一定的间隔时间,在间隔时间内Arduino会忽略按键按下情况,从而达到区分两次按键的目的。



该用户从未签到

发表于 2018-9-4 11:23 | 显示全部楼层
刚开始不明白 上拉电阻 下拉电阻,细细咀嚼一下,懂了,为了稳定引脚电平状态,不能让引脚处在悬空状态,所以需要接地或者接入高电平,但是又不能直接连,因为这样电路就短接了,所以接入一个大电阻

该用户从未签到

发表于 2019-7-26 16:41 | 显示全部楼层
love294710 发表于 2018-4-20 20:55
谢谢解答
您说这个我知道是取反
只是不太明白这个ledstate=!ledstate取反在这里有什么意义呢  

我也是一名初学者,接触Arduino及编程才一周。对于这个取反值一直无法理解,今天下午盯了它3个小时我感觉我想通了,大家分享一下。
首先我们来看程序的上半部分,里面写到了boolean ledState=false;这个在批注中有写是为了记录接下来程序运行时,你所按键时候,按键返回给状态的存储的地方。这个和之后练习中所涉及到的int counter=0 是一个概念。记录用的。
在loop程序中while(digitalRead(buttonPin)==HIGH){}
在按键没有按下时,Arduino读到的就是高电平,所以条件为真,一直在while的空{}中循环,不做任何动作。
这个if(ledState==true)中的true和else中的false没有先后顺序之分,只是为了给你按键动作时提供一个判断语句
当你按下按键时,Arduino读到了低电平while判断为假,进而运行下面的if程序,(if程序设定如果ledState为true则给ledPin为低电平)这个设定都随心所欲和上面说到的false,和HIGH和LOW都没有关系。。。
接上面话题,while判断为假运行了下面的if程序,给ledPin了低电平的同时,这个ledState的反值(也就是false)赋予给了上述boolean中ledState中。当你再次按下按键时Arduino读到了假值,然后就运行了else部分的程序,从来往复循环。简而言之
按键一次Arduino读到true,那就运行true的程序的同时=!代码将读到的true转换成了false保存到了boolean中去,在你第下次按键时arduino就是读到了boolean中的false,然后就运行了false的程序的同时=!代码将false转换成了true保存到了boolean中去。所以最后要设定个delay(500)毫秒的反应时间好给系统反应保存和运行。

该用户从未签到

发表于 2018-4-20 23:09 | 显示全部楼层
love294710 发表于 2018-4-20 20:55
谢谢解答
您说这个我知道是取反
只是不太明白这个ledstate=!ledstate取反在这里有什么意义呢  

第一次按下按键的时候,LED亮,以后不管你再怎么按按键,LED都亮,永久亮因为ledstate状态恒为false

该用户从未签到

发表于 2018-3-15 13:35 | 显示全部楼层
我试验成功了,虽然里面的原理我还是不太懂

该用户从未签到

发表于 2018-4-16 22:17 | 显示全部楼层
很齐全的算法

该用户从未签到

发表于 2018-4-20 14:38 | 显示全部楼层
代码中的
ledState=!ledState
起什么作用?
如果不用这个有什么影响吗?
纯小白!

点评

取反,如果不懂,请看C语言逻辑运算  详情 回复 发表于 2018-4-20 19:58

该用户从未签到

 楼主| 发表于 2018-4-20 19:58 | 显示全部楼层
love294710 发表于 2018-4-20 14:38
代码中的
ledState=!ledState
起什么作用?

取反,如果不懂,请看C语言逻辑运算

该用户从未签到

发表于 2018-4-20 20:55 | 显示全部楼层
love294710 发表于 2018-4-20 14:38
代码中的
ledState=!ledState
起什么作用?

谢谢解答
您说这个我知道是取反
只是不太明白这个ledstate=!ledstate取反在这里有什么意义呢  
如果这样写有什么弊病吗?
if(ledState==true)
  {
    digitalWrite(ledPin,LOW);
  }
  else
  {
    digitalWrite(ledPin,HIGH);
  }
  delay(500);
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

热门推荐

Arduino数字与字母字体应该如何设置?
Arduino数字与字母字体应
尝试用Arduino uno 做了个小工具,用来控制电脑水冷的运行。 洞洞板已经测试成功,完
WEMOS LOLIN32Lite(ESP32v1.0.0Rev1)入手+引脚图
WEMOS LOLIN32Lite(ESP32v
突发奇想做个精致的蓝牙遥控平衡小车(大学时做过一次,比较笨,用洞洞板焊电路做的比
【Arduino】168种传感器模块系列实验(129)---BH1750光照传感器
【Arduino】168种传感器模
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
16度双足机器人舵机驱动板pca9685连接舵机,舵机没反应
16度双足机器人舵机驱动板
各位同为arduino爱好者的大佬们大家好!想请教一下大家有关舵机驱动板pca9685
pca9685+arduino驱动舵机失败
pca9685+arduino驱动舵机
我网上别人的代码,编译通过且上传,但舵机不转,怎么解决?Arduino uno使用PCA9685模
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表