我正试图为Arduino编写一个代码,这是一个红灯模型。这个想法是,按下按钮将切换到第一个状态(打开和关闭LED)。然后,第二个也是最后一个状态将恢复到第一个状态,等待再次按下按钮。
使用delay()函数,在2 states....it之间需要一个时间间隔非常好地工作
但是我不被允许使用它,所以我尝试使用millis(),这个想法是,一旦按钮被按下,时间就应该开始,当它恢复到第一个状态时停止,再次按下按钮就重新启动。遗憾的是,它不起作用了,每当我按下按钮,什么都不会发生。
有人知道我怎么能修好它吗?以下是代码:
const long delay2 = 4000;
int but = 2;
int leda = 3;
int ledb = 4;
int ledc = 5;
int ledd = 6;
int lede = 7;
volatile byte state=LOW;
void setup() {
Serial.begin(9600);
for(int p=3; p <= 8; p++) pinMode(p, OUTPUT);
pinMode(but, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(but), changestate, FALLING);
}
void car(){
digitalWrite(leda, HIGH);
digitalWrite(ledb, LOW);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void wait(){
digitalWrite(leda, LOW);
digitalWrite(ledb, HIGH);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void ped(){
digitalWrite(leda, LOW);
digitalWrite(ledb, LOW);
digitalWrite(ledc, HIGH);
digitalWrite(ledd, HIGH);
digitalWrite(lede, LOW);
}
void changestate() {
state=state+1;
if (state > 3){
state=0;
}
}
void loop(){
switch(state){
case 0:
car();
unsigned long start_time = millis();
break;
case 1:
wait();
while (millis() > start_time + delay1);
state=2;
break;
case 2:
ped();
while (millis() > start_time + delay2);
state=0;
break;
default:
break;
}
}
EDIT: The issue has been solved! Here's the code for further reference:
#define delay1 500
#define delay2 4000
int but = 2;
int leda = 3;
int ledb = 4;
int ledc = 5;
int ledd = 6;
int lede = 7;
volatile byte state=LOW;
void setup() {
Serial.begin(9600);
for(int p=3; p <= 8; p++) pinMode(p, OUTPUT);
pinMode(but, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(but), changestate, FALLING);
}
void car(){
digitalWrite(leda, HIGH);
digitalWrite(ledb, LOW);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void wait(){
digitalWrite(leda, LOW);
digitalWrite(ledb, HIGH);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void ped(){
digitalWrite(leda, LOW);
digitalWrite(ledb, LOW);
digitalWrite(ledc, HIGH);
digitalWrite(ledd, HIGH);
digitalWrite(lede, LOW);
}
void changestate() {
state=state+1;
if (state > 3){
state=0;
}
}
unsigned long start_time = millis();
void loop(){
switch(state){
case 0:
car();
break;
case 1:
start_time = millis();
while(millis() < start_time + delay1){
wait();
state=2;
}
break;
case 2:
while(millis() < start_time + delay2){
ped();
}
state=0;
break;
default:
break;
}
} 发布于 2022-02-04 08:08:16
这是一个未经检验的建议。它只允许在足够时间过去的情况下进行状态更改。您可能希望在数组if (millis() - start_time > mydelays[state]) {中有不同的时间。
volatile bool change_allowed = true;
volatile bool statechanged = true;
volatile unsigned long start_time = 0;
void changestate() {
if (millis() - start_time > DELAY) {
change_allowed = true;
}
if (change_allowed) {
start_time = millis();
change_allowed = false;
state=state+1;
statechanged = true;
if (state > 2) {
state=0;
}
}
}
void loop() {
if (statechanged) {
statechanged = false;
switch(state){
case 0:
...
}发布于 2022-02-04 17:48:11
代码中有问题的东西:
unsigned long start_time = millis(); start_time不能是局部变量。在中断命令之后,循环函数将结束。堆栈上的局部变量将被销毁。在新的调用循环再次创建之后,内容是不可预测的。让它global.while (millis() > start_time + delay1);,如果这成为现实,它将暂停49天。您可能希望执行delay()millis() < start_time + delay1;,但这与使用while (millis() < start_time + delay1);相同--不要使用此表单。它在内部计数器溢出前不久产生错误的结果(每49.x天)。使用form (millis() - start_time > delay1计算有效运行时间,如果millis()的结果低于(millis() - start_time > delay1还有,你有脱脂按钮吗?这似乎是学校的锻炼。我不会给你写代码的。只有standart提示--使用Serial.println()记录代码运行的位置和变量中的内容。
https://stackoverflow.com/questions/70978754
复制相似问题