Getting a Serial Array over Serial

so i got my droid to send the gyro data over bluetooth to my arduino in a byte array of 3 elements. first character is the flag (capital letter, for the gyro data the flag is 'A') followed by a floating point then a semicolon thn the next floating point and a semicolon then the last floating point that an unprintable character (the ASCII number for it is 19)

note: my bluetooth module is pluged into pins 14 & 15 (yeah i have a mega) so instead of it being "Serial" its "Serial3"

And...?

well i sorta dont know how to get the info, and sort it into its correct locations.

heres what i got so far.

char flag;
char inByte;

bool neg = false;

int cnt;
double state;

int gyro[3];

void setup() 
{
  Serial.begin(57600);
  Serial3.begin(57600);
}

void loop() 
{
  if (Serial3.available() > 0)
  {
    inByte = Serial3.read();

    if (inByte == 'A')
    {
      flag = 'A';

      state = 1;
    }
    else if (state == 1)
    {
      cnt = 1;

      if (inByte == '-')
        neg = true;
      else
        neg = false;

      if ((inByte >= '0' && inByte <= '9') || inByte == '.')
      {
        if (cnt == 1)
        {
          gyro[int(state) - 1] = inByte - 48;
          cnt++;
        }
        else if (cnt == 2)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 1.5;
        }
        else if (cnt == 3)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 1.5;
        }
      }
    }
    else if (state == 1.5 && inByte == ';')
      state == 2;
    else if (state == 2)
    {
      cnt = 1;

      if (inByte == '-')
        neg = true;
      else
        neg = false;

      if ((inByte >= '0' && inByte <= '9') || inByte == '.')
      {
        if (cnt == 1)
        {
          gyro[int(state) - 1] = inByte - 48;
          cnt++;
        }
        else if (cnt == 2)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 2.5;
        }
        else if (cnt == 3)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 2.5;
        }
      }
    }
    else if (state == 2.5 && inByte == ';')
      state == 3;
    else if (state == 3)
    {
      cnt = 1;

      if (inByte == '-')
        neg = true;
      else
        neg = false;

      if ((inByte >= '0' && inByte <= '9') || inByte == '.')
      {
        if (cnt == 1)
        {
          gyro[int(state) - 1] = inByte - 48;
          cnt++;
        }
        else if (cnt == 2)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 3.5;
        }
        else if (cnt == 3)
        {
          if (inByte != '.')
          {
            gyro[int(state) - 1] = (gyro[int(state) - 1] * 10) + (inByte - 48);
            cnt++;
          }
          else
            state = 3.5;
        }
      }
    }
    else if (state == 3.5 && inByte == 19)
    {
      Serial.print("X: ");
      Serial.print(gyro[0]);

      Serial.print("Y: ");
      Serial.print(gyro[1]);

      Serial.print("Z: ");
      Serial.println(gyro[2]);
    }
  }
}

heres what i got so far.

Aside from the fact that you could be stuffing the data into an array, using strtok to parse the values, and atoi to convert the values to integers, what is the problem?

You're transmitting "floats", and assigning the result to "int"s?

Implementing an FSM with floating-point states is not the best idea.

Aside from the fact that you could be stuffing the data into an array, using strtok to parse the values, and atoi to convert the values to integers, what is the problem?

do you have an example? or something like that?

Have a look at this thread.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273230655/
It shows how to receive the serial data as a string.

Once you have the string, using strtok is pretty simple. There are examples on the forum. Each token returned by strtok can be converted to an integer using atoi or to a float using atof.

wow, thank you very much. almost there, it get the first value correctly. how do i get the other 2 (i care about those other 2 because those are the important ones)

char inData[35];
int index;
boolean started = false;
boolean ended = false;
void setup(){
Serial3.begin(57600);
Serial.begin(57600);
}
void loop()
{
   while(Serial3.available() > 0)
   {
       char aChar = Serial3.read();
       if(aChar >= 'A' && aChar <= 'Z')
       {
           started = true;
           index = 0;
           inData[index] = '\0';
       }
       else if(aChar == 19)
       {
           ended = true;
       }
       else if(started)
       {
           inData[index] = aChar;
           index++;
           inData[index] = '\0';
          }
   }
  

   if(started && ended)
   {
       // Convert the string to an integer
       int inInt = atoi(inData);
          Serial.println(inInt);
       // Use the value

       // Get ready for the next time
       started = false;
       ended = false;

       index = 0;
       inData[index] = '\0';
  
 }
}

So, what ends up in inData, when started and ended are both true?

That string should contain all the values. You need to pass that string to strtok to parse it.

yeah, it prints out 342.14063;1.84375;48.453125 (there are 5 boxes on the end and [box]5 filling the space before it)

i dont exactly understand how strtok works or what it does, or how to use it, sorry care to explain :confused:

char inData[32];
int index;
boolean started = false;
boolean ended = false;
void setup(){
  Serial3.begin(57600);
  Serial.begin(57600);
}
void loop()
{
  while(Serial3.available() > 0)
  {
    char aChar = Serial3.read();
    if(aChar >= 'A' && aChar <= 'Z')
    {
      started = true;
      index = 0;
      inData[index] = '\0';
    }
    else if(aChar == 19)
    {
      ended = true;
    }
    else if(started)
    {
      inData[index] = aChar;
      index++;
      inData[index] = '\0';
    }
  }


  if(started && ended)
  {
    // Convert the string to an integer
    int inInt = atoi(inData);
    for (int q = 0; q <= sizeof(inData);q++)
      Serial.print(inData[q]);
    Serial.println();
    Serial.print("X:");
    Serial.println(inInt);
    // Use the value

    // Get ready for the next time
    started = false;
    ended = false;

    index = 0;
    inData[index] = '\0';

  }
}

The inData variable is a string, since it is a NULL terminated array of characters. To get it's length, you use strlen, not sizeof.

The sizeof function tells you how big the array is, which is not the same thing as the number of characters in the array.

char *token = strtok(inData, ";"); // Find the 1st token delimited by ;
while(token)
{
   float num = atof(token); // Store this somewhere...

   token = strtok(NULL, ";") // Find the next token in the original string
}

ummm when i write the value to a servo, it spazzes out, like it gets to the location but it jumps back and forth around. i have another version of code and it does it even more, it jumps so much it never gets to the target value (in teh longer version).

#include <Servo.h>

char inData[34];
int index;
boolean started = false;
boolean ended = false;
int gyro [3];
Servo myservo;
void setup(){
  Serial3.begin(57600);
  Serial.begin(57600);
  myservo.attach(8);
}
void loop()
{
  myservo.write(map(gyro[1],30,-30,15,115));
  if(Serial3.available() > 0)
  {
    char aChar = Serial3.read();
    if(aChar >= 'A' && aChar <= 'Z')
    {
      started = true;
      index = 0;
      inData[index] = '\0';
    }
    else if(aChar == 19)
    {
      ended = true;
    }
    else if(started)
    {
      inData[index] = aChar;
      index++;
      inData[index] = '\0';
    }
  }


  if(started && ended)
  {
    // Convert the string to an integer
    for (int q = 0; q <= strlen(inData);q++)
      Serial.print(inData[q]);
      
    gyro[0] = atoi(strtok(inData, ";"));
    gyro[1] = atoi(strtok(NULL, ";"));
    gyro[2] = atoi(strtok(NULL, ";"));
    Serial.println();
    Serial.print("X:");
    Serial.print(gyro[0]);
    Serial.print(" Y:");
    Serial.print(gyro[1]);
    Serial.print(" Z:");
    Serial.println(gyro[2]);
    // Use the value

    // Get ready for the next time
    started = false;
    ended = false;

    index = 0;
    inData[index] = '\0';

  }
}

A few observations. First, this:

    for (int q = 0; q <= strlen(inData);q++)
      Serial.print(inData[q]);

is not the proper way to print a string.

A string is, by definition, a NULL-terminated array of characters. Well, the Serial.print() method is overloaded. One of the definitions allows printing a string:

   Serial.print(inData);

The advantage of using this method is that you can verify that the string is properly NULL-terminated.

Second, a bunch of characters appear in the serial monitor. What do they mean?

Serial.print("Echoing input: [");
Serial.print(inData);Serial.print("]\n");

This code clearly identifies what is being printed, and prints something just before and just after the data that is important. This lets you see that there are no extraneous characters.

Third, this code at the beginning of loop:

  myservo.write(map(gyro[1],30,-30,15,115));

is going to move the servo on every pass through loop. On the first pass, what is the value in gyro[1]? The Servo::write() method should not be called on every pass through loop. It needs to be called only when the value in gyro[1] changes.

Fourth, the range of numbers that are input to move the servo. Are they really in the range +30 to -30? Or, are they in the range -30 to +30?

Fifth:

    gyro[0] = atoi(strtok(inData, ";"));
    gyro[1] = atoi(strtok(NULL, ";"));
    gyro[2] = atoi(strtok(NULL, ";"));

While this code is great if the input is well formatted and tested, it is not really well suited for debugging. An extra character pointer variable takes just two bytes. Surely, your program is not that space constrained. With the extra character pointer variable, you can verify that the pointer is not NULL, after the call to strtok, before passing it to atoi.

Finally, the program did produce some output, didn’t it. Is that output too sensitive to share? We can help debug better the more information we have. The purpose of the Serial.print statements is to debug the program. We need to see that data, too.