Failure to get two consecutive user inputs from the serial monitor

Dear all,
I started from a working example that I wrote a few years ago, where a single character input in the serial monitor was used to choose the direction and the amount of stepper rotation. This was successfully managed inside the loop().

Now I need two parameters:

  1. the single character that determines the direction and the amount of stepper rotation
  2. the number of repetitions of that very same rotation. e.g., 5 times rotation "Q".

To that purpose, I tried to get the two values in the setup() function.

Another need that arises is checking within the loop() whether a rotation is completed, to reset the starting point and to repeat the rotation. I thought that checking for distanceToGo() == 0 would suffice.

Now I'm stupidly stuck with two problems:

  • A) my very first Serial.println is not shown
  • B) while the desired number of rotations is correctly acquired, the String incomingByte = Serial.readString(); doesn't wait for any input on my part, and the setup ends without waiting for my input. This is the serial monitor output that I'm getting after my initial input (7 + enter):

You required 7 rotations.

Which kind of rotation is required ?
Available commands:
====> 360° Rotation
o = 360° clockwise rotation
O = 360° counter-clockwise rotation
====> Rotation by small increments
k = rotate 4° clockwise
K = rotate 4° counter-clockwise
f = rotate 5° clockwise
F = rotate 5° counter-clockwise
t = rotate 10° clockwise
T = rotate 10° counter-clockwise
w = rotate 20° clockwise
W = rotate 20° counter-clockwise
q = rotate 40° clockwise
Q = rotate 40° counter-clockwise

Received

Starting rotation number 1 of 7
Starting rotation number 2 of 7
Starting rotation number 3 of 7
Starting rotation number 4 of 7
Starting rotation number 5 of 7
Starting rotation number 6 of 7
Starting rotation number 7 of 7

The full code is attached here: thanks for your help!

/*
 
Stepper-based microscope Z-stage

Circuit and comments: 
See http://www.cesarebrizio.it/Arduino/Z-Stage.html
Circuit is as illustrated here:
https://www.tdegypt.com/wp-content/uploads/2017/08/stepper-motor-wiring.png
the only exception being that the sketch uses digital outputs 4 - 5 - 6 - 7
while the Fritzing diagram uses digital outputs 8 - 9 - 10 - 11
 
*/

/*-----( Import needed libraries )-----*/
#include <AccelStepper.h>
#include <Keyboard.h>  // Needed only if keyboard stroke is to be sent (REQUIRES Arduino UNO R4 Minima)

/*-----( Declare Constants and Pin Numbers )-----*/
/* NEVER PUT ; AFTER A #define statement!!!! */
// motor pins
#define motorPin1 4           // Blue   - 28BYJ-48 pin 1
#define motorPin2 5           // Pink   - 28BYJ-48 pin 2
#define motorPin3 6           // Yellow - 28BYJ-48 pin 3
#define motorPin4 7           // Orange - 28BYJ-48 pin 4 \
                              // Red    - 28BYJ-48 pin 5 (VCC) \
                              // Blue   - 28BYJ-48 pin GND
#define STEPS_PER_TURN 2048   // number of steps in 360°
#define STEPS_PER_FOUR 22     // number of steps in 4°
#define STEPS_PER_FIVE 28     // number of steps in 5°
#define STEPS_PER_TEN 57      // number of steps in 10°
#define STEPS_PER_TWENTY 114  // number of steps in 20°
#define STEPS_PER_FORTY 228   // number of steps in 40°

int motorSpeed = 500;   // High speeds (800 and above) may cause erratic behavior in 28BYJ-48
int motorAccel = 400;   // As above: better avoiding extreme accelerations
int myPos = 0;          // will be used to define a starting point for 360° rotations
int LeftTurnUp = 0;     // Couple of flags to determine rotation direction
int RightTurnDown = 0;  // Couple of flags to determine rotation direction
int Continuous = 2;     // used below to discriminate single rotation commands
// Continuous will be set to 1 or 0 only when a valid command character will be received
//int incomingByte = 0;  // for incoming serial data
int STEPS_TO_DO = 0;   // to allocate the number of steps needed to perform the required rotation

int RotationsRequired = 0;   // How many rotations of the desired type are required?
int RotationsDone = 0;       // How many rotations of the desired type were completed?
int RotationsRemaining = 0;  // How many rotations remain to do?

/*-----( Objects for stepper control )-----*/
// Set up the stepper as 4 wire bipolar on pin 4,5,6,7
// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48
AccelStepper stepper(4, motorPin1, motorPin3, motorPin2, motorPin4);


void setup() {
  Serial.begin(9600);
  stepper.setMinPulseWidth(20);  // Advisable setting to avoid that pulses from Arduino are too quick to be decoded
  stepper.setMaxSpeed(motorSpeed);
  stepper.setSpeed(motorSpeed);
  stepper.setAcceleration(motorAccel);
  // the following two lines reset "step zero" to the current position
  stepper.setCurrentPosition(stepper.currentPosition());
  stepper.runToPosition();
  //Keyboard.begin();  // required to initialize the communication with the keyboard

// ================================================================
// INITIALLY, the user is asked for A NUMBER OF REQUIRED ROTATIONS 
// AND THE KIND OF ROTATIONS REQUIRED
// ================================================================

  Serial.println("===============================");
  Serial.println("How many rotations are desired?");

  while (Serial.available() == 0) {
  }

  RotationsRequired = Serial.parseInt();
  RotationsDone = 0;                       // For now, no rotations has been completed
  RotationsRemaining = RotationsRequired;  // For now, no rotations has been completed

  Serial.print("You required ");
  Serial.print(RotationsRequired);
  Serial.println(" rotations.");
  Serial.println("   ");
  Serial.println("Which kind of rotation is required ?");
  Serial.println("Available commands:");
  Serial.println("====> 360° Rotation");
  Serial.println("o = 360° clockwise rotation");
  Serial.println("O = 360° counter-clockwise rotation");
  Serial.println("====> Rotation by small increments");
  Serial.println("k = rotate 4° clockwise");
  Serial.println("K = rotate 4° counter-clockwise");
  Serial.println("f = rotate 5° clockwise");
  Serial.println("F = rotate 5° counter-clockwise");
  Serial.println("t = rotate 10° clockwise");
  Serial.println("T = rotate 10° counter-clockwise");
  Serial.println("w = rotate 20° clockwise");
  Serial.println("W = rotate 20° counter-clockwise");
  Serial.println("q = rotate 40° clockwise");
  Serial.println("Q = rotate 40° counter-clockwise");


  while (Serial.available() == 0) {
  }

  String incomingByte = Serial.readString();


    Serial.print("Received ");
    Serial.println(incomingByte);


    if (incomingByte == "o") {
      Serial.println("received «o» - activating single clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_TURN;
    }

    if (incomingByte == "O") {
      Serial.println("received «O» - activating single counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_TURN;
    }

    if (incomingByte == "k") {
      Serial.println("received «k» - activating 4° clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_FOUR;
    }

    if (incomingByte == "K") {
      Serial.println("received «K» - activating 4° counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_FOUR;
    }

    if (incomingByte == "f") {
      Serial.println("received «f» - activating 5° clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_FIVE;
    }

    if (incomingByte == "F") {
      Serial.println("received «F» - activating 5° counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_FIVE;
    }

    if (incomingByte == "t") {
      Serial.println("received «t» - activating 10° clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_TEN;
    }

    if (incomingByte == "T") {
      Serial.println("received «T» - activating 10° counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_TEN;
    }

    if (incomingByte == "w") {
      Serial.println("received «w» - activating 20° clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_TWENTY;
    }

    if (incomingByte == "W") {
      Serial.println("received «W» - activating 20° counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_TWENTY;
    }

    if (incomingByte == "q") {
      Serial.println("received «q» - activating 40° clockwise rotation");
      // The following couple of flags determines rotation direction
      LeftTurnUp = 0;
      RightTurnDown = 1;
      STEPS_TO_DO = STEPS_PER_FORTY;
    }

    if (incomingByte == "Q") {
      Serial.println("received «Q» - activating 40° counter-clockwise rotation");
      // The following couple of flags determines rotation direction
      RightTurnDown = 0;
      LeftTurnUp = 1;
      STEPS_TO_DO = STEPS_PER_FORTY;
    }

    // The two lines that follow allow to send commands in any sequence:
    // before execution, a quick stop is performed
    stepper.stop();                                         // Stop as fast as possible: sets new target
    stepper.runToPosition();                                // Now stopped after quickstop
    stepper.setCurrentPosition(stepper.currentPosition());  // Set step 0 "here"
    stepper.setSpeed(motorSpeed);                           // Previous commands have reset the speed

    Serial.print("Starting rotation number 1 of ");
    Serial.println(RotationsRequired); 

    // I store my current position as starting point of the rotation
    myPos = stepper.currentPosition();

    if (LeftTurnUp == 1)  //left turn
    {
      stepper.moveTo(myPos + STEPS_TO_DO);  // number of  steps in 5, 10, 20 or 360°
    }

    if (RightTurnDown == 1)  //right turn
    {
      stepper.moveTo(myPos - STEPS_TO_DO);  // number of  steps in 5, 10, 20 or 360°
    }
  

}

void loop() {
  stepper.run();

  // ==================================================
  // Let's check whether the stepper is still running
  // ==================================================
  if (stepper.distanceToGo() == 0) {
    //Serial.println("stepper.distanceToGo() = 0");
    // the rotation was completed
    // Send F1 to the keyboard
    //Keyboard.press(KEY_F1);
    //delay(100);
    //Keyboard.releaseAll();
    // Increase the count of rotations done
    RotationsDone = RotationsDone + 1;
    // Check how many rotations remain to do
    RotationsRemaining = RotationsRequired - RotationsDone;
    if (RotationsRemaining > 0) {
        Serial.print("Starting rotation number ");
        Serial.print(RotationsDone + 1);
        Serial.print(" of ");
        Serial.println(RotationsRequired); 
      // reset current position
      myPos = stepper.currentPosition();
      // start a new rotation of the same kind as the last one
      if (LeftTurnUp == 1)  //left turn
      {
        stepper.moveTo(myPos + STEPS_TO_DO);  // number of  steps in 5, 10, 20 or 360°
      }
      if (RightTurnDown == 1)  //right turn
      {
        stepper.moveTo(myPos - STEPS_TO_DO);  // number of  steps in 5, 10, 20 or 360°
      }
    }
  }
}

What have you got Line Ending set to in the Serial monitor ?

Anything except No Line Ending will cause problems

try removing any end of line characters after parseInt() which terminates when it reads a non-digit character (which is left in the serial buffer)

RotationsRequired = Serial.parseInt();
while(Serial.available()) Serial.read();

Many thanks, @UKHeliBob - I'll check that setting.

Thanks, @horace. In a few minutes I'll try that trick.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.