如何解决我的程序卡住并自我重复的问题?

How to solve issue with my program getting stuck and repeating itself?

节目

我有一个 Arduino 项目,控制步进电机进行自动化测试。

程序应等待用户输入,根据输入执行一些代码,并允许用户通过发送新命令来中途更改任务。

一些要执行的任务需要一个函数来保持程序直到下一个刻钟间隔,即 10:00、10:15、10:30 等

问题

有 3 个命令不会导致执行任务,它们大多只是打印一些内容并完成。如果其中一个命令是第一个发送的命令,程序将打印出它应该打印的内容,并且不会接受任何新命令。

此外,当任何其他命令为 运行 时,switch 语句中的任何打印都将打印两次。

我的结论是,出于某种原因,switch 语句在每次发送命令时都会 运行 通过两次,因此双重打印(默认开关将 运行 之前的 运行 命令)和程序暂停(那些特定的功能没有设置以前的 cmd 来记住。以前的 cmd 变量的原因是为了防止用户想要查看他们不必中断他们的测试的菜单。)。 =11=]

我已经尝试更改体系结构,以便循环不处理来自串行端口的字符,并制作了一个单独的函数来保持时间(最初是在循环()中)。

我也试过从循环和 Command() 函数中调用串行处理函数。

密码

void setup() 
{
    Serial.begin(9600);
    AFMS.begin();                   //start motor object
    myStepper1->setSpeed(300);      //set motor speed

    Serial.print("Starting AutoArduino V0.7 ...\n");
    Serial.print("Press H for help\n");
    Serial.print("\n");

    lastTime = -1;  // make sure lastTime is initialized to something that 
                    // is not 0 and not a multiple of 15.

 }

 void TimeKeeper() 
 { 
  while(Serial.available() <= 0){
    now = rtc.now();
    if (now.minute() != lastTime && now.minute() % 15 == 0){

        interval++;
        intervalTotal++;
        lastTime = now.minute();
        return; // this is where you want to exit loop() if you do not want
                // execution beyond this point. 
    }
  }
 }

void loop(){
    while (Serial.available() > 0) Command(Serial.read());
}


void Command(int cmd){ 
  myStepper1->release();
  if(prevCmd!=cmd) interval=0;

    switch (cmd) {                             //Switch stament will execute any code that matchs a received character. Data sent over serial is asynchronous, thus the single charaters.

     case 'B':
     case 'b':
        prevCmd = cmd;
        delay(100);
        Serial.print("Starting backwards flow... \n");
        BackwardFlow();
       break;

     case 'C':
     case 'c':
        prevCmd = cmd;
        delay(100);
        Serial.print("Incrementing... \n");
        delay(10);
        Increment();
       break;

     case 'D':
     case 'd':
        prevCmd = cmd;
        delay(100);
        Serial.print("Decrementing... \n");
        Decrement();
       break;

     case 'H':
     case 'h':
        delay(100);
        Serial.print("\n");
        Serial.print("B: Continuous backward flow\n");
        Serial.print("C: Increment every interval\n");
        Serial.print("D: Decriment every interval\n");
        Serial.print("F: Continuous forward flow\n");
        Serial.print("R: Reverse flow\n");
        Serial.print("X: Cancels current test\n");
        Serial.print("\n");
        return;
       break;

     case 'F':
     case 'f':
        prevCmd = cmd;
        delay(100);
        Serial.print("Starting forward flow... \n");
        ForwardFlow();
       break;

     case 'R':
     case 'r':
        interval =0;
        prevCmd = cmd;
        delay(100);
        Serial.print("Starting Reverse flow simulator... \n");
        ReverseFlowSim();
       break;

     case 'T':
     case 't':
        now = rtc.now();

        Serial.println("Current Date & Time: ");
        Serial.print(now.year(), DEC);
        Serial.print('/');
        Serial.print(now.month(), DEC);
        Serial.print('/');
        Serial.print(now.day(), DEC);
        Serial.print(" (");
        Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
        Serial.print(") ");
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.print(':');
        Serial.print(now.second(), DEC);
        Serial.println();
       break;

     case 'X':
     case 'x':                         
        delay(100);
        Serial.print("Stopping all tests \n");
        prevCmd = empty;
        cmdID = empty;
       break;

     default:
        delay(100);
        //Serial.print("Continuing: " + cmdID);
        Command(prevCmd);
      break;
    }
}

void ForwardFlow(){
  while(Serial.available() <= 0){
    myStepper1->step(512, FORWARD, SINGLE);   //512 steps per revolution
  }
    myStepper1->release();
}

void BackwardFlow(){
  while(Serial.available() <= 0){
    myStepper1->step(512, BACKWARD, SINGLE);   //512 steps per revolution
  }
    myStepper1->release();  
}

void Increment(){
    while(Serial.available() <= 0){
      TimeKeeper();
      for(int i=0; i < 1; i++){
        //if(Serial.available() > 0) Serialhandler();
        myStepper1->step(512, FORWARD, SINGLE);
      }
    }  
}

void Decrement(){
    while(Serial.available() <= 0){
      TimeKeeper();
      for(int i=0; i < 43; i++){
        //if(Serial.available() > 0) SerialHandler();
        myStepper1->step(512, BACKWARD, SINGLE);
      }
    }  
}

我希望程序允许我随意更改命令并允许用户在不停止程序的情况下接收帮助菜单,目前帮助菜单会导致程序停止工作,直到设备重新启动。

如果您只想显示帮助菜单,您可以在帮助字符大小写中打印一个空行后尝试删除 return 命令。对我来说,代码似乎会做与 TimeKeeper 中的 return 相同的事情。

检查串行监视器的行结束设置。我猜你发送的是 CR 或 NL。因此,当您发送一封设置 prevCmd 的信件时,随后的 CR/NL 会打印相同的内容。而一个没有设置 prevCmd 的字母会让你的程序陷入无限循环,因为 Command(prevCmd); 会被无限调用。

如果你期待CR或NL,你最好忽略它们。在将 Serial.read() 发送到 Command(int cmd) 之前评估返回值。

int cmd = Serial.read();
if (cmd != '\n' && cmd != '\r') {
    Command(cmd);
}