带有 set/reset 个按钮的 Arduino 计时器
Arduino timer with set/reset buttons
我正在为我的马建造一个自动干草喂食器,类似这样但只有两层楼
每隔 24 小时,中间的盘子应该掉下来,让干草掉下来供马吃,界面应该非常简单,3 个按钮,一个用于启动计时器,一个用于停止计时器并部署干草和一个是将伺服器重置在他的初始位置以再次锁定盘子,我的计时器有一些问题,当我按下绿色按钮时它开始但在它完成计数后它停止并且我必须再次按下绿色按钮,除非我按下红色按钮重置它,否则它应该无休止地运行
const int greenB = 2;
const int redB = 3;
int inAction = 0;
int greenState = 0;
int redState = 0;
void setup() {
Serial.begin(9600);
pinMode(greenB, INPUT);
pinMode(redB, INPUT);
}
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
while(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
goto stopTimer;
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
stopTimer: inAction = 0;
}
}
}
因为你使用了goto,所以出了问题。一旦代码到达 for 循环的末尾,它将到达标记为 stopTimer: 的行并将 inAction 设置为 0。这将停止一切,直到您再次按下绿色按钮。
在 C++ 中不需要使用 goto。如果你发现你想使用 goto 那么你很可能做错了。试试这个:
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
while(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
inAction = 0;
break; // Ends the for loop right here:
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
}
}
}
当你按下红色按钮时,break语句结束for循环。它就在那里出口。这也是循环中的最后一件事,因此循环然后退出。下一次通过循环 inAction 设置为 0,这将停止它。但除此之外,它只会让你的 10 秒倒计时不断 运行。
您还可以做很多事情来改进此代码。用延迟函数编写它意味着您可能必须按住按钮最多一秒钟,而该行在它注册您按下它之前完成。但这可能是另一天的教训。这至少会向您展示 goto 有多糟糕以及为什么您会出现不希望的行为。
一个很大的改进是让循环函数成为您的循环,并实际利用您的状态变量 inAction。看看你是否理解为什么这样更好:(如果你有更多的代码想要 运行 而 inAction 为 0 怎么办?)
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
}
if(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
inAction = 0;
break; // Ends the for loop right here:
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
}
}
}
我正在为我的马建造一个自动干草喂食器,类似这样但只有两层楼
每隔 24 小时,中间的盘子应该掉下来,让干草掉下来供马吃,界面应该非常简单,3 个按钮,一个用于启动计时器,一个用于停止计时器并部署干草和一个是将伺服器重置在他的初始位置以再次锁定盘子,我的计时器有一些问题,当我按下绿色按钮时它开始但在它完成计数后它停止并且我必须再次按下绿色按钮,除非我按下红色按钮重置它,否则它应该无休止地运行
const int greenB = 2;
const int redB = 3;
int inAction = 0;
int greenState = 0;
int redState = 0;
void setup() {
Serial.begin(9600);
pinMode(greenB, INPUT);
pinMode(redB, INPUT);
}
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
while(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
goto stopTimer;
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
stopTimer: inAction = 0;
}
}
}
因为你使用了goto,所以出了问题。一旦代码到达 for 循环的末尾,它将到达标记为 stopTimer: 的行并将 inAction 设置为 0。这将停止一切,直到您再次按下绿色按钮。
在 C++ 中不需要使用 goto。如果你发现你想使用 goto 那么你很可能做错了。试试这个:
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
while(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
inAction = 0;
break; // Ends the for loop right here:
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
}
}
}
当你按下红色按钮时,break语句结束for循环。它就在那里出口。这也是循环中的最后一件事,因此循环然后退出。下一次通过循环 inAction 设置为 0,这将停止它。但除此之外,它只会让你的 10 秒倒计时不断 运行。
您还可以做很多事情来改进此代码。用延迟函数编写它意味着您可能必须按住按钮最多一秒钟,而该行在它注册您按下它之前完成。但这可能是另一天的教训。这至少会向您展示 goto 有多糟糕以及为什么您会出现不希望的行为。
一个很大的改进是让循环函数成为您的循环,并实际利用您的状态变量 inAction。看看你是否理解为什么这样更好:(如果你有更多的代码想要 运行 而 inAction 为 0 怎么办?)
void loop() {
greenState = digitalRead(greenB);
redState = digitalRead(redB);
if(greenState == HIGH){
inAction = 1;
}
if(inAction == 1){
for(int i = 0; i<10;i++){
if(redState == HIGH){
Serial.println("timer stopped");
inAction = 0;
break; // Ends the for loop right here:
}
if(i == 9){
Serial.println("Cycle completed");
}
Serial.println("10 seconds timer");
delay(1000);
}
}
}
}