Using IOKit/ioctl in Objective-C to send data to Arduino does not work.

I am trying to send color from my app running on MAC to Arduino. This is my Arduino Code

const int pins[3] = {
  8, 9, 10};

void  setup() {
  Serial.begin(9600);
  for (int i=0; i<3; i++) {
    pinMode(pins[i], OUTPUT); // init pin for channel
  }
}

void loop() {
  int color;
  //Wait until we have the start byte)
  if(Serial.available()>0)
  {
  int val=Serial.parseInt();
  //Check we're starting at the right place
  if (val == 85) {
    analogWrite(8, 200);
    Serial.write(val);
    //Wait until we have the start byte)
    while (Serial.available() < 1) { }
    val=Serial.parseInt();
    if (val == 170) {
      Serial.write(val);
      //  Ensure that we have 3 data bytes
      while (Serial.available() < 3) { }
      for (int i=0; i<3; i++) {
        val = Serial.parseInt();
        Serial.write(val);
        color = constrain(val, 0, 255); 
        analogWrite(pins[i], color);
      }
    }
  }
  }
}

Now, when I use the Arduino Serial Monitor and type in a string like "85,170,255,255,255" it all works, LED light up, it all is fine. However, when I try to use IOKit to send data from my mac I run in to problems. This is code on my mac:

    uint8_t data[5];
    data[0] = 85;
    data[1] = 170;
    data[2] = color.red*255;
    data[3] = color.green*255;
    data[4] = color.blue*255;
    if(_serialFileDescriptor!=-1) {
		write(_serialFileDescriptor, &data, 5);
	}

I initialized serial port, I checked that serial port is woking by doing: write(_serialFileDescriptor, "any random string to see if data gets sent", 20); and then checking if it was received by

if(Serial.available()>0)
 {
  int val=Serial.parseInt();
  analogWrite(8, 200); //light up the LED to see if anything got sent
  Serial.write(val);
}

Data definitely gets sent through but it is different from what it is supposed to be. For example, when I send 85, reading data back on mac from the output of Serial.write(val); gives me "<"(which is ASCII for 60). I am confused and stuck, it was a week and I still can not figure it out. Thank you.

write(_serialFileDescriptor, "any random string to see if data gets sent", 20);

You send a string, then call:

if(Serial.available()>0)
 {
  int val=Serial.parseInt();
  analogWrite(8, 200); //light up the LED to see if anything got sent
  Serial.write(val);
}

This makes me think that you haven't a clue what parseInt() does.

This:

    uint8_t data[5];
    data[0] = 85;
    data[1] = 170;
    data[2] = color.red*255;
    data[3] = color.green*255;
    data[4] = color.blue*255;
    if(_serialFileDescriptor!=-1) {
		write(_serialFileDescriptor, &data, 5);
	}

Is sending 5 bytes, in binary. Then this:

  int val=Serial.parseInt();

is expecting a string. Again, I don't think you have a clue what you are sending or how you should be reading it on the Arduino end.

If you are sending strings that do not contain numeric digits, don't expect parseInt() to properly deal with that crap.

If you are sending binary data, do not expect a function that expects ASCII data to deal with it.

Serial.read() returns an int, but the high order byte is only used to indicate an error. If there is no error, the high order byte is 0, so it can be discarded. The low order byte will then be one of the 5 bytes you sent. Repeat that 4 more times as the other 4 bytes arrive.

Of course, sending binary data is not a good idea, since bytes can get lost/corrupted, and getting back in sync is nearly impossible.

Thanks for your comment. I didn't realize that. I changed my objective-c code to:

    int data[5];
    data[0] = 85;
    data[1] = 170;
    data[2] = color.red*255;
    data[3] = color.green*255;
    data[4] = color.blue*255;
    NSString *string=[NSString stringWithFormat:@""];
    for (int i=0; i<5; i++) {
        string = [string stringByAppendingString:[[NSNumber numberWithInt:data[i]]stringValue]];
        string = [string stringByAppendingString:@","];
    }
    char *charData = [string UTF8String];
    if(_serialFileDescriptor!=-1) {
		write(_serialFileDescriptor, charData, 5);
	}

So it should now be sending a string, but again, it does not work and I am not sure how can I track my mistake.

    data[0] = 85;

As a string, this will be two characters.

    data[1] = 170;

Three more, plus one for the comma between them. We're up to 6 characters.

    data[2] = color.red*255;
    data[3] = color.green*255;
    data[4] = color.blue*255;

As strings, these now range between 1 and 3 characters each (assuming that color's components are floats). With the separators, the string is now between 11 and 17 characters long.

    if(_serialFileDescriptor!=-1) {
		write(_serialFileDescriptor, charData, 5);

So, we send the first 5. I'm sure that there is a good reason for that, but, for the life of me, I can't see what that reason is.

Nor, of course, can I see your current Arduino code.

So, we send the first 5. I'm sure that there is a good reason for that, but, for the life of me, I can't see what that reason is.

Thanks for pointing that out. The only reason I am sending the first five is my own stupidity. I meant to be sending all 17
Bytes. Thank you.

I meant to be sending all 17 Bytes.

I hope you mean all the chars in the string, not all 17 bytes. The string may not be that long. You should get it's actual length.