Read accel data from a sensor

31 May 2015

Hi, I have a similar problem reading accel data from the sensor. I'm programmig in arm mbed compiler. My code is:

int main() { while(1) {

i2c.frequency(400000); char data_write[1]; data_write[0] = 0x01; OPERATION_MODE_ACCONLY; i2c.write(BNO055_OPR_MODE_ADDR, data_write,1);

wait(1); char data[2]; i2c.read(BNO055_I2C_ADDR2, data, 2);

wait(0.5); char data_2[2]; i2c.read(BNO055_I2C_ADDR1, data_2, 2);

i2c.read(0x29, data, 6); pc.baud (115200); pc.printf("Comienza el bucle\r\n"); pc.printf("aceleracion 1: %d\r\n", data[0]); pc.printf("aceleracion 2: %d\r\n", data[1]);

pc.printf("aceleracion 3: %d\r\n", data_2[0]); pc.printf("aceleracion 4: %d\r\n", data_2[1]);

} }

After reading accel data with i2c communication,: aceleracion 1 = 0 aceleracion 2 = 128 aceleracion 3 = 0 aceleracion 4 = 128.

It's always the same values.

What is wrong?

Thanks

31 May 2015

Please use the <<code>> and <</code>> tags around your posted code to keep it readable.

int main() { 

while(1) {
 i2c.frequency(400000);
 
 char data_write[1];
 data_write[0] = 0x01; //OPERATION_MODE_ACCONLY; 

 i2c.write(BNO055_OPR_MODE_ADDR, data_write,1);

 wait(1);
 
 char data[2];
 i2c.read(BNO055_I2C_ADDR2, data, 2);

 wait(0.5);

 char data_2[2];
 i2c.read(BNO055_I2C_ADDR1, data_2, 2);

 i2c.read(0x29, data, 6);

 pc.baud (115200);
 pc.printf("Comienza el bucle\r\n");
 pc.printf("aceleracion 1: %d\r\n", data[0]);
 pc.printf("aceleracion 2: %d\r\n", data[1]);
 pc.printf("aceleracion 3: %d\r\n", data_2[0]);
 pc.printf("aceleracion 4: %d\r\n", data_2[1]);

 }

}

There are multiple issues with this code. First, you dont need to set the I2C frequency and the serial baudrate again and again inside the while loop. Same for the declarations of the data_write, data and data_2 buffers. Declare them once outside the loop.

The final I2C read operation stores 6 bytes in the data buffer, which is only 2 bytes in size.

i2c.read(0x29, data, 6);

Why do you hardcode the slaveaddress 0x29, The other I2C operations use defines? The BNO055 has two possible I2C slaveaddresses 0101001b (0x29) and the alternative address 0101000b (0x28). However, this is given in the 7bit addressmode format. The mbed libs use the 8bit format and you must left shift the address by one bit, so either use 0x52 or 0x50 in the mbed I2C methods.

The first parameter in the I2C read/writes must be the device I2C slave address. Any specific internal registers for read or write must be set as part of the write message that you send first.

31 May 2015

Hi, I hardcode the slaveaddress and I set the I2C frequency inside the while loop because it's a test. I`ve changed the slave address and the values are the same.

int main()
{
    
        i2c.frequency(400000);
        i2c.start();
        pc.baud (115200);
        
        char data_write[1];
        char data[2];
        char data_2[2];
        
    while(1) {


        data_write[0] = 0x01;                               // OPERATION_MODE_ACCONLY;

        i2c.write(BNO055_OPR_MODE_ADDR, data_write,1);      // BNO055_OPR_MODE_ADDR = 0X3D

        wait(1);

        i2c.read(0x52, data, 2);                            // BNO055_I2C_ADDR2 = 0x29 --> 0x52

        wait(0.5);

        i2c.read(0x50, data_2, 2);                          // BNO055_I2C_ADDR1 = 0x28 --> 0x50
        
        pc.printf("Comienza el bucle\r\n");
        pc.printf("aceleracion 1: %d\r\n", data[0]);
        pc.printf("aceleracion 2: %d\r\n", data[1]);
        pc.printf("aceleracion 3: %d\r\n", data_2[0]);
        pc.printf("aceleracion 4: %d\r\n", data_2[1]);

    }
}

what specific internal registers for read or write do I need?

Thanks

31 May 2015

The device will only respond to one slaveaddress, either 0x52 or 0x50. Which one it is depends on the logic level on COM3 pin. See page 90 of the manual (table Table 4-7: I2C address selection). COM3 HIGH => 0x29 (ie 0x52 on mbed) or COM3 LOW => 0x28 (ie 0x50 on mbed).

I2C communication is shown on page 92 of manual. Make sure you have I2C pullup resitors installed. Delete the first i2c.start() in your code. It is not needed. I cant tell you which register you need, that depends on what you want to do. The user manual provides all the information on available registers and what they do for you.

To set the OPR_MODE register to value 0x01 use this code:

data_write[0] = BNO055_OPR_MODE_ADDR;   // BNO055_OPR_MODE_ADDR register = 0x3D
data_write[1] = 0x01;                                          // OPERATION_MODE_ACCONLY command bits
 
i2c.write ((BNO055_I2C_ADDR1 << 1), data_write, 2);     // select the register address and then write the value
                                                                                         // Assuming that I2C slaveaddress is 0x50

To read from a specific register first set the register and then read from it:

data_write[0] = BNO055_XXX_ADDR;   // Select the register
 
i2c.write( (BNO055_I2C_ADDR1 << 1), data_write, 1);     // select the register address you want
                                                            // Assuming that I2C slaveaddress is 0x50

i2c.read ((BNO055_I2C_ADDR1 << 1), data_2, 2);      // read byte from selected register and byte from the next register address.
                                                            // Assuming that I2C slaveaddress is 0x50

31 May 2015

Hi, I want read accel values, for example, X axe. COM3 is HIGH, then I read data from 0x29 address.

Now, my while loop is:

int main()
{

    i2c.frequency(400000);
    pc.baud (115200);

    char data_write[1];
    char data_x_l[2];
    char data_x_m[2];

    while(1) {

        /*
        data_write[0] = 0x01;                               // OPERATION_MODE_ACCONLY;

        i2c.write(BNO055_OPR_MODE_ADDR, data_write,1);      // BNO055_OPR_MODE_ADDR = 0X3D*/

        // WRITE
        data_write[0] = BNO055_OPR_MODE_ADDR;               // BNO055_OPR_MODE_ADDR register = 0x3D
        data_write[1] = 0x01;                               // OPERATION_MODE_ACCONLY command bits

        i2c.write ((0x52 << 1), data_write, 2);             // select the register address and then write the value
                                                            // Assuming that I2C slaveaddress is 0x52
        wait(1);


        //READ
        data_write[0] = 0x08;                               // Select the register

        i2c.write((0x52 << 1), data_write, 1);              // select the register address you want
                                                            // Assuming that I2C slaveaddress is 0x52

        i2c.read ((0x52 << 1), data_x_l, 2);                // read byte from selected register and byte from the next register address.
                                                            // Assuming that I2C slaveaddress is 0x52

        data_write[0] = 0x09;                               // Select the register

        i2c.write((0x52 << 1), data_write, 1);              // select the register address you want
                                                            // Assuming that I2C slaveaddress is 0x52

        i2c.read ((0x52 << 1), data_x_m, 2);                // read byte from selected register and byte from the next register address.
                                                            // Assuming that I2C slaveaddress is 0x52


        pc.printf("Comienza el bucle\r\n");
        pc.printf("aceleracion X L: %d\r\n", data_x_l[0]);
        pc.printf("aceleracion X L: %d\r\n", data_x_l[1]);
        pc.printf("aceleracion X M: %d\r\n", data_x_m[0]);
        pc.printf("aceleracion X M: %d\r\n", data_x_m[1]);

    }
} 

I'm working with a nrf51dk board. I can see I2C waves on the scope.

I2C i2c(p30,p7);

I2C pullup resitors are installed too.

Thanks and regards.

31 May 2015

You have declared data_write[] as array of 1 byte, but the i2c.write is sending 2 bytes. Change the size of data_write.

The slaveaddress is either (0x29 << 1) OR 0x52. Dont shift 0x52!

You select the first register to read from (0x08 in this case), the address is automatically incremented on each read.

int main()
{
 
    i2c.frequency(400000);
    pc.baud (115200);
 
    char data_write[2];
    char data_x[2];

    while(1) {
 
        // WRITE
        data_write[0] = BNO055_OPR_MODE_ADDR;               // BNO055_OPR_MODE_ADDR register = 0x3D
        data_write[1] = 0x01;                               // OPERATION_MODE_ACCONLY command bits
 
        i2c.write (0x52, data_write, 2);             // select the register address and then write the value
                                                            // Assuming that I2C slaveaddress is 0x52
        wait(1);
 
 
        //READ ACCEL_X in reg 0x08 (LSB) and 0x09 (MSB)
        data_write[0] = 0x08;                               // Select the starting register
 
        i2c.write(0x52, data_write, 1);              // select the starting register address you want
                                                            // Assuming that I2C slaveaddress is 0x52
 
        i2c.read (0x52, data_x, 2);                // read first byte from selected register and the next byte from the next register address.
                                                                 // registeraddresses are automatically incremented on each read
                                                            // Assuming that I2C slaveaddress is 0x52
 
 
        pc.printf("Comienza el bucle\r\n");
        pc.printf("aceleracion X L: %d\r\n", data_x[0]);
        pc.printf("aceleracion X M: %d\r\n", data_x[1]);
 
    }
} 

31 May 2015

Hi,

I'm using your code but both values are 0.

I'm using BNO055 Shuttle Board with the next pin connection:

NRF51 BNO055

P07 (SCL) 18 P30 (SDA) 17 VDD 1, 2 and 22 (i2c adr mode) GND 3

Rpull1 are connected between VDD and 18 Rpull2 are connected between VDD and 17

what can be wrong?

thanks for your help

31 May 2015

Sorry,

This is the pin connection:

NRF51-P07 with BNO055-18 (SCL). NRF51-P30 with BNO055-17 (SDA). NRF51-VDD with BNO055-1,2 and 22 (i2c adr mode). NRF51-GND with BNO055-3.

Rpull1 are connected between VDD and 18. Rpull2 are connected between VDD and 17.

what can be wrong?

thanks for your help

31 May 2015

You need to connect PS0 and PS1 to GND to activate the I2C interface. On the shuttleboard PS0 is pin 8 and PS1 is pin 9. They must also be connected to GND.

I did not check the datasheet in detail but note that the device is quite complex and some more register initialisations may be needed before it operates as you want.

01 Jun 2015

It works fine! thanks a lot!

02 Jul 2015

Just FYI, there is an Arduino-compatible code that allows use of most of the BNO055 functions as well as various boards with the BNO055 broken out available at Tindie:

https://www.tindie.com/products/onehorse/wearable-bno055-nano-board/

The code initializes the sensor for I2C, polls the data registers, and outputs properly scaled sensor data and quaternions to the serial monitor. Might be a good template for an mbed-compatible version.