Need help converting String to int...

I am trying to create a servo controller that accepts input via serial...
Here is the complete code I have so far. None of the servo code is written yet, but once I figure out how to convert a String to an int I can easily add that. Any code improvements would be appreciated also.

//receive 5 numbers via serial.  First 2 numbers are the servo number (01,02,etc...), Second 3 numbers are the servo position(001,030,180,etc...)
char inData[4];    // Allocate space for incoming serial data (2 digit servo number, 3 digit position)
char inByte;      // Incoming serial character 
byte index = 0;   // Index into array; where to store the character

int8_t servo_num;
int8_t servo_position;

void setup() {   
  Serial.begin(9600);   
}   
  
void loop() {   
  while (Serial.available() > 0){
    inByte = Serial.read ();          //read serial input one byte at a time
    inData[index] = inByte;           //add serial input to array
    index++;                          //increment index (length/bytes of serial data received)
    if (index > 4 || inByte == 10 || inByte == 13){  //serial data is 5 bytes long or received a charage return or line feed
      inData[index] = '\0';           //Null terminate the string
      index = 0;

//Is there a better way to do the next 3 lines?
      String serialData = inData; //convert character array to String
      String servoNum = String(String(aton(serialData.charAt(0)))+String(aton(serialData.charAt(1))));
      String servoPosition = String(String(aton(serialData.charAt(2)))+String(aton(serialData.charAt(3)))+String(aton(serialData.charAt(4))));
      //****THIS IS THE PART I AM STRUGGLING WITH****
      //need to convert servoNum and servoPosition to integers servo_num and servo_position...
      //****THIS IS THE PART I AM STRUGGLING WITH****
      Serial.println(servo_num);
      Serial.println(servo_position);
    }
  }   
}

int8_t aton(int num){
//convert ASCII code to number
  int aton_i;
  if (num == 48){
    aton_i = 0;
  } else if (num == 49){
    aton_i = 1;
  } else if (num == 50){
    aton_i = 2;
  } else if (num == 51){
    aton_i = 3;
  } else if (num == 52){
    aton_i = 4;
  } else if (num == 53){
    aton_i = 5;
  } else if (num == 54){
    aton_i = 6;
  } else if (num == 55){
    aton_i = 7;
  } else if (num == 56){
    aton_i = 8;
  } else if (num == 57){
    aton_i = 9;
  }
  return(aton_i);
}

Update: Thanks to help from Arrch the code is working, and I no longer need to worry about converting String to int. See updated code below.

Servo test code that probably does what you need.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

Ditch the String object all together and just use the string you already have.

It seems like you only convert it to String so you can use the + operator and charAt member function. Much easier to work with the char arrays:

char num[3];
char pos[4];
strncpy(num, inData, 2);
num[2] = '\0';
strcpy(pos, inData+3);

You don't even need the second array, since you will just be passing it into atoi(), you can just pass inData+3 to it.

You should also extend that char array out a bit. You are using 5 numbers plus a null, so you need 6 bytes, but you only give it 4.

I have been looking to figure out a way to do the same on some longer strings with various types of values.
I have been looking into two functions not commonly used on the arduino stuff.

atoi() http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
sscanf() http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/

From back in the day that has atoi.

// zoomkat 10-4-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// Powering a servo from the arduino usually DOES NOT WORK.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(2000); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-21"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(1);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n;
    char carray[6]; //converting string to number
    readString.toCharArray(carray, sizeof(carray));
    n = atoi(carray); 
    myservo.writeMicroseconds(n); // for microseconds
    //myservo.write(n); //for degees 0-180
    readString="";
  } 
}

Thanks for all the replies!

I ended using Arrch's approach,with a bit of tweaking (less code and achieves exactly what I am looking for).

Here is the updated code:

//receive 5 numbers via serial.  First 2 numbers are the servo number, Second 3 numbers are the servo position
char inData[5];    // Allocate space for incoming serial data (2 digit servo number, 3 digit position)
char inByte;      // Incoming serial character 
byte index = 0;   // Index into array; where to store the character

int8_t servo_num;
uint8_t servo_position;

char pos[4];

void setup() {   
  Serial.begin(9600);   
}   
  
void loop() {   
  while (Serial.available() > 0){
    inByte = Serial.read ();          //read serial input one byte at a time
    inData[index] = inByte;           //add serial input to array
    index++;                          //increment index (length/bytes of serial data received)
    if (index > 4 || inByte == 10 || inByte == 13){  //serial data is 5 bytes longs or received a charage return or line feed
      inData[index] = '\0';           //Null terminate the string
      index = 0;
      servo_num = getServoNum();
      servo_position = getServoPos();
      Serial.println(servo_num);
      Serial.println(servo_position);
    }
  }   
}

int getServoNum(){
  char num[3];
   strncpy(num, inData, 2);
   num[2] = '\0';
   return(atoi(num));
}

int getServoPos(){
  char pos[4];
  strcpy(pos, inData+2);
  pos[3] = '\0';
  uint8_t t_pos = atoi(pos);
  if (t_pos > 180){
    t_pos = 180; 
  }
  return(t_pos);
}
char inData[5];     // Allocate space for incoming serial data (2 digit servo number, 3 digit position)

Should be 6: 2 + 3 + 1 (Null terminating char needs a spot too)

int getServoPos(){
  char pos[4];
  strcpy(pos, inData+2);
  pos[3] = '\0';
  return(atoi(pos));
}

Could be shortened even further:

int getServoPos(){
  return(atoi(inData+2));
}

The only reason we copied the server number into it's own array was because it was null-terminated; you don't have that same concern in the server position.

Thinking about it further, you could just do something like this too, and save yourself a couple steps:

unsigned long tmp = atoi(inData);
int servo_num = tmp / 1000;
int servo_pos = tmp % 1000;

So say for example, inData was { '0', '2', '1', '2', '3', '\0' }.
tmp would be 2123.
tmp / 1000 would be 2
tmp % 1000 would be 123

I made the changes and it works great! Thanks for all the help.
I will play around with the tmp math...

//receive 5 numbers via serial.  First 2 numbers are the servo number, Second 3 numbers are the servo position
char inData[6];    // Allocate space for incoming serial data (2 digit servo number, 3 digit position)
char inByte;      // Incoming serial character 
byte index = 0;   // Index into array; where to store the character

int8_t servo_num;
uint8_t servo_position;

void setup() {   
  Serial.begin(9600);   
}   
  
void loop() {   
  while (Serial.available() > 0){
    inByte = Serial.read ();          //read serial input one byte at a time
    inData[index] = inByte;           //add serial input to array
    index++;                          //increment index (length/bytes of serial data received)
    if (index > 4 || inByte == 10 || inByte == 13){  //serial data is 5 bytes longs or received a charage return or line feed
      inData[index] = '\0';           //Null terminate the string
      index = 0;
      servo_num = getServoNum();
      servo_position = getServoPos();
      Serial.println(servo_num);
      Serial.println(servo_position);
    }
  }   
}

int getServoNum(){
  char num[3];
   strncpy(num, inData, 2);
   num[2] = '\0';
   return(atoi(num));
}

int getServoPos(){
  uint8_t t_pos = atoi(inData+2);
  if (t_pos > 180){
    t_pos = 180; 
  }
  return(t_pos);
}

I have another issue now... I am trying to add some error checking to the if statement in the loop() function.
The if statement tests for index to be greater than 4 or inByte to be either a charage return or line feed.
I need to clear inData and break the while loop if index is less than 5, but a charage return/line feed was received.

I have tried several things, but none seem to achieve the intended results. Any ideas?

void loop() {   
  while (Serial.available() > 0){
    inByte = Serial.read ();          //read serial input one byte at a time
    inData[index] = inByte;           //add serial input to array
    index++;                          //increment index (length/bytes of serial data received)
    if (index > 4 || inByte == 10 || inByte == 13){  //serial data is 5 bytes longs or received a charage return or line feed
      if (index < 5){
            //clear inData...
            break;
      }
      inData[index] = '\0';           //Null terminate the string
      index = 0;                      //reset index
      unsigned long tmp = atoi(inData);
      servo_num = tmp / 1000;
      servo_pos = tmp % 1000;
      if (servo_pos > 180){
        servo_pos = 180; 
      }
      Serial.println(servo_num);
      Serial.println(servo_pos);
    }
  }   
}

'char pos[4];' looks to no longer be used.

I'd suggest replacing ...

if (index > 4 || inByte == 10 || inByte == 13)

... with ...

if ( (index > 4) || (inByte == '\n') || (inByte == '\r') )

And 'getServoNum' can be shortened to ...

int getServoNum()
{
    char num[3] = { 0 };
    
    return atoi(strncpy(num, inData, sizeof(num) - 1));
}

Thanks. I removed "char pos[4]", since it is not needed anylonger.

getServoNum() and getServoPos() also gone now. They are replaced by this code:

      unsigned long tmp = atoi(inData);
      servo_num = tmp / 1000;
      servo_pos = tmp % 1000;

Which accomplishes the same goal as uses less code