BNO055 with LJUDDotNet | LabJack
 

BNO055 with LJUDDotNet

12 posts / 0 new
Last post
vu
vhle's picture
BNO055 with LJUDDotNet

Hi, I was wondering if anyone has had any luck getting the Adafruit BNO055 IMU working with Dot Net wrapper?  I got other I2C devices working on the U3 but this device doesn't seem to respond to any of my write commands.

I saw in the T9 forum that someone got this device working with Lua script and Python and was hoping for some tips.

Thanks.

LabJack Support
labjack support's picture
The first thing to do is to

The first thing to do is to check the acknowledgements using LJ_chI2C_GET_ACKS. That will tell you whether or not the slave device is responding to it's address. If it is not sending an acknowledgement then we either have a hardware issue, or an incorrect address.

Verify the address: U-Series LabJack devices expect the address to be in the upper 7 bits. So, the address should be 0x52, 0x50 or 0x80 depending on the address configuration from table 4-7 in the BNO055 datasheet.

Our I2C appnote is a good place to start. It covers a lot of common pitfalls: https://labjack.com/support/app-notes/i2c

vu
vhle's picture
Thanks for the reply.  Yes, I

Thanks for the reply.  Yes, I'm actually able to get the unit to acknowledge itself with ACKS.  Where I'm running into issues is trying to read the accelerometer data.  The code makes it to the end, so my write functions are producing the correct ACKS, but my reads are all 0.  I'm not sure if there needs to be some initialization done.

Here is my current code.  I'm not sure what I'm missing, but any help or insight would be greatly appreciated.

'Reset everything
LJUD.ePut(u3.ljhandle, LJUD.IO.PIN_CONFIGURATION_RESET, 0, 0, 0)

'Configure the I2C communication.
'The address of the accelerometer is &h29, left shifted by 1 bit to produce &h50
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_ADDRESS_BYTE, &H50, 0, 0)

'SCL is FIO4
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SCL_PIN_NUM, 4, 0, 0)

'SDA is FIO5
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SDA_PIN_NUM, 5, 0, 0)

'Enable clock stretching
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_OPTIONS, 8, 0, 0)

'Set a max speed of about 130 kHz.
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SPEED_ADJUST, 0, 0, 0)

'Execute the requests on a single LabJack.
LJUD.GoOne(u3.ljhandle)

'Set to normal power mode
If write_2bytes(&H0, &H3E) = False Then Return

'Enable ndof mode
If write_2bytes(&HC, &H3D) = False Then Return

For i = 0 To 7
     numI2CBytesToWrite = 1
     writeArray(0) = &H20 + i
     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)

     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_GET_ACKS, 0, 0, 0)

     numI2CBytesToRead = 1
     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)

     'Execute the requests.
     LJUD.GoOne(u3.ljhandle)

     'Get the result of the write just to check for an error.
     LJUD.GetResult(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, 0)

     'Get the write ACKs and compare to the expected value.  We expect bit 0 to be
     'the ACK of the last data byte progressing up to the ACK of the address
     'byte (data bytes only for Control firmware 1.43 and less).  So if n is the
     'number of data bytes, the ACKs value should be (2^(n+1))-1.
     LJUD.GetResult(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_GET_ACKS, writeACKS)
     expectedACKS = Math.Pow(2, numI2CBytesToWrite + 1) - 1
     If (writeACKS <> expectedACKS) Then
          Return
     End If
    

     'need to store read data here, readarray(0), but value is always 0

Next

 

vu
vhle's picture
The address seems to be

The address seems to be respondsing correctly, because I'm getting the proper aknowledgements.  However each time I loop through and do the read for the accelerometer values, all I get are 0s.  The accelerometer works when I connect it to an Arduino and use the supplied code so I don't think it's hardware.

I'm wondering if there's some initialization code that I'm missing?  Here is my code, any suggestions would be greatly appreciated:

 

'Variable to store the read data
Dim outputStr As String = ""

'Reset labjack pins
LJUD.ePut(u3.ljhandle, LJUD.IO.PIN_CONFIGURATION_RESET, 0, 0, 0)

'Configure the I2C communication.
'The address of the accelerometer is &h29, left shifted by 1 bit to produce &h50
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_ADDRESS_BYTE, &H50, 0, 0)

'SCL is FIO4
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SCL_PIN_NUM, 4, 0, 0)

'SDA is FIO5
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SDA_PIN_NUM, 5, 0, 0)

'Enable Clock Stretching
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_OPTIONS, 8, 0, 0)

'Set speed of 130 kHz.
LJUD.AddRequest(u3.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SPEED_ADJUST, 0, 0, 0)

'Execute the requests on a single LabJack.
LJUD.GoOne(u3.ljhandle)

'Set to normal power mode.  If no acknowledgment, exit the function
If write_2bytes(&H0, &H3E) = False Then Return

'Enable ndof mode.  If no acknowledgment, exit the function
If write_2bytes(&HC, &H3D) = False Then Return

For i = 0 To 7
     numI2CBytesToWrite = 1
     writeArray(0) = &H20 + i
     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)

     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_GET_ACKS, 0, 0, 0)

     numI2CBytesToRead = 1
     LJUD.AddRequest(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)

     'Execute the requests.
     LJUD.GoOne(u3.ljhandle)

     'Get the result of the write just to check for an error.
     LJUD.GetResult(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, 0)

     'If no acknowledgment, exit the function
     LJUD.GetResult(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_GET_ACKS, writeACKS)
     expectedACKS = Math.Pow(2, numI2CBytesToWrite + 1) - 1
     If (writeACKS <> expectedACKS) Then
          Return
     End If

     LJUD.GetResult(u3.ljhandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, 0)

     'Build the output string
     outputStr = outputStr & readArray(0) & " "

Next

LabJack Support
labjack support's picture
The BNO055 boots up in config
The BNO055 boots up in config mode. In config mode, none of the sensors are active. Check out section 3.3 of the datasheet for more information:
 
 
vu
vhle's picture
But I thought writing &HC to

But I thought writing &HC to address &H3D was supposed to put the unit into NDOF mode?

LabJack Support
labjack support's picture
Does this function "write

Does this function "write_2bytes(&HC, &H3D) " actually write the bytes from right to left?

  • Have you tried reading the config register? Would be good to know that it is being written.
  • Have you tried reading the ID registers 0-3? That's a good way to check communication.
vu
vhle's picture
I finally got everything to

I finally got everything to work. The key was writing to the registers in config mode first and then switching over to ndof mode. 

After that, it's a matter of sending a write and read request.  Here's my code reading tempearture and the absolute roll, pitch and yaw degrees, in case anyone wants to reference it in the future.  Thanks for your help!

 

        Dim numI2CBytesToWrite As Integer
        Dim numI2CBytesToRead As Integer

        Dim writeArray(128) As Byte
        Dim readArray(128) As Byte

        Dim Iyaw, Iroll, Ipitch As Integer

        LJUD.ePut(lngHandle, LJUD.IO.PIN_CONFIGURATION_RESET, 0, 0, 0)

        LJUD.AddRequest(lngHandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_ADDRESS_BYTE, &H50, 0, 0)

        'SCL is FIO4
        LJUD.AddRequest(lngHandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SCL_PIN_NUM, ACC_SCL, 0, 0)

        'SDA is FIO5
        LJUD.AddRequest(lngHandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SDA_PIN_NUM, ACC_SDA, 0, 0)

        '8 = clock stretching, 4 = no stop when restarting, 2 = reset at start
        LJUD.AddRequest(lngHandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_OPTIONS, 12, 0, 0)

        'See description of low-level I2C function.  0 is max speed of about 130 kHz.
        LJUD.AddRequest(lngHandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.I2C_SPEED_ADJUST, 0, 0, 0)

        'Execute the requests on a single LabJack.
        LJUD.GoOne(lngHandle)

'**************************************************************************************************************************************
        'code to get the temperature
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H34
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

 

'**************************************************************************************************************************************
        'yaw msb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1B
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Iyaw = Convert.ToInt16(readArray(0)) << 8

 

        '**************************************************************************************************************************************
        'yaw lsb.  1 degree = 16 lsb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1A
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Iyaw = Iyaw + readArray(0)
        Iyaw /= 16

 

        '**************************************************************************************************************************************
        'roll msb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1D
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Iroll = Convert.ToInt16(readArray(0)) << 8

        '**************************************************************************************************************************************
        'roll lsb.  1 degree = 16 lsb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1C
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Iroll = Iroll + readArray(0)
        Iroll /= 16
 

       '**************************************************************************************************************************************
        'pitch msb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1F
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Ipitch = Convert.ToInt16(readArray(0)) << 8


        '**************************************************************************************************************************************
        'pitch lsb.  1 degree = 16 lsb
        numI2CBytesToWrite = 1
        numI2CBytesToRead = 1

        writeArray(0) = &H1E
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_WRITE, numI2CBytesToWrite, writeArray, 0)
        LJUD.AddRequest(lngHandle, LJUD.IO.I2C_COMMUNICATION, LJUD.CHANNEL.I2C_READ, numI2CBytesToRead, readArray, 0)
        LJUD.Go()

        Ipitch = Ipitch + readArray(0)
        Ipitch /= 16

 

vu
vhle's picture
Hi,  we've been getting

Hi,  we've been getting random system access violation errors with this code.  Sometimes the code runs fine for a few days, other times it stops after a few hours.

Do you know if there are any issues running i2c code this way or with the Dot net wrapper in general?

LabJack Support
labjack support's picture
For all your AddRequest calls

For all your AddRequest calls that write or read the arrays, change them to use the AddRequestPtr function and that will likely solve the access violation errors. AddRequest is a bit of an old function and is not 64-bit application safe when passing arrays/pointers to the x1 parameter. It is based on 32-bit pointer addresses, and will cut off the upper 32-bits of an address that can lead to memory related errors. Likely when the array's address is above a 32-bit value you see the crash, AddRequestPtr, and other Ptr related functions, are both 32-bit and 64-bit pointer address safe.

Otherwise, your write/read arrays look large enough and shouldn't cause an issue.

vu
vhle's picture
thanks for the suggestion, i

thanks for the suggestion, i will give it a try.  do you know if i also need to put a sleep in the thread to delay things a bit between each go request?

LabJack Support
labjack support's picture
Additional software delays

Additional software delays between Go operations are not needed for U3 operations. Once the Go finishes and you retrieve your results/data, you are ready for the next Go requests.