2016-08-18 94 views
6

Dostaję danych przez BLE i chcę, aby przekształcić je w wartości po przecinku, jednak podejrzewam coś złego, ponieważ zakres wartości wydaje się być niepoprawnySwift - konwersja danych do wartości dziesiętnych

od BLE otrzymam characteristic.value

24ffa400 6d08fcff fffffbff 0d001500 5eff

która jest skonstruowana maily wartości IMU.

kiedy próbuję przekonwertować pierwsze dwa bajty, w tym przykładzie 24ff, który jest wartością osi X przyspieszenia, otrzymuję wartość z zakresu 1000-30000 (wprowadziłem pewien dynamiczny ruch do czujnika, aby zobaczyć, jak zmienia się wartość).

To musi być źle, ponieważ docs powiedzieć, że skala przyspieszenia jest ±16G Istnieją dwa ważne informacje:

sekwencji bajtów w ramce idzie w następujący sposób: [LSB, MSB]

wartości 16bit i wykorzystuje dwa uzupełnienie

ten sposób przekonwertować dane do wartości dziesiętnych:

class func getAccelerometerData(value: NSData) -> [String] { 

    let dataFromSensor = dataToSignedBytes8(value) 
    let bytes:[Int8] = [dataFromSensor[1], dataFromSensor[0]] 

    let u16 = UnsafePointer<Int16>(bytes).memory 
    return([twosComplement(u16)]) 
} 

class func twosComplement(num:Int16) -> String { 
    var numm:UInt16 = 0 
    if num < 0 { 
     let a = Int(UInt16.max) + Int(num) + 1 
     numm = UInt16(a) 
    } 
    else { return String(num, radix:10) } 
    return String(numm, radix:10) 
} 

Przypuszczam, że powinienem uzyskać wartości z zakresu < -16: 16> zamiast wielkich wartości, o których wspomniałem powyżej, co jest nie tak z moim podejściem?

góry dzięki

EDIT: Brakujące metoda realizacja

class func dataToSignedBytes8(value : NSData) -> [Int8] { 
    let count = value.length 
    var array = [Int8](count: count, repeatedValue: 0) 
    value.getBytes(&array, length:count * sizeof(Int8)) 
    return array 
} 

Odpowiedz

2

Biorąc pod uwagę niektóre NSData,

let value = NSData(bytes: [0x24, 0xff, 0xa4, 0x00] as [UInt8], length: 4) 
print(value) // <24ffa400> 

można pobrać pierwsze dwa bajty [LSB, MSB] aby jako podpisana 16-bitowa liczba całkowita z

let i16 = Int16(littleEndian: UnsafePointer<Int16>(data.bytes).memory) 
print(i16) // -220 

ilość ta mieści się w zakresie -32768 .. 32767 i musi być skalowane w celu pływający zakresie temperatury zgodnie ze specyfikacją urządzenia, na przykład:

let scaled = 16.0 * Double(i16)/32768.0 
print(scaled) // -0.107421875 

scaled jest Double i mogą być przekształcone w ciągu z String(scaled) lub przy użyciu NSNumberFormatter.

+0

Więc mogę pominąć funkcję dwóch dopełnień? Czy powinienem również zwracać uwagę na zamówienie LSB i MSB? teraz nie czegoś jak to klasę 'funkcjono getAccelerometerData (wartość: NSData) -> dwukrotnie { pozwolić dataFromSensor = dataToSignedBytes8 (wartość) pozwolić bajty [int8] = [dataFromSensor [0] dataFromSensor [1]] let i16 = UnsafePointer (bajty) .memory powrót (16,0 * Podwójny (i16)/32768.0) ' i wygląda na to, że działa, czy mógłbyś potwierdzić kod? – DCDC

+0

@DCDC: Nie wiem, co robi twoja dataToSignedBytes8, co wydaje się niepotrzebne, możesz uzyskać dostęp do danych bezpośrednio, tak jak to pokazano. W przeciwnym razie wygląda to poprawnie. Zakłada się, że 'Int16' używa mało-endianowej reprezentacji pamięci, co ma miejsce w przypadku wszystkich obecnych urządzeń iOS. –

+0

@DCDC: Zaktualizowałem kod, aby uczynić bajt-porządek bezpiecznym! –