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

时间:2019-09-09 17:34:02

标签: arduino arduino-uno arduino-ide

程序

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

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

要执行的某些任务需要将程序保持到下一个四分之一小时间隔(即10:00、10:15、10:30等)的功能。

问题

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

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

我的结论是,由于某种原因,每次发送命令时switch语句都会运行两次,因此两次打印(默认开关将运行先前运行的命令)并且程序暂停(这些特定功能未设置)以前的cmd要记住。使用上一个cmd变量的原因是,如果用户希望看到他们不必中断测试的菜单。

我尝试过更改体系结构,以使循环不处理来自串行端口的字符,并为保持时间做了一个单独的功能(最初是在loop()中)。

我还尝试过从循环和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);
      }
    }  
}

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

2 个答案:

答案 0 :(得分:1)

检查串行监视器的行结束设置。我的猜测是您要发送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);
}

答案 1 :(得分:0)

如果只想显示帮助菜单,则可以在打印辅助字符的情况下打印空白行后尝试删除return命令。在我看来,该代码将与TimeKeeper中的return做同样的事情。