在 Arduino 中读取传感器时按下按钮
Push a button while reading sensor in Arduino
我一直在做一个小温度计项目来学习 Arduino,有一件烦人的事情我不知道如何解决。
我有两个按钮来设置最低和最高温度,当我按下按钮时,它应该设置显示的最低和最高温度。
问题是有时(50% 的时间)当我在读取温度传感器的过程中按下按钮时,按钮不起作用。我按下它,但未设置 Min/Max 温度,因为 Arduino 卡在读取温度传感器中。
有什么技巧可以解决这种问题吗?例如,如果我有一个用于输入数字的键盘,我想我也会遇到同样的问题,但它不是 "user-friendly"。
这是我使用的部分代码的示例:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
//variables declaration...
void setup() {
sensors.begin();
sensors.getAddress(sensor1, 0);
pinMode(buzzer, OUTPUT);
pinMode(btBuzzer, INPUT);
pinMode(btMin, INPUT);
pinMode(btMax, INPUT);
}
void loop() {
readButtons();
playBuzzer();
readTemperature();
printDisplay();
delay(150);
}
void readButtons(){
if(digitalRead(btBuzzer)){
buzzerOn = !buzzerOn;
}
if(digitalRead(btMin)){
if(tempMin == 69)
tempMin = 59;
else
tempMin++;
}
if(digitalRead(btMax)){
if(tempMax == 75)
tempMax = 63;
else
tempMax++;
}
}
void readTemperature(){
sensors.requestTemperatures();
temperature = sensors.getTempC(sensor1);
}
//lots of other methods
学习编码的一些最佳方法存在于如何回答这个问题中。
我想建议做的是尝试为您的代码计时。请记住 loop() 正在创建一个重复结构。因此,我们可以说计算机每次循环 运行 需要多长时间。当我们有一个像按下按钮这样的中断时,它如何影响循环中的迭代,它是否取决于如何让处理器休息(延迟)。
延迟是必需的,以便不执行所谓的 "spin" 处理器(让处理器尽可能快地完成大量工作以完成任何事情)。但是,请注意代码如何不考虑更改我们延迟多长时间完成的工作?
现在让我们想象一下处理器实际上可以非常快地多次执行该循环。请记住,仅 150 毫秒的延迟时间并不长。因此,也许按下一个按钮就足以将 tempMin 快速连续地从 59 设置为 69 并循环多次,而不是一次只增加一个数字。
您在这里拥有的是学习调试的机会。第一个技巧是确定循环 运行ning 是太快还是太慢;您是否获得了所需的功能,最后是否可以在知道问题发生得太快或太慢后重新提出问题。
现在,我建议看看全局变量和有限状态机(即,如果你处于按下按钮的状态,在你完成你的状态之前不要接受任何进一步的按钮按下,并且只在已知方法)。
正如其他人在这里指出的那样,按下按钮可能不会在您使用 digitalRead(btBuzzer)
查询 pin 的同时发生。这种类型的问题就是所谓的 "interrupts" 的发明目的,它允许您响应在您不监视感兴趣的引脚时可能发生的事件。
例如,Arduino UNO R3 允许在引脚 2 和 3 上进行中断。您应该查找 attachInterrupt() 的参考资料。处理器将在您注册的事件("interrupt")中执行回调函数(例如,引脚 2 上的电压从低变为高)。这意味着您将不再需要从主循环中调用 readButtons()
函数。
我一直在做一个小温度计项目来学习 Arduino,有一件烦人的事情我不知道如何解决。
我有两个按钮来设置最低和最高温度,当我按下按钮时,它应该设置显示的最低和最高温度。 问题是有时(50% 的时间)当我在读取温度传感器的过程中按下按钮时,按钮不起作用。我按下它,但未设置 Min/Max 温度,因为 Arduino 卡在读取温度传感器中。
有什么技巧可以解决这种问题吗?例如,如果我有一个用于输入数字的键盘,我想我也会遇到同样的问题,但它不是 "user-friendly"。
这是我使用的部分代码的示例:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
//variables declaration...
void setup() {
sensors.begin();
sensors.getAddress(sensor1, 0);
pinMode(buzzer, OUTPUT);
pinMode(btBuzzer, INPUT);
pinMode(btMin, INPUT);
pinMode(btMax, INPUT);
}
void loop() {
readButtons();
playBuzzer();
readTemperature();
printDisplay();
delay(150);
}
void readButtons(){
if(digitalRead(btBuzzer)){
buzzerOn = !buzzerOn;
}
if(digitalRead(btMin)){
if(tempMin == 69)
tempMin = 59;
else
tempMin++;
}
if(digitalRead(btMax)){
if(tempMax == 75)
tempMax = 63;
else
tempMax++;
}
}
void readTemperature(){
sensors.requestTemperatures();
temperature = sensors.getTempC(sensor1);
}
//lots of other methods
学习编码的一些最佳方法存在于如何回答这个问题中。 我想建议做的是尝试为您的代码计时。请记住 loop() 正在创建一个重复结构。因此,我们可以说计算机每次循环 运行 需要多长时间。当我们有一个像按下按钮这样的中断时,它如何影响循环中的迭代,它是否取决于如何让处理器休息(延迟)。
延迟是必需的,以便不执行所谓的 "spin" 处理器(让处理器尽可能快地完成大量工作以完成任何事情)。但是,请注意代码如何不考虑更改我们延迟多长时间完成的工作? 现在让我们想象一下处理器实际上可以非常快地多次执行该循环。请记住,仅 150 毫秒的延迟时间并不长。因此,也许按下一个按钮就足以将 tempMin 快速连续地从 59 设置为 69 并循环多次,而不是一次只增加一个数字。 您在这里拥有的是学习调试的机会。第一个技巧是确定循环 运行ning 是太快还是太慢;您是否获得了所需的功能,最后是否可以在知道问题发生得太快或太慢后重新提出问题。 现在,我建议看看全局变量和有限状态机(即,如果你处于按下按钮的状态,在你完成你的状态之前不要接受任何进一步的按钮按下,并且只在已知方法)。
正如其他人在这里指出的那样,按下按钮可能不会在您使用 digitalRead(btBuzzer)
查询 pin 的同时发生。这种类型的问题就是所谓的 "interrupts" 的发明目的,它允许您响应在您不监视感兴趣的引脚时可能发生的事件。
例如,Arduino UNO R3 允许在引脚 2 和 3 上进行中断。您应该查找 attachInterrupt() 的参考资料。处理器将在您注册的事件("interrupt")中执行回调函数(例如,引脚 2 上的电压从低变为高)。这意味着您将不再需要从主循环中调用 readButtons()
函数。