0
votes

Using the following code, I am attempting to convert three float values into a single NSData object, which I can then transmit over a serial port.

    float kP = [[self.kPTextField stringValue] floatValue];
    float kI = [[self.kITextField stringValue] floatValue];
    float kD = [[self.kDTextField stringValue] floatValue];
    float combined[] = {kP, kI, kD};

    NSData *dataPackage = [NSData dataWithBytes:&combined length:sizeof(combined)];

    [self.serialPort sendData:dataPackage];

The problem is that it doesn't seem to work very well. Whenever I use the "sizeof()" C function, it tells me that the "dataPackage" is only 8 bytes, even though 3 float values should total 12 bytes. I am receiving the data with an Arduino. It sees the bytes coming in, but they aren't legible at all. I don't think it's a problem on the Arduino side of things (but who knows?).

Any help would be appreciated! I'm not a CS major, just a bio major, and I've never learned this stuff in a formal way so I am sorry if my question is ridiculous. I've spent several hours searching the net about this problem and haven't found anything that helped.

EDIT: It turns out this code was completely correct. I made a simple mistake on the arduino side of things by using a struct instead of a union to take the bytes and convert them back into floats.

For others who may be in a similar predicament, a successful way to convert floats from bytes coming out of the serial port is the following:

(at top of implementation file)

union {
  float pidVals[3];
  byte bytes[12];
} pidUnion;

(inside loop)

if (Serial.available() > 11) {

  for (int i = 0; i < 12; i++) {
    pidUnion.bytes[i] = Serial.read();
  }

}

//Now, you can get access to all three floats of data using pidUnion.pidVals[0], pidUnion.pidVals[1], etc.

This probably isn't the best or most reliable way to transmit data. There is no error-correcting mechanism or packet structure. But it does work in a pinch. I imagine you would probably want to find a way to create a packet of data along with a hash byte to make sure all of the data is correct on the other side, this code doesn't have any of that though.

1
Can you explain more precisely what you're expecting to happen and what actually happens? "they aren't legible" where? when? by what? What is [self.serialPort dataPackage]; meant to do? - jscs
Yes, Josh, thanks for the response! self.serialPort is an object from a third-party library called ORSSerialPort that allows easy serial port communication. Basically, I'm expecting the "dataPackage" object to be 12 bytes large, since it is the combination of three 4-byte floats. But strangely, it always stays at 8 bytes no matter what I do. When I send the data over the port, the arduino receives some data but it is non-sensical. Basically, something like 124235245 or -352245 or -426246245. The only thing I can think of is that the NSData somehow isn't right since it is only 8 bytes. - Nightsd01
you should be aware that transmitting over the serial port can change the byte order, and that your device might not even use the same binary format as your device... - Grady Player

1 Answers

1
votes

There are multiple problems with your code.

First, you don't want to use stringValue on a text field. You want the text property, which is a string.

So the first line should read like this:

float kP = [self.kPTextField.text floatValue];

Second, in C, an array of things is a pointer. The data type of

float combined[]

and

float *combined

is identical. Both are "pointer to float".

So this code:

NSData *dataPackage = [NSData dataWithBytes:&combined 
  length: sizeof(combined)];

Should not have an ampersand in front of combined. It should read:

NSData *dataPackage = [NSData dataWithBytes:combined 
  length: sizeof(combined)];

Third, what matters is sizeof(combined), not sizeof(dataPackage).

The expression sizeof(dataPackage) will tell you the size of the variable dataPackage, which is a pointer to an NSData object. You must be running on a 64 bit device, where pointers are 8 bytes.

To test the length of the data in your NSData object, you want to ask it with the length property:

NSLog(@"sizeof(combined) = %d", sizeof(combined)";
NSData *dataPackage = [NSData dataWithBytes:&combined 
      length: sizeof(combined)];
NSLog(@"dataPackage.length = %d", dataPackage.length";

Both log statements should display values of 12.