我有一个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);
}
}
}
我希望程序允许我随意更改命令,并允许用户在不停止程序的情况下接收帮助菜单,当前,帮助菜单会导致程序停止工作,直到重新启动设备为止。
答案 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
做同样的事情。