Reading serial, Problem with s and S

Developing a digital control for a rotating table a simple, stupid problem is present.
The input should be s5, or S5 for the table make 5 turns per revolution.
Also a72 or A72 is used, for a stepping angle of 72 degrees.
The capital letter works but not the minor(?) letter. What do I miss. A shame to ask but.....
Look at setup() that's reading input from serial monitor.

The code:

#include<arduino.h>

//I2C for LCD
#include <AccelStepper.h>
//#include <Wire.h>
//#include <hd44780.h>
//#include <hd44780ioClass/hd44780_I2Cexp.h>

//hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

AccelStepper myStepper (1, 6, 7);

// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2

enum mode {Sides, Angle };
mode Mode; //Angle or Step mode
int nrOfFaces = 4;//Will be prompted in Setup
float stepAngle = 90.0;// will be set when angles selected
unsigned long nrOfStepsPerRev = 200L * 16L * 40L; // microstep 32
unsigned long currentStep;
unsigned long anglePos;

enum cmd {increase, decrease, Go, ChgMode, GoStep, nobutton};

void setup() {
  char inChar;
  Serial.begin(115200);
  Serial.println("Rotation ");

  pinMode(13, OUTPUT); digitalWrite(13, LOW);// Make board LED go off

  myStepper.setMaxSpeed(4000);
  myStepper.setAcceleration(30000);

#define digitalIncreaseButton 2
  pinMode (digitalIncreaseButton, INPUT_PULLUP);

#define cuttingSpeed 100 // when cutting during rotation
#define movingSpeed 500 //when moving without cutting

  /*
         int status;
      status = mylcd.begin(LCD_COLS, LCD_ROWS);
      if (status) // non zero status means it was unsuccesful
      {
        status = -status; // convert negative status value to positive number

        // begin() failed so blink error code using the onboard LED if possible
        hd44780::fatalError(status); // does not return
      }
      mylcd.clear();

      mylcd.print("230201a Rotating. S Steps ot A Angle ");
  */
  Serial.println("230202a Rotating. S: Steps, A:Angle");

  while (!Serial.available()) {}; //Wait for Serial input
  inChar = Serial.read();//Read type of mode, Sides or Angle
  if (inChar == 's')inChar == 'S';//  DOESN*T work
  if (inChar == 'S')//ORIGINAL S works
  {
    Serial.println("Step mode selected");
    Mode = Sides;
    while (!Serial.available()) {}; //Wait for Serial input
    nrOfFaces = Serial.parseInt();
    Serial.print("Sides/Faces = "); Serial.println(nrOfFaces);
  }


  if (inChar == 'a')inChar == 'A';
  if (inChar == 'A')
  {
    Serial.println("Angle mode selected");
    Mode = Angle;
    while (!Serial.available()) {}; //Wait for Serial input
    stepAngle = Serial.parseFloat();
    Serial.print("Angle step = "); Serial.println(stepAngle);
  }
  myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
  anglePos = 0;
  currentStep = 0;
  Serial.println("S for stepping, both step/faces and angle");
  //  delay(5000);
}

enum cmd readButtons(void)
{
  char cmd = 'q';

  if ((digitalIncreaseButton) == 0)
  {
    Serial.println("Button step received");
    return (GoStep);
  }//     increase);
  if (Serial.available() > 0)
  {
    cmd = Serial.read();
  }

  if (cmd == 's' )
  {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (GoStep);
  }
  if (cmd == 'S' ) {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (GoStep);
  }

  if (cmd == 'c' )
  {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (ChgMode);
  }
  if (cmd == 'C' ) {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (ChgMode);
  }

  return (nobutton);
}

boolean guardCheck(void)
{
  /* commented out until hardware is designed
    if (!digitalRead(guard1) && !digitalRead(guard2))
    return (true);//Unlocked, clear to go
    else
    return false;//Locked, don't go
  */
  return (true);
}

void loop()
{
  unsigned long lastMillis;
  //  unsigned long anglePos;
  enum cmd lcmd;
  //  enum mode lmode;
  float tmpfloat;

  lcmd = readButtons();// Read button inputs/ Serial, if any    + - Go Chg mode

  if ( millis() - lastMillis > 200 )
  {
    lastMillis = millis();
    if ( Mode == Sides )  //number of surnrOfFaces
    {
      switch (lcmd)
      {
        case increase:
          {
            nrOfFaces++;
            break;
          }
        case decrease:
          {
            nrOfFaces--;
            if (nrOfFaces < 2)
            {
              nrOfFaces = 1; //1 rotate one turn
              //              myStepper.setMaxSpeed(cuttingSpeed);
            }
            else
              //              myStepper.setMaxSpeed(movingSpeed);
              break;
          }
        case ChgMode:
          {
            myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            anglePos = 0;
            currentStep = 0;

            setup();// Ask for new mode
            Mode = Angle;
            /*
                        Serial.print("Mode, anglePos, currentStep = ");
                        if (Mode = Angle ) Serial.print("Angle");
                        if (Mode = Sides ) Serial.print("Sides");
                        Serial.print(anglePos);
                        Serial.println (currentStep);
            */
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON
            anglePos += nrOfStepsPerRev / nrOfFaces;
            //            myStepper.runToNewPosition();//Blocking until done
            break;
          }

        case GoStep:
          {
            Serial.print("GoStep S received. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("Stepping to step "); Serial.println(currentStep + 1);
            anglePos = (nrOfStepsPerRev * ++currentStep) / nrOfFaces;
            currentStep %= nrOfFaces;
            Serial.print("anglePos = "); Serial.println( anglePos);
            tmpfloat = 360 * float(currentStep) / float(nrOfFaces);
            Serial.print("Angle = "); Serial.println( tmpfloat);

            lastMillis = millis();
            myStepper.runToNewPosition(anglePos);//Blocking until done

            Serial.print("Runtime "); Serial.println( millis() - lastMillis);
            Serial.println("Ready."); Serial.println();

            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
              myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            break;
          }
        default:
          break;
      }//end of switch
    }//end of "if (lmode == Sides)"
    else if ( Mode == Angle )  // Angle per step
    {
      switch (lcmd)
      {
        case increase:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / nrOfFaces;
            break;
          }
        case decrease:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / nrOfFaces;
            if (nrOfFaces < 1) nrOfFaces = 1; //1 rotate one turn
            break;
          }
        case ChgMode:
          {
            myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            anglePos = 0;
            currentStep = 0;

            setup();// Ask for new mode
            Mode = Sides;

            /*
                        Serial.print("Mode, anglePos, currentStep = ");
                        if (Mode = Angle ) Serial.print("Angle");
                        if (Mode = Sides ) Serial.print("Sides");
                        Serial.print(anglePos);
                        Serial.println (currentStep);
            */
            break;
          }
        case GoStep:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON
            Serial.println("GoStep A eceived. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("anglePos1 = "); Serial.println( anglePos);
            anglePos += (nrOfStepsPerRev * stepAngle) / 360L;
            Serial.print("anglePos2 = "); Serial.println( anglePos);
            Serial.print ("Angle "); Serial.println((anglePos * 360 ) / nrOfStepsPerRev) + 0.5;
            lastMillis = millis();
            myStepper.runToNewPosition(anglePos);//Blocking until done

            if (anglePos > nrOfStepsPerRev)
            {
              anglePos -= nrOfStepsPerRev;
              myStepper.setCurrentPosition(anglePos);
            }
            Serial.print("Runtime "); Serial.println( millis() - lastMillis);
            Serial.println("Ready."); Serial.println();

            //            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
            //myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            //            break;
          }
        default:
          break;
      }
    }
  }
  //  if (guardCheck())
  //  {
  //    Serial.print("!");
  //myStepper.run();
  //  }
}// End of loop
/*
  moveTo KEYWORD2
  move  KEYWORD2
  run KEYWORD2
  runSpeed  KEYWORD2
  setMaxSpeed KEYWORD2
  setAcceleration KEYWORD2
  setSpeed  KEYWORD2
  speed KEYWORD2
  distanceToGo  KEYWORD2
  targetPosition  KEYWORD2z
  currentPosition KEYWORD2
  setCurrentPosition  KEYWORD2
  runToPosition KEYWORD2
  runSpeedToPosition  KEYWORD2
  runToNewPosition  KEYWORD2
  stop  KEYWORD2
  disableOutputs  KEYWORD2
  enableOutputs KEYWORD2
  setMinPulseWidth  KEYWORD2
  setEnablePin  KEYWORD2
  setPinsInverted KEYWORD2
  maxSpeed  KEYWORD2

  enum flag {const1, const2, ..., constN};
  By default, const1 is 0, const2 is 1 and so on. You can change default values of enum elements during declaration (if necessary).

  // Changing default values of enum constants
  enum suit {
  club = 0,
  diamonds = 10,
  hearts = 20,
  spades = 3,
  };
*/

One comment. Code tags. Not being rude, by the way. If the code is tagged, it's embedded such that a single click allows export to the IDE. Much simpler, and foolproof.

Single = not == for assignment.

OP tried :smiley: It went wrong because of the below

  1. The backtick
  2. [code] should, if not mistaken, be on a new line

Fully okey. Usually I use mark, copy and paste into code tags. This time I tried to use the automated function in the IDE, and fell. Not my day....

See reply #5.....

Haha. It surely doesn't work... Copy and paste and home blind .... Never thought I would do a mistake like that. Thanks for Your time!

For that style of parsing, you might look into switch-case structures.

Alternately, cast all your command characters to upper or lower case,mand work with a single case.

To use complete words, break the words into separate parameter fields, use the above, and look for substrings with strcmp().

You can make quite a clever text parser with those.

Using toupper() on the incoming characters would be much better...

Thanks for Your reply... But... Maybe too late here, 6 AM...

I don't follow You

I try to do that upon reading from serial.

Sorry, I don't get it. Strings and substrings was easy in Various Basic....

I'm lost.

Summing things up. I got the code doing what I want.
Code:

#include<arduino.h>

//I2C for LCD
#include <AccelStepper.h>
//#include <Wire.h>
//#include <hd44780.h>
//#include <hd44780ioClass/hd44780_I2Cexp.h>

//hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

AccelStepper myStepper (1, 6, 7);

// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2

enum mode {Sides, Angle };
mode Mode; //Angle or Step mode
int nrOfFaces = 4;//Will be prompted in Setup
float stepAngle = 90.0;// will be set when angles selected
unsigned long nrOfStepsPerRev = 200L * 16L * 40L; // microstep 32
unsigned long currentStep;
unsigned long anglePos;
float accFloatAngle;//for display only

enum cmd {increase, decrease, Go, ChgMode, GoStep, nobutton};

void setup() {
  char inChar;
  Serial.begin(115200);
  Serial.println("Rotation ");

  pinMode(13, OUTPUT); digitalWrite(13, LOW);// Make board LED go off

  myStepper.setMaxSpeed(4000);
  myStepper.setAcceleration(30000);

#define digitalIncreaseButton 2
  pinMode (digitalIncreaseButton, INPUT_PULLUP);

#define cuttingSpeed 100 // when cutting during rotation
#define movingSpeed 500 //when moving without cutting

  /*
         int status;
      status = mylcd.begin(LCD_COLS, LCD_ROWS);
      if (status) // non zero status means it was unsuccesful
      {
        status = -status; // convert negative status value to positive number

        // begin() failed so blink error code using the onboard LED if possible
        hd44780::fatalError(status); // does not return
      }
      mylcd.clear();

      mylcd.print("230201a Rotating. S Steps ot A Angle ");
  */
  Serial.println("230202a Rotating. S: Steps, A:Angle");

  while (!Serial.available()) {}; //Wait for Serial input
  inChar = Serial.read();//Read type of mode, Sides or Angle
  if (inChar == 's')inChar = 'S';//  DOESN*T work
  if (inChar == 'S')//ORIGINAL S works
  {
    Serial.println("Step mode selected");
    Mode = Sides;
    while (!Serial.available()) {}; //Wait for Serial input
    nrOfFaces = Serial.parseInt();
    Serial.print("Sides/Faces = "); Serial.println(nrOfFaces);
  }


  if (inChar == 'a')inChar = 'A';
  if (inChar == 'A')
  {
    Serial.println("Angle mode selected");
    Mode = Angle;
    while (!Serial.available()) {}; //Wait for Serial input
    stepAngle = Serial.parseFloat();
    Serial.print("Angle step = "); Serial.println(stepAngle);
  }
  myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
  anglePos = 0;
  currentStep = 0;
  Serial.println("S for stepping, both step/faces and angle");
  //  delay(5000);
}

enum cmd readButtons(void)
{
  char cmd = 'q';

  if ((digitalIncreaseButton) == 0)
  {
    Serial.println("Button step received");
    return (GoStep);
  }//     increase);
  if (Serial.available() > 0)
  {
    cmd = Serial.read();
  }

  if (cmd == 's' )
  {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (GoStep);
  }
  if (cmd == 'S' ) {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (GoStep);
  }

  if (cmd == 'c' )
  {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (ChgMode);
  }
  if (cmd == 'C' ) {
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (ChgMode);
  }

  return (nobutton);
}

boolean guardCheck(void)
{
  /* commented out until hardware is designed
    if (!digitalRead(guard1) && !digitalRead(guard2))
    return (true);//Unlocked, clear to go
    else
    return false;//Locked, don't go
  */
  return (true);
}

void loop()
{
  unsigned long lastMillis;
  //  unsigned long anglePos;
  enum cmd lcmd;
  //  enum mode lmode;
  //  float accFloatAngle;//for display only
  float tmpfloat;

  lcmd = readButtons();// Read button inputs/ Serial, if any    + - Go Chg mode

  if ( millis() - lastMillis > 200 )
  {
    lastMillis = millis();
    if ( Mode == Sides )  //number of surnrOfFaces
    {
      switch (lcmd)
      {
        case increase:
          {
            nrOfFaces++;
            break;
          }
        case decrease:
          {
            nrOfFaces--;
            if (nrOfFaces < 2)
            {
              nrOfFaces = 1; //1 rotate one turn
              //              myStepper.setMaxSpeed(cuttingSpeed);
            }
            else
              //              myStepper.setMaxSpeed(movingSpeed);
              break;
          }
        case ChgMode:
          {
            myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            anglePos = 0;
            currentStep = 0;
            accFloatAngle = 0;

            setup();// Ask for new mode
            //            Mode = Angle;
            /*
                        Serial.print("Mode, anglePos, currentStep = ");
                        if (Mode = Angle ) Serial.print("Angle");
                        if (Mode = Sides ) Serial.print("Sides");
                        Serial.print(anglePos);
                        Serial.println (currentStep);
            */
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON
            anglePos += nrOfStepsPerRev / nrOfFaces;
            //            myStepper.runToNewPosition();//Blocking until done
            break;
          }

        case GoStep:
          {
            Serial.print("GoStep S received. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("Stepping to step "); Serial.println(currentStep + 1);
            anglePos = (nrOfStepsPerRev * ++currentStep) / nrOfFaces;
            currentStep %= nrOfFaces;
            Serial.print("anglePos = "); Serial.println( anglePos);
            tmpfloat = 360 * float(currentStep) / float(nrOfFaces);
            Serial.print("Angle = "); Serial.println( tmpfloat);

            lastMillis = millis();
            myStepper.runToNewPosition(anglePos);//Blocking until done

            Serial.print("Runtime "); Serial.println( millis() - lastMillis);
            Serial.println("Ready."); Serial.println();

            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
              myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            break;
          }
        default:
          break;
      }//end of switch
    }//end of "if (lmode == Sides)"
    else if ( Mode == Angle )  // Angle per step
    {
      switch (lcmd)
      {
        case increase:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / nrOfFaces;
            break;
          }
        case decrease:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / nrOfFaces;
            if (nrOfFaces < 1) nrOfFaces = 1; //1 rotate one turn
            break;
          }
        case ChgMode:
          {
            myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            anglePos = 0;
            currentStep = 0;
            accFloatAngle = 0;

            setup();// Ask for new mode
            //            Mode = Sides;

            /*
                        Serial.print("Mode, anglePos, currentStep = ");
                        if (Mode = Angle ) Serial.print("Angle");
                        if (Mode = Sides ) Serial.print("Sides");
                        Serial.print(anglePos);
                        Serial.println (currentStep);
            */
            break;
          }
        case GoStep:
          {
            Serial.println("GoStep A eceived. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("anglePos1 = "); Serial.println( anglePos);
            Serial.print("accFloatAgle1 = "); Serial.println( accFloatAngle );
            accFloatAngle += stepAngle;
            Serial.print ("accFloatAngle "); Serial.println(accFloatAngle);
            //            if (accFloatAngle > 360.0) accFloatAngle -= 360.0;
            anglePos = accFloatAngle * nrOfStepsPerRev / 360.0 ; // in steps

            lastMillis = millis();
            myStepper.runToNewPosition(anglePos);//Blocking until done
            Serial.print("Runtime "); Serial.println( millis() - lastMillis);
            Serial.println("Ready."); Serial.println();

            //            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
            //myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            //            break;
          }
        default:
          break;
      }
    }
  }
  //  if (guardCheck())
  //  {
  //    Serial.print("!");
  //myStepper.run();
  //  }
}// End of loop
/*
  moveTo KEYWORD2
  move  KEYWORD2
  run KEYWORD2
  runSpeed  KEYWORD2
  setMaxSpeed KEYWORD2
  setAcceleration KEYWORD2
  setSpeed  KEYWORD2
  speed KEYWORD2
  distanceToGo  KEYWORD2
  targetPosition  KEYWORD2z
  currentPosition KEYWORD2
  setCurrentPosition  KEYWORD2
  runToPosition KEYWORD2
  runSpeedToPosition  KEYWORD2
  runToNewPosition  KEYWORD2
  stop  KEYWORD2
  disableOutputs  KEYWORD2
  enableOutputs KEYWORD2
  setMinPulseWidth  KEYWORD2
  setEnablePin  KEYWORD2
  setPinsInverted KEYWORD2
  maxSpeed  KEYWORD2

  enum flag {const1, const2, ..., constN};
  By default, const1 is 0, const2 is 1 and so on. You can change default values of enum elements during declaration (if necessary).

  // Changing default values of enum constants
  enum suit {
  club = 0,
  diamonds = 10,
  hearts = 20,
  spades = 3,
  };
*/

I fixed the first post (again)

Tu use code tags make sure you paste the code on a new line and either use the IDE’s feature to copy for the forum or otherwise select the whole code and press the </> icon in the tool bar to mark it as code. (also make sure you indented the code in the IDE before copying, that’s done by pressing ctrlT on a PC or cmdT on a Mac)

Firstly, to simplify parsing chars, if you AND a char with 0x5F, you suppress bit 6, which makes all lower case chars upper case. E.g. 's'(0x73) becomes 'S'(0x53).
Secondly, even if you don't do that, switch() allows(untested code, sorry):

switch(cmd){
  case 's':
  case 'S':
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (GoStep);
  break;
  case 'c':
  case 'C':
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return (ChgMode);
  break;
  default:
  return (nobutton);
  break;
}

Although, that's not a style I would use for such a code. The multiple return paths are a coding style I shy away from; I prefer 'one entry', 'one exit' path.

and the break are not necessary after the return call (nor the parenthesis) and you could skip the default and perform the return for the function there

switch(cmd){
  case 's':
  case 'S':
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return GoStep;

  case 'c':
  case 'C':
    Serial.print("Recieved cmd "); Serial.println(cmd);
    return ChgMode;
}

return nobutton;

Bur it's really annoying to see cmd used for the enum type and a char...

that adds to the confusion there...

PS: I also favor 'one entry', 'one exit' path when possible

To make any typed English letter upper case:

if(char >= 'a' && char <= 'z')
  bitClear(char,5); // subtract 32 from ASCII value

To make any typed letter lower case:

if(char >= 'A' && char <= 'Z')
  bitSet(char,5); // add 32 to ASCII value

Many methods for skinning that poor old cat.

or rely on the old functions toupper and tolower