DCDC DCDC - 3 months ago 16
iOS Question

Swift - converting data to decimal values

I'm getting data via BLE and I want to convert them into decimal values, however I suspect I do something wrong because value range appears to be incorrect

from BLE I receive

characteristic.value


24ffa400 6d08fcff fffffbff 0d001500 5eff


which is constructed maily of IMU values.

when I try to convert the first two bytes, in this example
24ff
which is accelerometer X axis value, I get a value from range 1000-30000 (I introduced some dynamic movement to the sensor to see how the value is changing).

This must be wrong since docs say that accelerometer scale is
±16G

There are two more important information:


sequence of bytes in frame goes as follows: [LSB, MSB]

values are 16bit and utilizes two's complement


this is how I convert data into decimal value:

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)
}


I suppose I should obtain values from range <-16:16> instead of huge values I mentioned above, what is wrong with my approach?

Thanks in advance

EDIT:
Missing method implementation

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
}

Answer

Given some NSData,

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

you can retrieve the first two bytes in [LSB, MSB] order as a signed 16-bit integer with

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

This number is in the range -32768 .. 32767 and must be scaled to the floating point range as per the specification of the device, for example:

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

scaled is a Double and can be converted to a string with String(scaled), or using a NSNumberFormatter.