Go Down

Topic: read string and split it! (Read 2153 times) previous topic - next topic

mkanon

i have a unity -> arduino setup. my unity code :
Code: [Select]

int left = System.Convert.ToInt32(Nite3.offsetleftarm);
int right = System.Convert.ToInt32(Nite3.offsetrightarm);
_SerialPort.Write(left+"-"+right);


on the sketch-side
Code: [Select]

void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo2.attach(10);
  //Serial.begin(9600); // start serial port
  Serial.begin(57600); // start serial port

}


// Function to read a string from the serialport and store it in an array
void readSerialString (char *strArray)
{
  int i = 0;
  if(Serial.available()){               
    while (Serial.available()) {       
      strArray[i] = Serial.read();                                        
      i++;        
    }
  }
  serInStringLength=i;



int serReadInt()
{
int i, serAva;                           // i is a counter, serAva hold number of serial available
char inputBytes [7];                 // Array hold input bytes
char * inputBytesPtr = &inputBytes[0];  // Pointer to the first element of the array
     
if (Serial.available()>0)            // Check to see if there are any serial input
{
   delay(5);                              // Delay for terminal to finish transmitted
                                              // 5mS work great for 9600 baud (increase this number for slower baud)
   serAva = Serial.available();  // Read number of input bytes
   for (i=0; i<serAva; i++)       // Load input bytes into array
     inputBytes[i] = Serial.read();
   inputBytes[i] =  '\0';             // Put NULL character at the end
   return atoi(inputBytesPtr);    // Call atoi function and return result
}
else
   return -1;                           // Return -1 if there is no input
}



// Function to find out wether the array is empty or not
boolean isStringEmpty(char *strArray)
{
  if (strArray[0] == 0) return true;
  else return false;
}

void loop () {
   int a = serReadInt();
    //a is now the complete string(int)..
    myservo.write(a);

    // how do i cut to b?
    myservo2.write(b);
}   


Because of me being total new... i really don't have a an idea how to split the char i got from unity.. the above setup without the b was with one value! worked well!! the setup in sketch also works with int and it should work with char/string

robtillaart

Code: [Select]

if (Serial.available()>0)            // Check to see if there are any serial input
{
   delay(5);                              // Delay for terminal to finish transmitted
                                              // 5mS work great for 9600 baud (increase this number for slower baud)
   serAva = Serial.available();  // Read number of input bytes
   for (i=0; i<serAva; i++)       // Load input bytes into array
     inputBytes[i] = Serial.read();
   inputBytes[i] =  '\0';             // Put NULL character at the end
   return atoi(inputBytesPtr);    // Call atoi function and return result
}
else
   return -1;                           // Return -1 if there is no input
}


your code is opportunistic, it assumes that if the are bytes available that ALL bytes are available. Suppose unity needs to send 645 (3 bytes) and the Arduino checks Serial.Available() when only one has arrived, then the code will return 6 and in the next call maybe 45.
This is because communication takes time and serial communication is asynchronuous, meaning that you are never sure when the bytes arrive. Fortunately there is a simple trick to solve this and that is read characters until you read some marker that indicates end of field. When sending numbers this can be a space, a tab, a return (\n), or a comma, in fact any character except digits of course.
Another way it can be solved is to have the numbers a fixed length, but the risk is if you miss one byte you're out of sync and all data is wrong. The method with a marker is more robust as it syncs after any integer.

To more robustly read ints from serial try this code (not tested) it reads max 1 char per iteration and tests if it is a digit if so its adds it to the return value which is gradually build up. If the read char is no digit it returns the build up value; Furthermore it has a timeout build in if the serial communication fails.

Code: [Select]

int serReadInt()
{
  unsigned long start = millis();
  int val = 0;
  char c;
  while (true)
  {
    if (millis() - 5000 > start ) return -1;  // timeout
    if ( Serial.available() > 0 )
    {
      c = Serial.read();
      if ( '0' <= c && c < '9') val *= 10 + (c - '0');
      else return val;       
    }
  }


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up