首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试使用millis而不是延迟来实现开关状态循环。

尝试使用millis而不是延迟来实现开关状态循环。
EN

Stack Overflow用户
提问于 2022-02-03 21:49:13
回答 2查看 308关注 0票数 0

我正试图为Arduino编写一个代码,这是一个红灯模型。这个想法是,按下按钮将切换到第一个状态(打开和关闭LED)。然后,第二个也是最后一个状态将恢复到第一个状态,等待再次按下按钮。

使用delay()函数,在2 states....it之间需要一个时间间隔非常好地工作

但是我不被允许使用它,所以我尝试使用millis(),这个想法是,一旦按钮被按下,时间就应该开始,当它恢复到第一个状态时停止,再次按下按钮就重新启动。遗憾的是,它不起作用了,每当我按下按钮,什么都不会发生。

有人知道我怎么能修好它吗?以下是代码:

代码语言:javascript
复制
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;
    }
} 
EN

回答 2

Stack Overflow用户

发布于 2022-02-04 08:08:16

这是一个未经检验的建议。它只允许在足够时间过去的情况下进行状态更改。您可能希望在数组if (millis() - start_time > mydelays[state]) {中有不同的时间。

代码语言:javascript
复制
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:
...
}
票数 0
EN

Stack Overflow用户

发布于 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()记录代码运行的位置和变量中的内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70978754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档