2015-03-12 2 views
0

Используя следующий код, я пытаюсь преобразовать три значения float в один объект NSData, который затем могу передать через последовательный порт.Как преобразовать float в NSData Bytes

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]; 

Проблема в том, что она не работает очень хорошо. Всякий раз, когда я использую функцию «sizeof()« C », он сообщает мне, что« dataPackage »составляет всего 8 байтов, хотя 3 значения float должны составлять 12 байтов. Я получаю данные с Arduino. Он видит, что байты входят, но они не могут быть разборчивы. Я не думаю, что это проблема на стороне Ардуины (но кто знает?).

Любая помощь будет оценена! Я не майор CS, просто биолог, и я никогда не изучал этот материал формально, поэтому мне жаль, если мой вопрос нелепо. Я провел несколько часов в поисках информации об этой проблеме и не нашел ничего, что помогло.

EDIT: Оказывается, этот код был полностью верным. Я сделал простую ошибку на стороне arduino, используя структуру вместо объединения, чтобы взять байты и преобразовать их обратно в поплавки.

Для тех, кто может быть в подобном затруднительном положении, успешный способ преобразования поплавки из байтов, поступающих из последовательного порта является следующее:

(в верхней части файла реализации)

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

(внутри петли)

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. 

Это, вероятно, не лучший или самый надежный способ передачи данных. Механизм исправления ошибок или структура пакета отсутствуют. Но он работает в крайнем случае. Я предполагаю, что вы, вероятно, захотите найти способ создания пакета данных вместе с хеш-байт, чтобы убедиться, что все данные верны с другой стороны, этот код не имеет ничего подобного.

+1

Можете ли вы объяснить более точно что вы ожидаете, и что на самом деле происходит? «они не разборчивы» где? когда? чем? Что такое '[self.serialPort dataPackage],' предназначено? –

+0

Да, Джош, спасибо за ответ! self.serialPort - это объект из сторонней библиотеки ORSSerialPort, которая позволяет легко осуществлять последовательный порт. В принципе, я ожидаю, что объект dataPackage будет иметь размер 12 байт, так как это комбинация трех 4-байтовых поплавков. Но, как ни странно, он всегда остается в 8 байт независимо от того, что я делаю. Когда я отправляю данные по порту, arduino получает некоторые данные, но нечувствителен. В принципе, что-то вроде 124235245 или -352245 или -426246245. Единственное, о чем я могу думать, это то, что NSData как-то не прав, так как это всего 8 байтов. – Nightsd01

+0

вы должны знать, что передача через последовательный порт может изменить порядок байтов и что ваше устройство может даже не использовать тот же двоичный формат, что и ваше устройство ... –

ответ

1

С кодом возникает множество проблем.

Во-первых, вы не хотите использовать stringValue в текстовом поле. Вам нужно свойство text, которое является строкой.

Таким образом, первая строка должна гласить так:

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

Во-вторых, в C, массив вещей является указателем. Тип данных

float combined[] 

и

float *combined 

идентична. Оба являются «указателями на float».

Так этот код:

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

не должен иметь амперсанд перед комбинированным. Должно быть:

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

В-третьих, важно то sizeof(combined), не sizeof(dataPackage).

Выражение sizeof(dataPackage) сообщит вам размер переменной dataPackage, который является указателем на объект NSData. Вы должны работать на 64-битном устройстве, где указатели составляют 8 байтов.

Чтобы проверить длину данных в вашем объекте NSData, вы хотите спросить его собственность длина:

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

Оба утверждения журнала должны отображаться значения 12.

+0

Вы абсолютно БРИЛЛИАНТ! Спасибо! Оказывается, все это было проблемой на стороне ардуинов, случайно используя конструкцию вместо объединения. Вы абсолютно правы по всем пунктам, хотя я очень ценю ваш ответ. Это всегда путало меня, когда я вижу людей, использующих ссылочный оператор с примитивными типами данных, такими как float, теперь вы отлично ответили на этот вопрос :) – Nightsd01

+0

Хорошо, кто изменил меня и почему? Если вы считаете, что мой ответ был испорчен, пожалуйста, сообщите мне, что с ним случилось. Я искренне пытаюсь предоставить полезную информацию. –

+0

Незначительный nitpick: 'float combination []' и 'float * объединены' имеют одно важное различие в этом случае. 'float combination []' здесь определяется компилятором как 'float combination [3]', так как значение инициализации имеет 3 элемента. 'sizeof()' правильно сообщает, что размер 12 ('sizeof (float) * 3'). Если он был объявлен как 'float combination *', 'sizeof (объединенный)' будет 8, это размер указателя на 64-разрядной OS X. В любом случае ваш код работает правильно (и я его поддерживает). –

Смежные вопросы