Reputation: 226
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
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