Problem with Beginning and Ending Serial Communication

I have written a sketch that will run a step motor for x number of steps in response to typing the letter A in the serial monitor. If the letter B is typed in the serial monitor, the motor will move x number steps in the opposite direction.

So far this does indeed happen. I type A and the motor moves clockwise to the position. I enter B and the motor runs anticlockwise to the opposite position. The problem is that while the motor is moving, any entries typed into the serial monitor are recognised and trigger new actions. So as to prevent errors, I want to turn off serial communication as the motor is moving (see code below). Thus, if I type A, the motor will move, but entries typed into the serial monitor as the motor turns should be totally ignored and dropped. To put it another way: only allow new commands when the motor is stopped; if the motor is running any command entered into the serial monitor should be ignored.

I am attempting to do this with the code below, but it isn't working. Commands entered when the motor is turning are recognised and implemented as soon as the motor finishes the current step cycle.

Is the fact that the serial monitor is open causing the Arduino to get serial communication even though the code should be turning it off?

{
Serial.begin(9600);
while (!Serial)
	{
	;//wait for serial port to connect
	}
LastMotorState = 1;
}


void loop()
{
	if(Serial.available())
	{
	    TriggerByte = Serial.read();
	}

	if(TriggerByte == 65 //ASCI "A"
	   &&
	   LastMotorState == 1)
	 {
	    Serial.end();
	    stepper.runToNewPosition(-800);
	    LastMotorState = 2;
	    Serial.begin(9600);
	}

	if(TriggerByte == 66 //ASCI "B"
	   &&
	   LastMotorState == 2)
	 {
	    Serial.end();
	    stepper.runToNewPosition(800);
	    LastMotorState = 1;
	    Serial.begin(9600);
	}
}

Calling Serial.begin() again is NOT how to flush the incoming serial buffer.

Simply read, and discard any data in the buffer as soon as the motor stops moving.

Although, frankly, this is not the best approach. I can't imagine why you don't want to buffer commands for the motor.

PaulS:
I can't imagine why you don't want to buffer commands for the motor.

Paul, thanks for the reply. The motor will rotate to point A, at which point other tasks have to be completed. When the letter 'B' is entered, the motor needs to rotate to point B. The problem is that if I enter 'A', (the motor starts moving) and then accidentally enter 'B' before the motor stops moving, the motor will rotate to point A and then immediately rotate to point B. Thus I need some way to prevent an accidental command from triggering (unwanted) movement.

Instead of another Serial.begin call a function to clear buffered serial input…

void loop()
{
	if(Serial.available())
	{
    TriggerByte = Serial.read();
  }
  
	if(TriggerByte == 65 //ASCI "A"
  &&
  LastMotorState == 1)
  {
    Serial.end();
    stepper.runToNewPosition(-800);
    LastMotorState = 2);
    flushSerial();
  }
  
	if(TriggerByte == 66 //ASCI "B"
  &&
  LastMotorState == 2)
  {
    Serial.end();
    stepper.runToNewPosition(800);
    LastMotorState = 1);
    flushSerial();
  }
}

void flushSerial(){
  while (Serial.available){
    Serial.read();
  }
}

I have tried putting a Serial.read(); after the stepper.runToNewPosition lines but this seems only to work “once” … for instance, if I type ‘B’ one time, it is read from the buffer and ignored, but if I type ‘B’ two or more times, the second ‘B’ is read from the buffer causing the motor to immediately rotate to point B after it reaches point A.

I have also tried the following code, but this also only seems to work “once”

	if(TriggerByte == 65 //ASCI "A"
	   &&
	   LastMotorState == 1)
	 {
	    stepper.runToNewPosition(-800);
	    LastMotorState = 2;
	    CurrentMotorPosition = stepper.currentPosition();
	    if(CurrentMotorPosition == -800)
	      Serial.read();
	}

	if(TriggerByte == 66 //ASCI "B"
	   &&
	   LastMotorState == 2)
	 {
	    stepper.runToNewPosition(800);
	    LastMotorState = 1;
	    CurrentMotorPosition = stepper.currentPosition();
	    if(CurrentMotorPosition == 800)
	      Serial.read();
	}

The key seems to be preventing serial communication while the motor is rotating. Does anyone know how to achieve this?

Riva, thanks, but if by flushSerial() you mean Serial.flush() that won’t work. According to the official Arduino page, this "Waits for the transmission of outgoing serial data to complete. "

You don't need to prevent serial communication. The solution is much simpler.

You just need a variable (let's call it motorMoving) which goes by the rather grand name of a "state variable".

Set motorMoving to true when the motor starts moving and ignore any serial input until your software sets it back to false at a time of your convenience. If necessary you can read and discard all stuff in the Serial buffer before setting motorMoving back to false.

...R

Arduino-x:
I have tried putting a Serial.read(); after the stepper.runToNewPosition lines but this seems only to work “once” … for instance, if I type ‘B’ one time, it is read from the buffer and ignored, but if I type ‘B’ two or more times, the second ‘B’ is read from the buffer causing the motor to immediately rotate to point B after it reaches point A.

Riva, thanks, but if by flushSerial() you mean Serial.flush() that won’t work. According to the official Arduino page, this "Waits for the transmission of outgoing serial data to complete. "

If you look at the code posted with my first reply (It is not a complete program as you did not supply the full program in your initial post) you will see what I mean.

Riva, my mind must have been in standby mode :sleeping: ... I didn't scroll down in the code you suggested, so didn't see the function you were calling. Anyway, it does the trick. Thanks a bundle!