Hex data - how to read it?

Im reading a serial device (accelerometer) and it sends a block data via usb/serial. It comes in as binary and I am able to read the hex by this in the serial controller:

If Me.BytesAvailable > 0 Then
  OutputArea.AppendText( EncodeHex(Me.ReadAll) + EndOfLine.Windows)
End If

I am trying to get the values(dont need super accurate but is a plus) in positions 9-13 - anyone know how to do it? Please point me to some reading or help out?

I get something like this (with no spaces):
7E 00 1D 90 00 13 A2 00 41 91 65 7E FF FE C2 7F 00 01 03 FF E3 00 18 00 00 0F FF D2 00 3E 00 00 AB

The device maker shows this on the data sheet:
Frame Field Offset (Payload Section) Fixed Value(if any) Description
Header 0 0x7F Header to differentiate various type of packets
Node ID 1 0x00 Factory Default Node ID to differentiate up to 256 nodes in a network. User configural values
Firmware 2 – Used to determine firmware version programmed in the device
Battery Voltage MSB 3 – Sampled battery voltage of the device.Battery Voltage=((Battery Voltage MSB x 256+Battery Voltage LSB) x 0.00322 V
LSB 4 –
Packet Counter 5 – It is an 8-bit counter that increments with each packet transmission. It can be used to detect missing packets.
Sensor Type MSB 6 0x00 Two bytes to determine sensor type. It can be used in conjunction with Node ID to create sensor networks of up to 256 nodes for a single type of sensor and multiple such networks can coexist and can be differentiated in processing software on PC end
MSB 7 0x18
Reserved 8 0x00 For future use
Acceleration Data

9/X[0] – Accelerometer X-axis Data (16 bit Signed Output) Acceleration (mg) = X[0]<<8)+X[1]
10/X[1] –
11/Y[0] – Accelerometer Y-axis Data (16 bit Signed Output) Acceleration (mg) = Y[0]<<8)+Y[1]
12/Y[1] –
13/Z[0] – Accelerometer Z-axis Data (16 bit Signed Output)Acceleration (mg) = Z[0]<<8)+Z[1]

14/Z[1] – Temperature Data
15/T[0] – data (16 bit Signed Output) Temperature (°C) = (T[0]<<8)+T[1]
16/T[1] - Note: The temperature output gives the change in temperature between two readings and does not provide temperature of the sensor or environment.

There are 3 ways to do this:

  • Brute Force: Pull the byte values out of a string:
dim s as string = me.ReadAll
dim I as integer = (val(midb(s, 10)) * 256) + val(midb(s, 11))
  • MemoryBlock:
dim mb as MemoryBlock = me.ReadAll
dim I as integer = mb.UInt16Value(9)
  • Structure: define a structure that contains the fields as defined in the documentation, then access the value directly.
dim st as theStructure
st.StringValue = me.ReadAll
dim I as integer = st.XAxis

Refer to the documentation for guidance on the above.

Thank you Tim! I will be reading all I can. This gets me in the right areas. Much appreciated!

ugh. I cant seem to get this. If I use this kind of setup:
dim mb as MemoryBlock = me.ReadAll
dim I as integer = mb.UInt16Value(9)

Im actually using:
dim I as integer = mb.UInt16Value(25) since the docs say the 9 is offset in the payload and the whole mb.Size is 33.

I get this kind of output for the x,y,z pairs - not what I would expect looking at the same data in the mfg. app I see very small numbers, signed (like .002. -015, 0, 0, .016, .11)
X,Y,Z = 65280 x 57855 x 225 x 0 x 0 x 0
X,Y,Z = 0 x 0 x 65280 x 57855 x 225 x 0

Anyone have any idea how to read this kind of data?

Ok, 2 corrections. First, use mb.Int16Value instead of mb.UInt16Value, since you want a signed value. Second, set mb.LittleEndian = False. Then, it looks like the values are mg, so you may need to divide by 1000 to match what you’re seeing in the other program.

Thanks Tim! I did get the Int16 and the values are coming in signed. I set the LittleEndian to false and it didnt seem to affect the values. The thing is that I was able to see the packet counter in position 5. So, I am relatively sure Im getting the right spots for the 6 xyz value pairs. The thing is, if I take those Int16 values, set up some Doubles and divide the Int16s by 1000, the values dont seem to be what I would expect.

By accessing the Int16 at the position: mb.UInt16Value(25) , is that reading 16bits?

Yes, that is reading 16 bits. Are you sure you’re reading from the right location in the memoryblock?

Can you post a hex packet and the corresponding x,y,z accelerometer values from their software for that packet so I can double check the expected value before posting the code for you?

@Tim - yes its offset but im not exactly sure i am at the right position. I did get the counter in the doc as expected so counted up from there so i am pretty sure Im getting the right offset.

@Julian - this is also soooo very hepful!! Thank youa million!

@Julian, I will try but I cant access their app packets. Heres what I typically get from the unit in hex, while the unit is standing absolutely still:

If I use the memorey block method I do get values that change slightly when moving the unit but if I use your structure setup, the xyz values never change no matter f the unit is moving or not.

I should mention that using the memory block and putting the read values into a double prior to maniplulating them, I am almost certainly not accessing the bits correctly as I dont know what im doing too well but now having seen your structure I see the error of my ways! Thank you so much! So, I think the values in the struct method must be losing some accuracy due to the Int structs…

I am definately close here thanks to you guys!! I do love the struct setup so I will play with that today to see if I can get it working. Its nice and clear (dumb down) for me to understand it better!

so I havent moved the unit and run their app and heres what is displayed:
x: -0.031 y: -0.031 z: -0.031 - starting still
x: -0.843 y: 0.156 z: -0.015 - moving
x: 0.0 y: 0.0 z: -0.0116 - still fopr a couple of cycles

They have a moving graph with auto scaling thats fairly nice and the point is afic, one can see when the unit is moved slightly as compared to not moving relatively still data sets. Thats what Im after! I want to know when the thing is moving and whenits still - to monitor that unit’s activity.

Try redownloading https://www.dropbox.com/s/jlu8u61ys2saijr/TestSerialAccelerometerStructure.xojo_binary_project?dl=0

and see if that works, I switched the bytes around so they are in the correct format to be read directly from the struct

Packet structure taken from https://ncd.io/iot-wireless-asset-monitor-product-manual/ so it might not be 100%.

@Julian - again, huge thanks! This is pretty close but the values dont change when the device is moved. Wierd! I assume in this version youre just tapping the xyz[0] vals? which is fine but Im lost as to why theyre not changing. Always:XYZ :0, 4.095 , -11.776 no matter if the unit is still or moving a lot. I am running both the memory block style and your struct style inside the DAtaAvailable event of the serial controller so I am pretty sure the “p” packet struct is going out of scope and clearing each time through.

Thanks again - for doing so much to help!!

I added a 1 byte packet counter to the payload struct in position 5 - this seems to have shifted the data one byte and now looks pretty good. Now that I see I need to fill the hex string from the device …

Bingo! (i think ;))
PacketCtr: 235 XYZ :0, -0.031 , 0.125
PacketCtr: 241 XYZ :-0.031, -0.031 , 0.031
PacketCtr: 242 XYZ :0.312, 0.031 , -0.062
PacketCtr: 243 XYZ :0.312, -0.187 , -0.5
PacketCtr: 244 XYZ :-0.062, 0.031 , 0.062
PacketCtr: 245 XYZ :-0.125, -0.062 , -0.125
PacketCtr: 246 XYZ :0, -0.031 , -0.031
PacketCtr: 247 XYZ :0.343, 0.25 , -0.343
PacketCtr: 248 XYZ :-0.062, 0.156 , 0.281

@Julian & @Tim. very much appreciated! I hope I can help someone like this some time. :slight_smile:

Ah yes I missed the packet counter, well spotted, glad its working! I altered the download in case someone else uses the code.