I'm looking at interfacing a WIT motion HWT901B-232 10 axis Gyro with a CR1000, CR6, or CR800. The HWT901B-232 consists of a high precision gyroscope, accelerometer,
geomagnetic field and barometer sensor with a data rate of up to 200Hz.
Data output is hexadecimal, not ASCII and default baud is 9600. The sensor outputs data for time, acceleration, angle, magnetic, pressure, altitude, and quaternion.
Some data is transmitted as a low byte and high byte, and the two are combined into a signed short type data. ie acceleration output for the X-axis acceleration, data Ax is from AxL the low byte and AxH the high byte.
Ax = ((AxH<<8)|AxL)/32768*16g
where (g is Gravity acceleration, 9.8m/s2)
Note: AxH needs to be coerced into a signed short data and then shifted, and the data type of Data is also a signed short type so that it can represent negative numbers.
Sensor output for acceleration is in the following form:
0x55 0x51 AxL AxH AyL AyH AzL AzH TL TH SUM
Calculate formula:
ax = ((AxH<<8)|AxL)/32768*16g(g is Gravity acceleration, 9.8m/s2)
ay = ((AyH<<8)|AyL)/32768*16g(g is Gravity acceleration, 9.8m/s2)
az = ((AzH<<8)|AzL)/32768*16g(g is Gravity acceleration, 9.8m/s2)
Temperature calculated formular:
T = ((TH<<8)|TL)/100 ℃
SUM = 0x55+0x51+AxH+AxL+AyH+AyL+AzH+AzL+TH+TL
The other sensor outputs are similar.
Thoughts on the program:
'Declare a variable to hold the incoming data.
Public SerialHexData As String * 1000, Receive, NBytesReturned
...
SerialOpen (Com1,9600,0,0,1000)
...
I then have tried the following but have not been able to get this to work.
SerialInRecord (Com1,SerialIndest,&H5551,100,0,NBytesReturned,01)
I have also tried SerialIn to read in the Hex data with some success and I can see the data in the terminal, (W), and it's Hex, 55 51 00 03 07...
Hoping for a few hints to nudge me in the right direction, will post the code up when it's working as these low-cost Gyros may have a broad application and others might find a use.
Change your SerialOpen to use format 3 instead of format 0.
Also, change SerialInRecord to read in 9 bytes.
SerialInRecord (Com1,SerialIndest,&H5551,9,0,NBytesReturned,01)
Note that the two header bytes won't be included in SerialIndest. It is recommended to use the checksum to validate the data. You can use the CheckSum() instruction, but will need to add back in the value of the first two bytes to get the correct result.
To get the value of an individual byte, I suggest the ASCII() function. Use the third dimension on the string to specify which byte.
ASCII(SerialIndest(1,1,5)) 'Returns the value of the 5th byte in the string.
Thanks JDavis format 3 instead of 1 for the serial open definately makes a difference and the SerialInRecord's work:
SerialInRecord (Com1,SerialInTime,&H5550,9,0,NBReturnTime,01)
SerialInRecord (Com1,SerialInAccel,&H5551,9,0,NBReturnAccel,01)
SerialInRecord (Com1,SerialInAngular,&H5552,9,0,NBReturnAngular,01)
SerialInRecord (Com1,SerialInAngle,&H5553,9,0,NBReturnAngle,01)
SerialInRecord (Com1,SerialInMag,&H5554,9,0,NBReturnMag,01)
SerialInRecord (Com1,SerialInAtmos,&H5556,9,0,NBReturnAtmos,01)
SerialInRecord (Com1,SerialInQuat,&H5559,9,0,NBReturnQuat,01)
I then used MoveBytes to get the value of an individual byte as I think I need to keep the value as Hex to then do the next part witch involves the bit shift:
MoveBytes (HxL, 0, SerialInMag, 0, 1)
HexString = ""
LongVal = ASCII(HxL(1,1,1))
HexString = FormatLong (LongVal,"%02X")
HxL = HexString
MoveBytes (HxH, 0, SerialInMag, 1, 1)
HexString = ""
LongVal = ASCII(HxH(1,1,i))
HexString = FormatLong (LongVal,"%02X")
HxH = HexString
....
Next, some data is transmitted as a low byte and high byte, the two are then combined into a signed short type data. In the above the magnetic output for the x axis, Hx is calculated from HxL the low byte and HxH the high byte as follows:
Hx = ((AxH<<8)|AxL)/32768*16g
where (g is Gravity acceleration, 9.8m/s2)
From the manual, HxH is coerced into signed short data and then shifted, so that it can represent negative numbers.
So I think I use MoveBytes again to bit shift AxH? Then combine this with AxL? Then Hx should end up a signed float? Help doing this would also be greatly appreciated.
If you have multiple messages coming in on that one comport, you should be using 101 instead of 01 for the option on SerialInRecord.
If you use MoveBytes, you will need to use a Long as the destination. Then, you would have to do the math to get a floating point value.
Things can be simpler in your code this way:
Hx = (ASCII(SerialInAccel(1,1,1)) + (ASCII(SerialInAccel(1,1,2)) * 256) ) / 32768 * 16 * 9.8
Bit shifting is faster in the processing than doing the *256, but the math runs really fast anyway.