YFROBOT创客社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 24386|回复: 1
打印 上一主题 下一主题

Arduino OneButton Library -- 很好用的按键库(支持单击、双击、长按)无阻塞-推荐

[复制链接]

签到天数: 866 天

[LV.10]以坛为家III

跳转到指定楼层
楼主
发表于 2020-2-25 15:44:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原文地址:http://www.mathertel.de/Arduino/OneButtonLibrary.aspx
Arduino OneButton库
该草图和库显示了如何通过检测一些典型的按钮按下事件(例如单击,双击和长时间按下按钮)来使用输入引脚。这使您可以将同一按钮重复使用以实现多种功能,并降低硬件投资。

下载项目文件
您可以使用git或svn从github下载OneButton库,或将最新版本下载为zip文件。
(标有“下载ZIP”的右侧按钮)
https://github.com/mathertel/OneButton

介绍
从Arduino编程开始,您肯定会看过简单的Button教程,以了解如何从按钮中读取信息,以及Debounce示例,该示例演示了如何通过消除因触点抖动而产生的短时开/关序列,从按钮中获得清晰的信号。
结果是一个名为OneButton的小型库,您可以轻松地将其连接到草图。这篇文章向您展示了如何使用该库,如何实现它,并在最后给出了简短的参考表。
我网站上的这篇文章也是为了解释一些好的实现方法而写的,所以我希望所有超链接都可以指导您找到其他重要的示例和教程(如果您还没有看过的话)。

读取按钮而不阻塞程序
上面提到的简单示例的一个缺点是,它们使用loop()函数,因此很难重用它们包含的代码。
我希望您的草图必须做更复杂的事情,并且您需要使用loop()函数来实现自己的目的。因此,避免实现此功能是库和可重用代码的普遍要求。相反,应该经常调用库的tick()函数。在此功能内,您将找到用于检测所有3个可用事件的编码。
对于3个已实现事件中的任何一个,您都可以注册一个函数以将您的代码链接到库。当检测到相应情况时,将调用您的函数。

使用OneButton库的示例
这是一个简单的示例,当双击引脚A1上的按钮时,该示例使用OneButton库更改引脚13上的默认led。
[C] 纯文本查看 复制代码
/*
 S01_SimpleOneButton
 Simple OneButton sketch that shows how to ???

 The circuit:
 * Connect a pushbutton to pin A1 (ButtonPin) and ground
 * and see results on pin 13 (StatusPin).
 * 03.03.2011 created by Matthias Hertel
 */

#include "OneButton.h"

// Setup a new OneButton on pin A1.  
OneButton button(A1);


// setup code here, to run once:
void setup() {
  // enable the standard led on pin 13.
  pinMode(13, OUTPUT);      // sets the digital pin as output
  
  // link the doubleclick function to be called on a doubleclick event.   
  button.attachDoubleClick(doubleclick);
} // setup
  

// main code here, to run repeatedly: 
void loop() {
  // keep watching the push button:
  button.tick();

  // You can implement other code in here or just wait a while 
  delay(10);
} // loop


// this function will be called when the button was pressed 2 times in a short timeframe.
void doubleclick() {
  static int m = LOW;
  // reverse the LED 
  m = !m;
  digitalWrite(13, m);
} // doubleclick

请还阅读内联注释。您可以在此处看到在第二次释放按钮时如何将doubleclick功能附加到该情况。

实施细节
如果您想在这里查看图书馆的工作方式,请做一些解释:
在tick()函数内的OneButton库中,您可以找到用于检查输入引脚以检测单击,双击或长按情况的实现。这种实现称为有限状态机(FSM),它实现以下状态图:

每次调用tick()函数时,都会针对当前状态和输入值进行分析,并在适用时调用外部函数和/或更改当前状态。特别是OneButton库的实现永远不会调用delay()或类似的函数,因此在大多数情况下会很快返回。
这是此(软件)计算机如何工作的简要说明:

输入值
此实现使用的第一个输入值是数字输入引脚的值。该引脚在内部被拉高,并且在按下时被附带的按钮拉低。
在状态机功能的开头完成该事件源的实现:
[C] 纯文本查看 复制代码
int buttonLevel = digitalRead(_pin); // current button signal.

所需的其他输入是当前时间。millis()给出了一个安静的良好线性时序值,可以完美地用于检测经过特定时间量。当前值被复制到now 变量中:
[C] 纯文本查看 复制代码
unsigned long now = millis(); // current (relative) time in msecs.


状态
在一次呼叫和随后一次呼叫之间必须记住的信息称为状态。特别是有一个称为状态的变量,它将使用上图中的数字保存有关当前情况的信息,而另一个变量将存储第一次按下按钮时的时间。
这两个变量是在状态机函数中定义的,并用static关键字标记,因此它们将在下次调用tick函数时存储该值。
[C] 纯文本查看 复制代码
int _state = 0; // starting with state 0: waiting for button to be pressed
unsigned long _startTime; // will be set in state 1


起始情况(状态0)
机器从等待按钮按下的情况开始(状态0)。如果未按下该按钮,则它仅从函数返回,因为此后不久将再次调用该函数。
但是,如果按下按钮,则必须记住另一种情况(状态1)已经到位。由于稍后进行了时序分析,因此还必须记住当前时间。就这样。
[C] 纯文本查看 复制代码
if (_state == 0) { // waiting for One pin being pressed.
  if (buttonLevel == ButtonDown) {
    _state = 1; // step to state 1
    _startTime = now; // remember starting time
  } // if



第一次按下按钮(状态1)
下次调用该函数时(几毫秒后),它是刚刚按下按钮的开始情况(状态0)或新情况(状态1)。在这种情况下,只需要等到再次释放按钮并切换到下一种情况(状态2)即可。当仍然按下该按钮时,无需执行任何操作,并且由于人的手指不是那么快,这种情况(状态1)可能会停留一段时间。
当这种情况(状态1)持续的时间长于“长时间”(当前为1秒)时,将检测到另一种情况(状态6)。这是通过将实际时间加上定义的时间间隔与持续的开始时间进行比较来完成的。在这种情况下,将调用外部press()函数。
[C] 纯文本查看 复制代码
} else if (_state == 1) { // waiting for One pin being released.
  if (buttonLevel == ButtonUp) {
    _state = 2; // step to state 2

  } else if ((buttonLevel == ButtonDown) && (now > _startTime + _pressTicks)) {
    if (_pressFunc) _pressFunc();
    _state = 6; // step to state 6
  } // if
  

该按钮是从第一次单击释放的(状态2)
在这种情况下(状态2),按钮已经释放,可能会发生两件事:
如果经过了一段时间并且第二次没有按下按钮,则将调用外部click()函数,并且状态将重置为0。
如果在经过第二次按钮之前第二次按下按钮,则检测到下一种情况(状态3)将继续:
[C] 纯文本查看 复制代码
} else if (_state == 2) { // waiting for One pin being pressed the second time or timeout.
  if (now > _startTime + _clickTicks) {
    // this was only a single short click
    if (_clickFunc) _clickFunc();
    _state = 0; // restart.

  } else if (buttonLevel == ButtonDown) {
    _state = 3; // step to state 3
  } // if


等待菜单销第二次释放(状态3)
在定义的时间范围内检测到第二次单击后的最终状况(状态3)是等待按钮被释放。发生这种情况时,将调用外部doubleClick()函数并重置状态机,以便一切都可以从头开始。
[C] 纯文本查看 复制代码
} else if (_state == 3) { // waiting for One pin being released finally.
  if (buttonLevel == ButtonUp) {
    // this was a 2 click sequence.
    if (_doubleClickFunc) _doubleClickFunc();
    _state = 0; // restart.
  } // if


等待菜单销第二次释放(状态6)
这种情况(状态6)与第二次单击等待按钮释放后的情况非常相似。发生这种情况时,将重置状态机,以便一切都可以从头开始。
[C] 纯文本查看 复制代码
} else if (_state == 6) { // waiting for One pin being release after long press.
  if (buttonLevel == ButtonUp) {
    _state = 0; // restart.
  } // if  


摘要
在很多情况下,实现有限状态机(FSM)都很容易,它可以大大降低实现复杂性,还可以帮助您为Arduino编写伪多任务草图。

OneButton库的安装
OneButton功能的代码可通过使用库技术获得,并附带2个文件。您可以在Library Tutorial中找到有关如何构建库的信息。
通过在库文件夹中创建一个新的子文件夹(称为OneButton)并将文件(OneButton.h,OneButton.cpp)复制到其中,可以很容易地将代码安装为库。此后您应该重新启动Arduino,因为在启动时会检测到可用的库。
在这种情况下,您必须使用带有尖括号的#include语句包括库:
[C] 纯文本查看 复制代码
#include <OneButton.h>


另一种方法是将相同的2个文件保留在草图文件夹中。然后,当您下次打开草图时,这些文件在Arduino开发环境中可用。如果您想尝试新事物或想要改进库,那么这很好。
在这种情况下,您必须使用#include语句并在双引号中包含库:
[C] 纯文本查看 复制代码
#include“ OneButton.h”


样品
库文件夹中有一个示例草图,其中显示了如何设置库,如何将特殊功能绑定到doubleclick事件以及如何切换输出引脚。

变更日志
30.08.2011首次发布版本。
2011年3月12日更新为与Arduino 1.0环境兼容。
2013年7月4日添加了示例草图BlinkMachine。
草图显示了如何设置库并绑定​​“机器”,该机器可以使LED缓慢或快速闪烁。



本帖子中包含更多资源

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

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 支持支持 反对反对

该用户从未签到

沙发
发表于 2020-3-1 08:21:18 | 只看该作者
最近在学python  用来捣鼓下arduino 应该可以吧
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|小黑屋|联系我们|YFROBOT ( 苏ICP备20009901号-2  

GMT+8, 2024-4-20 02:25 , Processed in 0.047155 second(s), 24 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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