If/Else statements reading from serial monitor

Hi,

I am a newcomer and first time poster, I'm working on trying to control a servo from an analog joystick. I have my X/Y Axis values being written to the serial monitor, I have been looking over parsing the serial data strings and how to turn certain strings into an if statement. I'm sure there are a lot of topics that cover this but I have not been able to find anything after searching, I have found a lot of how to write to the serial monitor but I am looking to read specific string text and turning that into an if statement.

Thanks

jbarth200:
Hi,

I am a newcomer and first time poster, I'm working on trying to control a servo from an analog joystick. I have my X/Y Axis values being written to the serial monitor, I have been looking over parsing the serial data strings and how to turn certain strings into an if statement. I'm sure there are a lot of topics that cover this but I have not been able to find anything after searching, I have found a lot of how to write to the serial monitor but I am looking to read specific string text and turning that into an if statement.

Thanks

That is about as clear as mud.

You'll want to start by posting your sketch using code tags.

I have found a lot of how to write to the serial monitor but I am looking to read specific string text and turning that into an if statement.

What specific text strings? X and Y from your joystick are likely numbers not text strings so you can just do comparisons such as

int X;

...

if (X < -5) { // go left
...
} else if (X > 5) { // go right
...
} else { // centered don’t move
...
}

Dealing with cStrings ( text in null terminated char array) is done through functions from standard C libraries such as stdlib.h or string.h

If your question is how to get stuff from the serial monitor then have a look at Serial Input Basics

ok. so if you want to use strings as command, you first need to used delimiters to mark the end of your command string.

you can used "readStringUntil()" function to read your string to an array from serial monitor (Serial.readStringUntil() - Arduino Reference)

then in your actual code use a if/elseif or switch case statements to define your actions. for example:

char cmd;

if(cmd=="CMD1"){
//do command 1
}
else if(cmd=="CMD2"){
//do command 2
}
.
.
.

OR

switch(cmd){

case "CMD1":
//do command 1
break;

case "CMD2":
//do command 2
break;

.

.

.

}

@Sherzaad

(Where are your code tags?)

This code is total crap, you don’t compare cStrings with == and switch does not work on char arrays… (and allocating some memory in the array would be a good idea)

Why would you make such recommendations?

J-M-L:
What specific text strings? X and Y from your joystick are likely numbers not text strings so you can just do comparisons such as

int X;

if (X < -5) { // go left

} else if (X > 5) { // go right

} else { // centered don’t move

}




Dealing with cStrings ( text in null terminated char array) is done through functions from standard C libraries such as [stdlib.h](http://www.cplusplus.com/reference/cstdlib/) or [string.h](http://www.cplusplus.com/reference/cstring/)


If your question is how to get stuff from the serial monitor then have a look at [Serial Input Basics](http://forum.arduino.cc/index.php?topic=396450.0)

I will look into those, thank you. And yes, they would be just numbers, the example sketch I was using (Pasted below) did add in some text around those values. I will need to look up some more basics as I think I may be too new to try to understand some of this, after you said that I went back through and was able to achieve what I wanted based off the analogRead function of that pin, I guess before hand I was trying to do a Serial.read and was trying to say “if (Serial.read() > “X-axis: 507”){ condition” I was going about it all wrong.

 #include <Servo.h>

Servo myservo;


int pos = 0;




// Arduino pin numbers
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

void setup() {
  myservo.attach(9);
  pinMode(SW_pin, INPUT);
  digitalWrite(SW_pin, HIGH);
  Serial.begin(9600);
}

void loop() {
  Serial.print("Switch:  ");
  Serial.print(digitalRead(SW_pin));
  Serial.print("\n");
  Serial.print("X-axis: ");
  Serial.print(analogRead(X_pin));
  Serial.print("\n");
  Serial.print("Y-axis: ");
  Serial.println(analogRead(Y_pin));
  Serial.print("\n\n");
  delay(1000);

  if (analogRead(X_pin) > 507) {
    Serial.println("Close");
    pos <= 180; pos += 20; // goes from 0 degrees to 180 degrees
    // in steps of 20 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(150);                       // waits 15ms for the servo to reach the position
  }
  else
  {
    pos <= -180; pos += 20; // goes from 0 degrees to 180 degrees
    // in steps of 20 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(150);                       // waits 15ms for the servo to reach the position
  }
}

Disregard the servo info as of now, that was while testing, I was able to write “Close” onto my serial monitor, this gets me what I needed. Thanks again.

There is no way for you to read what you sent to the serial console (well not without routing the output Tx to Rx)... a read would read what the user typed in not what you printed out

If you want to make sure your code acts on the same value your printed, best is to read it only once and save it somewhere and then use that variable,

int x = analogRead(X_pin);
Serial.print("X-axis: ");
Serial.println(x); // println will add  “\r\n” for you at the end after printing the value
if (x > 507) {
   ....
}

Thank you for all the good information, I changed my code above to reflect correctly. I did change a few things around to try and get my servo to act upon the if statement. Still working on having a better understandings of servos as well.

Hi,
What sort of control do you want between your joystick and servo?

  • Joystick in mid position, servo at 90deg
  • When you move the joystick the servo tracks the joystick.
  • So when the joystick is fully left - servo goes to 0deg
  • joystick fully right - servo goes to 180deg.
  • Any joystick position in between the servo position in between. So if you return joystick to mid position the servo returns to 90deg.

OR

  • Joystick in mid position
  • Move joystick left and servo moves and keeps moving to 0deg until joystick returns to midposition then servo stops'
  • Joystick right and servo moves towards 180deg unitl joystick returns to midposition then servo stops.?

I think you have become fixated on displaying your joystick position and using the displayed value to control the servo.

Think like this, the joystick controls the servo and the display is an addon that monitors what is sent to the servo.

Look in the IDE under Servo and load the SWEEP example, and apply that to your servo, ONLY code for ONE servo and get it working, forget the other for the moment.
Then add the display.

So first try the SWEEP example, your joystick is the pot input.
Show us a circuit diagram of what you have, please.

Just a picture of a pen/pencil paper schematic will save a thousand words.
What joystick do you have?

Tom... :slight_smile:

Thanks, ideally I want to go left on the joystick, have the servo go one way, when I release the joystick back to center, I want the servo to hold the position, if it did not make it to the limit of the 180 degrees, when I go left again on the joystick it would continue where it left off. When I go right I want it to go the opposite direction from where the servo was in a hold position so if I go left and stop and it doesn’t go all the way, go right and it will start going the opposite direction. I have not put anything on paper, pretty much just voltage to the servo and pin 9 for pulses, my joystick is X axis is A1, Y axis is A2. Here is the code I have now, I am getting closer to what I want but still feel far off, also I’m fairly sure there is an array or some way to clean this up and not have all these if statements.

//www.elegoo.com
//2016.12.09

#include <Servo.h>

Servo myservo;






// Arduino pin numbers
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

void setup() {
  myservo.attach(9);
  pinMode(SW_pin, INPUT);
  digitalWrite(SW_pin, HIGH);
  Serial.begin(9600);

}

void loop() {
  Serial.print("Switch:  ");
  Serial.print(digitalRead(SW_pin));
  Serial.print("\n");
  Serial.print("X-axis: ");
  Serial.print(analogRead(X_pin));
  Serial.print("\n");
  Serial.print("Y-axis: ");
  Serial.println(analogRead(Y_pin));
  Serial.print("\n\n");
  delay(50);


  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(100);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(110);
    delay(500);

  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(120);
    delay(500);

  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(130);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(140);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(150);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(160);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(170);
    delay(500);
  }

  if (analogRead(X_pin) > 535) {
    Serial.println("Close");
    myservo.write(180);
    delay(500);

  }




  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(80);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(70);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(60);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(50);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(40);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(30);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(20);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(10);
    delay(500);
  }

  if (analogRead(X_pin) < 502) {
    Serial.println("Not Close");
    myservo.write(0);
    delay(500);
  }
}

Figured this may be the wrong road to go down, I am going to use a stepper motor to try to achieve what I need.

Hi,
You need to read ALL your inputs digital and analog and store them as variables, at the BEGINNING of the loop.

Then use those variables through your code, that way you take a snapshot of your inputs and act on it.

Continually reading various input repeatedly in your code will cause confusion and code inconsistencies.

I'll have a look at your code and see what I can do.

Tom... :slight_smile:

Hi,
Try this code,
I have edited yours and hopefully I have it doing what you want.
X axis is connected to A0.
Y axis is connected to A1.
If you want the servo to move faster, increase the value of

int servoXincrement = 1; // steps to move servoX per loop

I have changed your monitor display to make it readable at the loop rate.
This will change the loop sample rate in milliseconds

const int loopupdate = 50;

I have added some hysteresis into the joystick response so you have a dead band in the center position of the joystick position. This will stop any jitter in the center position.

// 15:15    30/03/2018

#include <Servo.h>
Servo servoX;  // name the servo controlled by X axis joystick

// Arduino pin numbers
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = A0; // analog pin connected to X output
const int Y_pin = A1; // analog pin connected to Y output
const int servoXincrement = 1; // steps to move servoX per loop
const int Xhysteresis = 50; // hysteresis to give centre deadband to joystick
const int loopupdate = 50;

int XJval = 0;  // joystick X axis value
int YJval = 0;  // joystick Y axis value
bool SWVal = 0; // switch state (Pressed == LOW)
int servoXval = 90; // initial position of the servoX


void setup() {
  servoX.attach(9);
  pinMode(SW_pin, INPUT_PULLUP);
  pinMode(X_pin, INPUT);
  pinMode(Y_pin, INPUT);
  Serial.begin(9600);
  servoX.write(servoXval); // position servo at 90 deg

}

void loop() {
  // read all inputs and display to monitor
  Serial.print("Switch:  ");
  SWVal = digitalRead(SW_pin);
  Serial.print(SWVal);
  Serial.print("\t X-axis: ");
  XJval = analogRead(X_pin);
  Serial.print(XJval);
  Serial.print("\t Y-axis: ");
  YJval = analogRead(Y_pin);
  Serial.print(YJval);

  delay(loopupdate);

  // check for Close XJval
  if (XJval > 535 + Xhysteresis) {
    servoXval = servoXval + servoXincrement; // inc servo position
    if (servoXval > 180)  // if val over 180, keeps value at 180.
    {
      servoXval = 180;
    }
    Serial.print("\t Closing");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
    servoX.write(servoXval);
  }

  // check for Open XJval
  if (XJval < 535 - Xhysteresis) {
    servoXval = servoXval - servoXincrement;  // dec servo position
    if (servoXval < 0)  // if val under 0, keeps value at 0.
    {
      servoXval = 0;
    }
    Serial.print("\t Opening");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
    servoX.write(servoXval);
  }
  if (XJval > ((535 - Xhysteresis)) && (XJval < (535 + Xhysteresis)))
  {
    Serial.print("\t Stopped");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
  }

}

Tom… :slight_smile:

So you need to memorize the servo’s angle in a variable and in the setup bring your servo to that angle.

Then you let the loop spin and check if deltaT ms have elapsed.

  • if so check where your joystick is:
  • if it’s left you subtract 1 to the servo position (assuming you are > MINANGLE)
  • if it’s centered you do nothing
  • if it’s right you add 1 to the servo position (assuming you are < MAXANGLE)

deltaT, MINANGLE, MAXANGLE are parameters you define for your program / system

—-

EDIT well (Sadly IMHO) Tom gave you a code that is basically Implementing this. ==> for you to do so that you don’t purely copy
=> don’t use delay and implement a loop with millis()
=> handle min and max angles. Cheap Servos usuallly don’t do well close to 0 or 180
=> manage speed of the motor using Y axis and playing with the timing between two updates

Hi,

jbarth200:
Figured this may be the wrong road to go down, I am going to use a stepper motor to try to achieve what I need.

Is the reason for the code edit, to show it is possible.

J-M-L:
EDIT well (Sadly IMHO) Tom gave you a code that is basically Implementing this. ==> for you to do so that you don’t purely copy
=> don’t use delay and implement a loop with millis()
=> handle min and max angles. Cheap Servos usuallly don’t do well close to 0 or 180
=> manage speed of the motor using Y axis and playing with the timing between two updates

I agree about delay and max/min angles, but I don’t have the OPs servos, or how his system responds.
Tom, :slight_smile:

You could have told OP it was possible without giving the full answer but this sure makes OP’s life easier :slight_smile:

While I understand what J-M-L is saying, I appreciate it very much Tom! Seeing the end result and working back to understand each variable and how this code works has actually helped me a lot by understanding better control with the use of variables and the difference between const int/int. I am looking forward to giving this a go tonight and expanding the use of this. Thank you both for all the help with this!

jbarth200:
While I understand what J-M-L is saying, I appreciate it very much Tom! Seeing the end result and working back to understand each variable and how this code works has actually helped me a lot by understanding better control with the use of variables and the difference between const int/int. I am looking forward to giving this a go tonight and expanding the use of this. Thank you both for all the help with this!

I could see you were floundering a bit with your code, so a hopefully working example will help.
It is by no means the best code and you still have to write for Y axis.
I hope you understand the Serial.print /t , it is the tab instruction that helps to give a column of numbers, making the continually up dating monitor easier to read.
As previously mentioned, there are other ways to update the monitor, but this is the simplest.
Other methods only print to monitor if there is a displayed data change so reading your results is even easier.
Tom.. :slight_smile:

So I have setup the code for control over 2 servos, I’m having some issues though, while controlling 1 servo worked without any issues, it somewhat seems like I’m getting some sort of feedback, if I run this sketch and remove the servo from pin 10, the behavior is perfect for pin 9, I can move that servo from pin 9 to pin 10 and the Y axis movements works perfectly. The minute I add the 2nd servo into the mix, both start acting strange and moving erratically. Here is my code, are their specific pins that I should be using? I had thought the frequency for pins 9/10 on the Mega2560 R3 were the same, is that possibly my problem?

// 15:15    30/03/2018

#include <Servo.h>
Servo servoX;  // name the servo controlled by X axis joystick
Servo servoY; // name the 2nd servo controllered by Y axis joystick

// Arduino pin numbers
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = A0; // analog pin connected to X output
const int Y_pin = A1; // analog pin connected to Y output
const int servoXincrement = 5; // steps to move servoX per loop
const int Xhysteresis = 50; // hysteresis to give centre deadband to joystick
const int loopupdate = 100;
const int servoYincrement = 5; // steps to move servoY per loop
const int Yhysteresis = 50; // hysteresis to give centre deadband to joystick


int XJval = 0;  // joystick X axis value
int YJval = 0;  // joystick Y axis value
bool SWVal = 0; // switch state (Pressed == LOW)
int servoXval = 90; // initial position of the servoX
int servoYval = 90; // inital position of the servoY


void setup() {
  servoX.attach(9);
  servoY.attach(10);
  pinMode(SW_pin, INPUT_PULLUP);
  pinMode(X_pin, INPUT);
  pinMode(Y_pin, INPUT);
  Serial.begin(9600);
  servoX.write(servoXval); // position servo X at 90 deg
  servoY.write(servoYval); // position servo Y at 90 deg

}

void loop() {
  // read all inputs and display to monitor
  Serial.print("Switch:  ");
  SWVal = digitalRead(SW_pin);
  Serial.print(SWVal);
  Serial.print("\t X-axis: ");
  XJval = analogRead(X_pin);
  Serial.print(XJval);
  Serial.print("\t Y-axis: ");
  YJval = analogRead(Y_pin);
  Serial.print(YJval);

  delay(loopupdate);

  // check for Close XJval
  if (XJval > 800 + Xhysteresis) {
    servoXval = servoXval + servoXincrement; // inc servo position
    if (servoXval >= 170)  // if val over 180, keeps value at 180.
    {
      servoXval = 170;
    }
    Serial.print("\t Closing");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
    servoX.write(servoXval);
  }

  // check for Open XJval
  if (XJval < 200 - Xhysteresis) {
    servoXval = servoXval - servoXincrement;  // dec servo position
    if (servoXval <= 10) // if val under 0, keeps value at 0.
    {
      servoXval = 10;
    }
    Serial.print("\t Opening");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
    servoX.write(servoXval);
  }
  if (XJval > ((535 - Xhysteresis)) && (XJval < (535 + Xhysteresis)))
  {
    Serial.print("\t Stopped");
    Serial.print("\t ServoX Position \t ");
    Serial.println(servoXval);
  }


  delay(loopupdate);

  // check for Close XJval
  if (YJval > 800 + Xhysteresis) {
    servoYval = servoYval + servoYincrement; // inc servo position
    if (servoYval >= 160)  // if val over 180, keeps value at 180.
    {
      servoYval = 160;
    }
    Serial.print("\t Closing 2");
    Serial.print("\t ServoY Position \t ");
    Serial.println(servoYval);
    servoY.write(servoYval);
  }


  // check for Open XJval
  if (YJval < 200 - Xhysteresis) {
    servoYval = servoYval - servoYincrement;  // dec servo position
    if (servoYval <= 10) // if val under 0, keeps value at 0.
    {
      servoYval = 10;
    }
    Serial.print("\t Opening 2");
    Serial.print("\t ServoY Position \t ");
    Serial.println(servoYval);
    servoY.write(servoYval);
  }
  if (YJval > ((535 - Xhysteresis)) && (YJval < (535 + Xhysteresis)))
  {
    Serial.print("\t Stopped 2");
    Serial.print("\t ServoY Position \t ");
    Serial.println(servoYval);
  }
}

Realized using the serial monitor that at times 2 IF conditions were present, although they should not have been. I did switch to digital pins 53/51 and changed a few values..seems much more stable now.