Reading both char and int and evaluating from serial monitor

Hello there :slight_smile:

I have some code that reads a numerical value from the serial monitor and passes it on once ‘enter’ is sent.
I would like to be able to send a single char and have that evaluated as well (or string), but I must admit Im too new at this to figure it out.

(see code below)
What I’d like to do, is to send ‘123’ or ‘r’ and send the program to a function depending on the input.
if(var == 123){
function_int();
}
if(var1 == ‘r’){
function_char;
}

  Var = 0;
  if (Serial.available()) {
    Serial.println("debug");
    byte incomingByte = Serial.read(); //read serial
    while (incomingByte != '\n') { //run 'while' as long as 'enter' hasn't been sent
      Serial.println("debug0");
      if (incomingByte >= '0' && incomingByte <= '9') //restrict to 0-9
        newPosTemp = newPosTemp * 10 + (incomingByte - '0'); //convert to int
      incomingByte = Serial.read();


    }

    if (newPosTemp >= 0 && newPosTemp <= 3501) { //restrict to 0-3501 so we don't slam in to end of rail
      newPos = newPosTemp; //otherwise newPos keeps incrementing
      Serial.print("moving to ");
      Serial.println(newPosTemp);
      newPosTemp = 0; //reset
      Stop = 0; //ensure motor has a green light
      time = millis();
      Var = 1;
    }
    else
    { Serial.println("Choose a position <= 3500");
      newPosTemp = 0;
      Stop = 0;
    }
  }

Can I get some guidance? :slight_smile:

Best regards

Can I get some guidance?

      if (incomingByte >= '0' && incomingByte <= '9') //restrict to 0-9
        newPosTemp = newPosTemp * 10 + (incomingByte - '0'); //convert to int

If the character isn’t a digit, it must be something else, right?

Add an else clause to deal with the something else part.

Okay, so that makes sense. I’ve modified the code a bit.

IF something other than 0-9 is received, it should convert the value to CHAR and print it (and print the byte value as well).

If I enter an ‘r’ now, I get this output in the monitor:

debug0
114
r
debug0

…repeatedly

…which means it stays in the ‘while’ loop (even though a ‘newline’ has been sent)

If I enter a value of ‘123’, it returns:

debug
debug0
debug0
debug0
moving to 123
Choose a position <= 3500

…which means it takes 3 values from the monitor + newline and passes it on.

I don’t really understand why when the first ‘if’ afterwards is true (between 0-3501) it run the ‘else’ statement ?
And why is the if(incomingByte == 114) never true?

Thanks for the help so far :slight_smile:

Best regards,

int newPosTemp;
int newPos;
int Var = 0;

char newVar;
char var;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

}

void loop() {
  Var = 0;
  if (Serial.available()) {
    Serial.println("debug");
    byte incomingByte = Serial.read(); //read serial
    while (incomingByte != '\n') { //run 'while' as long as 'enter' hasn't been sent
      Serial.println("debug0");
      if (incomingByte >= '0' && incomingByte <= '9') { //restrict to 0-9
        newPosTemp = newPosTemp * 10 + (incomingByte - '0'); //convert to int
        incomingByte = Serial.read();
      }
      else
      {
        newVar = incomingByte;
        Serial.println(incomingByte);
        Serial.println(newVar);
      }

    }

    if (newPosTemp >= 0 && newPosTemp <= 3501) { //restrict to 0-3501 so we don't slam in to end of rail
      newPos = newPosTemp; //otherwise newPos keeps incrementing
      Serial.print("moving to ");
      Serial.println(newPosTemp);
      newPosTemp = 0; //reset
      Var = 1;
    }
    if (incomingByte == 114) {
      Serial.println(newVar);
      Serial.println("Success!");
    }
    else
    { Serial.println("Choose a position <= 3500");
      newPosTemp = 0;

    }
  }

}

IF something other than 0-9 is received, it should convert the value to CHAR

Well, no. First, the type returned by Serial.print() is an int. When you KNOW that there will be data to read, because you called Serial.available() first (which you do), then the data is in the low order byte.

But, it makes more sense to use a one byte type that reflects what the data really is.

   char incomingData = Serial.read();
   if(incomingData >= '0' && incomingData <= '9')
   {
      // Convert the character to a value by subtracting '0'
   }
   else
   {
      // No conversion needed, since you already have a char
   }

I absolutely hate when the variable name implies a type, as incomingByte does. It looks stupid when you change the type, then.

byte incomingData ==> char incomingData looks reasonable.
byte incomingByte ==> char incomingByte looks stupid.

(Putting away soap box now).

And why is the if(incomingByte == 114) never true?

The last byte read was what? What triggered the end of the while loop? Hint: It was NOT the arrival of a 114 (whatever that is).

You recorded the non-digit character in another variable. Why are you not testing THAT variable?

Why not make it VERY clear what you are testing?

if(incomingData == 'r')

performs the same text, but I do not need to consult an ASCII table to learn what to send.

I thought serial.read() returned a byte hmm is it an int and ‘char incomingData = serial.read’ stores it as a char? I have to read up on that.

I absolutely hate when the variable name implies a type, as incomingByte does. It looks stupid when you change the type, then.

byte incomingData ==> char incomingData looks reasonable.
byte incomingByte ==> char incomingByte looks stupid.

(Putting away soap box now).

Point taken - it was from a book Im reading - hurray for search&replace :slight_smile:

I used a newVar = incomingData to store the ‘r’ before checking for a newline again >_o, that way the newVar == ‘r’ works.

You recorded the non-digit character in another variable. Why are you not testing THAT variable?

To which are you referring?

I’ve put my code below that now WORKS! Thanks! :slight_smile:

int newPosTemp;
int newPos;
int Var = 0;

char newVar;
char var;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

}

void loop() {
  Var = 0;
  if (Serial.available()) {
    Serial.println("debug");
    char incomingData = Serial.read(); //read serial
    while (incomingData != '\n') { //run 'while' as long as 'enter' hasn't been sent
      Serial.println("debug0");
      if (incomingData >= '0' && incomingData <= '9') { //restrict to 0-9
        newPosTemp = newPosTemp * 10 + (incomingData - '0'); //convert to int
        incomingData = Serial.read();
      }
      else
      {
        //Serial.println(incomingData);
        newVar = incomingData;
        incomingData = Serial.read();
      }

    }

    if (newPosTemp >= 0 && newPosTemp <= 3501 && newVar != 'r') { //restrict to 0-3501 so we don't slam in to end of rail
      newPos = newPosTemp; //otherwise newPos keeps incrementing
      Serial.print("moving to ");
      Serial.println(newPosTemp);
      newPosTemp = 0; //reset
      Var = 1;
    }
    
    if(newPosTemp >= 3500){
      Serial.println("Choose a position <= 3500");
      newPosTemp = 0;
    }
    
    if (newVar == 'r') {
      Serial.println(newVar);
      Serial.println("Success!");
      
    }
    

    
  }

Have a look at the examples in serial input basics - simple and reliable.

...R

Robin2: Have a look at the examples in serial input basics - simple and reliable.

...R

Cool - seems just what I need to read :)

Regards

You might find:

isascii() isdigit()

useful.

econjack: You might find:

isascii() isdigit()

useful.

Thanks :)