Nightsd01
Nightsd01

Reputation: 226

How to Convert Float to NSData Bytes

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.

Upvotes: 0

Views: 1411

Answers (1)

Duncan C
Duncan C

Reputation: 131418

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.

Upvotes: 1

Related Questions