c++ - Arduino - 通过按钮停止循环
问题描述
所以我一直在试验 TinkerCad,等待我的 arduino 到货。目前我有一个 LED 灯循环,我想通过按下按钮来启动和停止循环。
目前我可以通过按钮启动我的循环,但不能通过按下相同的按钮来停止循环。这和去抖有关系吗?
const int button = 10;
const int led1 = 8;
const int led2 = 4;
const int led3 = 3;
const int timedelay = 250;
boolean buttonstate = false;
void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
if(digitalRead(button)==HIGH) // check if button is pushed
buttonstate = !buttonstate; //reverse buttonstate value
if(buttonstate==true)
{
digitalWrite(led1, HIGH);
delay(timedelay);
digitalWrite(led1, LOW);
delay(timedelay);
digitalWrite(led2, HIGH);
delay(timedelay);
digitalWrite(led2, LOW);
delay(timedelay);
digitalWrite(led3, HIGH);
delay(timedelay);
digitalWrite(led2, HIGH);
delay(timedelay);
digitalWrite(led1, HIGH);
delay(timedelay);
digitalWrite(led3, LOW);
delay(timedelay);
digitalWrite(led2, LOW);
delay(timedelay);
digitalWrite(led1, LOW);
delay(timedelay);
digitalWrite(led1, HIGH); }
else {
digitalWrite(led1, HIGH);
}
}
我的电路设置:
编辑:
我已经调整了我的代码,用毫秒替换了延迟并寻找按钮状态的变化。仍在寻找一种方法来在循环结束时调整 interval_led1 以制作生病的 LED 灯序列。
const int led1 = 13;
const int led2 = 8;
const int led3 = 5;
const int button = 10;
int ledState_led1 = LOW; // ledState used to set the LED
int ledState_led2 = LOW;
int ledState_led3 = LOW;
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_led1 = 0; // will store last time LED was updated
unsigned long previousMillis_led2 = 0;
unsigned long previousMillis_led3 = 0;
long interval_led1 = 500; // interval at which to blink (milliseconds)
long interval_led2 = 600;
long interval_led3 = 700;
boolean buttonstate = false;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis_led1 = millis();
unsigned long currentMillis_led2 = millis();
unsigned long currentMillis_led3 = millis();
bool current_state = digitalRead(button);
bool prev_buttonstate= false;
if(current_state==HIGH && current_state != prev_buttonstate)
{
buttonstate = !buttonstate; //reverse buttonstate value
}
prev_buttonstate = current_state;
if(buttonstate==true)
if (currentMillis_led1 - previousMillis_led1 >= interval_led1) {
previousMillis_led1 = currentMillis_led1;
if (ledState_led1 == LOW) {
ledState_led1 = HIGH;
} else {
ledState_led1 = LOW;
}
digitalWrite(led1, ledState_led1);
}
if(buttonstate==true)
if (currentMillis_led2 - previousMillis_led2 >= interval_led2) {
previousMillis_led2 = currentMillis_led2;
if (ledState_led2 == LOW) {
ledState_led2 = HIGH;
} else {
ledState_led2 = LOW;
}
digitalWrite(led2, ledState_led2);
}
if(buttonstate==true)
if (currentMillis_led3 - previousMillis_led3 >= interval_led3) {
previousMillis_led3 = currentMillis_led3;
if (ledState_led3 == LOW) {
ledState_led3 = HIGH;
} else {
ledState_led3 = LOW;
}
digitalWrite(led3, ledState_led3);
}
}
解决方案
在这里,您的两种情况在延迟方面非常不同:
由于其中包含多条指令,因此
if(buttonstate==true)
执行时间很长,由于其中没有指令,因此执行速度非常快。delay
else
delay
当buttonstate==True
你按下按钮时(正如 Delta_G 所说,delay()
阻止测试在大多数情况下发生,你应该使用millis()
例如做计时,但是假设你很幸运并且你通过了你的第一个if
语句),所以buttonstate
会翻转到false
.
由于您的指令没有延迟else
,因此电路板将立即返回到您的初始状态if
,不幸的是true
,由于您的速度不够快,无法仅按下此按钮几微秒,因此仍然会出现这种情况。所以buttonstate
会再次翻转,你的代码会落在你if(buttonstate==true)
很长的代码中,让你在if(digitalRead(button)==HIGH)
重新评估之前及时释放按钮。
解决方案(除了@Delta_G 提出的计时问题和@TomServo 提出的硬件问题)是寻求按钮状态的变化。因此,您必须与之前的值进行比较。您可以声明另一个布尔值boolean prev_buttonstate = false;
,并且可以执行以下操作:
bool current_state = digitalRead(button);
if(current_state==HIGH && current_state != prev_buttonstate)
{
buttonstate = !buttonstate; //reverse buttonstate value
}
prev_buttonstate = current_state;
希望能帮助到你!
推荐阅读
- java - 使用 Java Apache HttpClient 4.5.12 时如何解决“连接重置”
- sql - SQL union all 与 group by
- sql - SQL 链接服务器 - 无法执行过程
- algorithm - 素数算法
- java - 我如何从java中的url中获取特定的单词
- laravel - 从关系中只获取一列
- c# - 使用 Fedex ShipService WSDL 的 C# 中的无效包裹计数或无效包裹序列号
- python - 为什么这个简单计算器的第二版可以正常工作,而第一版却不行?是因为代码中运算符的顺序吗?
- php - DataTables SSP - 列问题
- api - Asterisk API - 从浏览器访问的问题