Getting input from serial monitor

I am using someone else's code, and running into a problem with it, and not understanding where it is going wrong. It is supposed to take an input of 3 bits, and in his example, separated by commas. When I try it, it seems to fail to properly format or compute the input the first time around, but then it subsequently correctly formats it, and keeps repeating it.

I am wondering:
1)Why does it fail on the first input, of say 015,015,015?
2) Why does it keep repeating the output?
3) Is it made to accept a subsequent input of another three, three bit characters? If so, it doesn't seem to work for me.

Here is the code:

[code]
#include "I2Cdev.h"               
#include "MPU6050.h"
#include "Wire.h"

#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38

#define Y_STEP_PIN 60
#define Y_DIR_PIN 61
#define Y_ENABLE_PIN 56

#define Z_STEP_PIN 46
#define Z_DIR_PIN 48
#define Z_ENABLE_PIN 62

MPU6050 accelgyro1 (0x68);
MPU6050 accelgyro2 (0x69); 
 
int16_t ax, ay, az;
int16_t gx, gy, gz;
double x,y,z, xx, yy, zz;
double d,D,A,B,C;
int F=0,f;

String readString, Sumbu_X, Sumbu_Y, Sumbu_Z;
double R,S,T;
double Q1,W1,E1;
double Q0,Q4,W0,W4,E2;
double Q3,W3,E3;

#define LED_PIN 13
bool blinkState = false;

void setup() {
  Wire.begin();
  Wire.setClock(400000);
  Serial.begin(9600);
  Serial.println("Initializing I2C devices...");
  accelgyro1.initialize();
  accelgyro2.initialize();  
 
  Serial.println("Testing device connections...");
  Serial.println(accelgyro1.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  Serial.println("Testing device connections...");
  Serial.println(accelgyro2.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  Serial.println("Input the Coordinate (3 bit each plane) Of X,Y,Z!");
  pinMode(LED_PIN, OUTPUT);
  pinMode(X_STEP_PIN  , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_ENABLE_PIN    , OUTPUT);
  digitalWrite(X_ENABLE_PIN    , LOW);
  pinMode(Z_STEP_PIN  , OUTPUT);
  pinMode(Z_DIR_PIN    , OUTPUT);
  pinMode(Z_ENABLE_PIN    , OUTPUT);
  digitalWrite(Z_ENABLE_PIN    , LOW);
  pinMode(Y_STEP_PIN  , OUTPUT);
  pinMode(Y_DIR_PIN    , OUTPUT);
  pinMode(Y_ENABLE_PIN    , OUTPUT);
  digitalWrite(Y_ENABLE_PIN    , LOW);
}

void loop() {
  while (Serial.available()) { 
    if (Serial.available() >0) {
     char c = Serial.read();
     readString += c;
    } 
  }

  if (readString.length() >0) {
     Serial.println(readString);      
     Sumbu_X = readString.substring(0, 4);
     Sumbu_Y = readString.substring(4, 8);
     Sumbu_Z = readString.substring(8, 12);
          
     double n1;
     double n2;
     double n3;
     
     char carray1[6];
     Sumbu_X.toCharArray(carray1, sizeof(carray1));
     n1 = atoi(carray1); 
     
     char carray2[6];
     Sumbu_Y.toCharArray(carray2, sizeof(carray2));
     n2 = atoi(carray2); 

     char carray3[6];
     Sumbu_Z.toCharArray(carray3, sizeof(carray3));
     n3 = atoi(carray3); 

     R = n1;
     S = n2;
     T = n3;
     
     Serial.print("X = ");Serial.println (R);
     Serial.print("Y = ");Serial.println (S);
     Serial.print("Z = ");Serial.println (T);

     /*Sudut Theta Satu*/
     Q1 = S/R;
     W1 = atan(Q1)/0.0174532925199433;
  
      if (R>=0 && S>=0) {
        f = W1/0.1;
        Serial.print("Sudut 1 = ");Serial.println (W1);
      }
      else if(R<=0 && S>=0) {
        E1 = 180+W1;
        f = E1/0.1;
        Serial.print("Sudut 1 = ");Serial.println (E1);
      }
      else if(R<=0 && S<=0) {
        E1 = 180+W1;
        f = E1/0.1;
        Serial.print("Sudut 1 = ");Serial.println (E1);
      }
      else {
        E1 = 360+W1;
        f = E1/0.1;
        Serial.print("Sudut 1 = ");Serial.println (E1);
      }

     /*Sudut Theta 2*/
     Q0 = (T-10)/(sqrt((R*R)+(S*S)));
     W0 = atan(Q0)/0.0174532925199433;
     Q4 = ((13.5*13.5)+(R*R)+(S*S)+((T-10)*(T-10))-(16*16))/(2*13.5*sqrt((R*R)+(S*S)+((T-10)*(T-10))));
     W4 = acos(Q4)/0.0174532925199433;
     E2 = W0+W4;
     Serial.print("Sudut 2 = ");Serial.println (E2);
     
     /*Sudut Theta 3*/
     Q3 = ((R*R)+(S*S)+((T-10)*(T-10))-(13.5*13.5)-(16*16))/(2*13.5*16);
     W3 = acos(Q3)/0.0174532925199433;
     E3 = -1*W3;
     Serial.print("Sudut 3 = ");Serial.println (E3);
     delay(1);

     /*Link 1*/
     for(F;F<=f;F++){
      digitalWrite(X_DIR_PIN, HIGH);
      digitalWrite(X_STEP_PIN, HIGH);
      delay(1);
      digitalWrite(X_STEP_PIN, LOW);
     }
     
     /*Link 2*/
     gyro(); 
     
     if (A>= (E2-2) && A <= (E2+2)){
      /*Link 3*/
     gyro_1();
  
      if(C>= (E3-2) && C<= (E3+2)){
      }
      else{
        if (C < E3){
          digitalWrite(Z_DIR_PIN, LOW);
          digitalWrite(Z_STEP_PIN, HIGH);
          delay(1);
          digitalWrite(Z_STEP_PIN, LOW);
        }
        else{
          digitalWrite(Z_DIR_PIN, HIGH);
          digitalWrite(Z_STEP_PIN, HIGH);
          delay(1);
          digitalWrite(Z_STEP_PIN, LOW);
        } 
      }
     }

     /*Link 2*/
     else{
      if (A < E2){
        digitalWrite(Y_DIR_PIN, HIGH);
        digitalWrite(Y_STEP_PIN, HIGH);
        delay(1);
        digitalWrite(Y_STEP_PIN, LOW);
      }
      else{
        digitalWrite(Y_DIR_PIN, LOW);
        digitalWrite(Y_STEP_PIN, HIGH);
        delay(1);
        digitalWrite(Y_STEP_PIN, LOW);
      }
     }
     
 }
}

void gyro() {
  accelgyro1.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  xx = ax;
  yy = ay;
  zz = az;

  x = xx/(4*4096);
  y = yy/(4*4096);
  z = zz/(4*4096);
  d = x/z;
  D = atan(d)/0.0174532925199433;
  if (D<0)
  {
    A = 180+D;
  }
  else 
  {
    A=D;  
  }
}

void gyro_1(){
  accelgyro2.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  xx = ax;
  yy = ay;
  zz = az;

  x = xx/(4*4096);
  y = yy/(4*4096);
  z = zz/(4*4096);
  d = x/z;
  B = atan(d)/0.0174532925199433;
  C=B-A;
}

[/code]

The variable "readString" is never cleared, so it will only work once. I also believe that the substrings retreived from "readString" are one character too long.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

...R

Thanks, I had forgotten about your write up on the subject. I had written a program previously, that parsed data from serial that was in the format <1,180>

and to do that I used the following:

[code]
void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  Sumbu_X = atoi(strtokIndx); // my addition convert first part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Sumbu_Y = atoi(strtokIndx);     // convert this part to an integer


}

[/code]

How would I edit this so that it parses a third integer, such as from <1,180,180>?

I'm thinking:

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  Sumbu_X = atoi(strtokIndx); // my addition convert first part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Sumbu_Y = atoi(strtokIndx);     // convert this part to an integer

strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Sumbu_Z = atoi(strtokIndx);     // convert this part to an integer


}

Northof49:
How would I edit this so that it parses a third integer, such as from <1,180,180>?

I'm thinking:

Did you try it? What happened?

Arduinos are great for learning-by-doing.

...R

Can anyone explain to me what is happening when he takes the data that he collects called Sumbu_X and converts it first to n1, then converts it to R? Is all that done simply to produce an integer?

  if (readString.length() >0) {
     Serial.println(readString);      
     Sumbu_X = readString.substring(0, 4);
     Sumbu_Y = readString.substring(4, 8);
     Sumbu_Z = readString.substring(8, 12);
          
     double n1;
     double n2;
     double n3;
     
     char carray1[6];
     Sumbu_X.toCharArray(carray1, sizeof(carray1));
     n1 = atoi(carray1); 
     
     char carray2[6];
     Sumbu_Y.toCharArray(carray2, sizeof(carray2));
     n2 = atoi(carray2); 

     char carray3[6];
     Sumbu_Z.toCharArray(carray3, sizeof(carray3));
     n3 = atoi(carray3); 

     R = n1;
     S = n2;
     T = n3;
     
     Serial.print("X = ");Serial.println (R);
     Serial.print("Y = ");Serial.println (S);
     Serial.print("Z = ");Serial.println (T);

He does the same thing with Sumbu_Y and Sumbu_Z

It appears from the serial print output that R,S and T are simply integers. If so, what a lot of convolutions to get there.

There are many things wrong with that code. It starts by collecting characters with:

[color=#222222]while (Serial.available()) { [/color][color=#222222][/color]
[color=#222222]    if (Serial.available() >0) {[/color][color=#222222][/color]
[color=#222222]     char c = Serial.read();[/color][color=#222222][/color]
[color=#222222]     readString += c;[/color][color=#222222][/color]
[color=#222222]    } [/color][color=#222222][/color]
[color=#222222]  }[/color]

The entire if clause is redundant. You CAN'T get TO the if UNLESS Serial.available() IS > 0.

This code does NOTHING to determine that ALL characters have been received. Most likely, it will pickup a single character, then exit the while loop.

Then, it attempts to parse a 12-character string, even though it certainly does NOT have 12 characters to parse:

[color=#222222]  if (readString.length() >0) {[/color][color=#222222][/color]
[color=#222222]     Serial.println(readString);      [/color][color=#222222][/color]
[color=#222222]     Sumbu_X = readString.substring(0, 4);[/color][color=#222222][/color]
[color=#222222]     Sumbu_Y = readString.substring(4, 8);[/color][color=#222222][/color]
[color=#222222]     Sumbu_Z = readString.substring(8, 12);[/color]

Read the tutorial on how to properly read and parse Serial data. The existing code is a perfect example of how NOT to do it...

Regards,
Ray L.

WHY THE HE11 DOES COPY/PASTE ON TEXT IN THE EDITOR INSERT ALL THOSE D@MNED COLOR CODES!!!

Robin2:
Did you try it? What happened?

Arduinos are great for learning-by-doing.

...R

Yes, it works perfectly, retrieves 3 integers from the serial.

I will proceed with using that serial parsing method.

Edit: I re wrote the above program using the suggested serial parsing method and all problems I noted above are now solved. Now to expand the functionality even further than the original author.