12-19-2019 09:49 AM - edited 12-19-2019 09:50 AM
I'm not able to successfully load init data into BMI270 chip using the code below. Since maximum bytes is 255, I load 32 bytes at the time. I get 0x02 as a result from reading 0x21 (status). I do not have any available SPI ports.
These are the first register readouts:
24200010000000000000000000000000000000000000000026960101000000000002adff00008000800
242000100000000000000000000000000000000000000000fcc40100000000000002310000008000800
242000100000000000000000000000000000000000000000c7f30100000000000002310000008000800
242000100000000000000000000000000000000000000000a222020000000000000200800000800080
2420001000000000000000000000000000000000000000007551020000000000000200800000800080
Any obvious errors? Greatful for any hints or trixes.
uint16_t i;
uint16_t j;
uint32_t err_code;
uint8_t d[33];
uint32_t addr;
nrf_delay_us(500);
bmi270_write(BMI2_PWR_CONF_ADDR, 0x00); // Power on
nrf_delay_us(500);
bmi270_write(BMI2_CMD_REG_ADDR, 0xb6); // Reset
nrf_delay_ms(500);
bmi270_write(BMI2_INIT_CTRL_ADDR, 0x00); // init start
nrf_delay_us(500);
for(i = 0; i < 256; i++)
{
bmi270_write(BMI2_INIT_ADDR_0, 0);
bmi270_write(BMI2_INIT_ADDR_1, i);
d[0] = BMI2_INIT_DATA_ADDR;
addr = i << 5;
for(j = 0; j < 32; j++)
{
d[j+1] = bmi270_config_file[addr + j];
}
err_code = nrf_drv_twi_tx(&m_twi, BMI2_I2C_PRIM_ADDR, d, 33, false);
nrf_delay_us(500);
}
nrf_delay_ms(500);
bmi270_write(BMI2_INIT_CTRL_ADDR, 0x01);
nrf_delay_ms(500);
bmi270_write(BMI2_PWR_CONF_ADDR, 0x00); // Power on
nrf_delay_us(500);
bmi270_write(BMI2_PWR_CTRL_ADDR, 0x0e); // Accelerometer and gyroscope on
nrf_delay_us(500);
bmi270_write(BMI2_FIFO_CONFIG_1_ADDR, 0x00); // FIFO off
nrf_delay_us(500);
bmi270_write(BMI2_PWR_CTRL_ADDR, 0x0e); // Accelerometer and gyroscope on
bmi270_write(BMI2_ACC_CONF_ADDR, 0xbb); // Performance, Avg32, 100Hz
bmi270_write(BMI2_ACC_RANGE_ADDR,0x00); // Range +- 2g
bmi270_write(BMI2_GYR_CONF_ADDR, 0xcb); // Performance, normal operation, 200Hz
bmi270_write(BMI2_GYR_RANGE_ADDR, 0x04); // Gyre range +- 125dps
bmi270_write(BMI2_FIFO_DOWNS_ADDR, 0x00); // Filtering off
bmi270_write(BMI2_FIFO_CONFIG_1_ADDR, 0xd0); // Store acc and Gyro in FIFO
12-19-2019 04:16 PM
I'm also having such problem. Please solve this asap!
12-23-2019 09:54 AM - edited 12-23-2019 10:16 PM
It seems like I've managed to make it work. These are the necessary steps:
Implement the i2c write function. I used pigpio library which has exactly what we need: i2cWriteI2CBlockData. I've seen this function in many libraries - it's pretty common.
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length) {
/* Write to registers using I2C. Return 0 for a successful execution. */
//int i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)
int ret = i2cWriteI2CBlockData(i2cHnd, reg_addr, (char *) reg_data, length);
if (ret != 0) {
printf("*** ERROR in i2c_reg_write %d\n", ret); // do your error handing thing here
return 1;
}
return 0;
}
Implement the i2c read function. I stopped experimenting with the details of read function immediately when this produced good results. Possibly the i2cReadI2CBlockData would work... But instead of that this one just increments the register address and the position in the resulting buffer. Important to undestand that with this approach you won't be able to read back the freshly written config data. That has to be done through the BMI2_INIT_DATA_ADDR register in combination with BMI2_INIT_ADDR_0 and BMI2_INIT_ADDR_1. tldr, this one works.
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {
/* Read from registers using I2C. Return 0 for a successful execution. */
uint16_t count = 0;
int res;
while (count < length) {
res = i2cReadByteData(i2cHnd, (reg_addr + count));
if (res < 0) {
printf("*** ERROR in i2c_reg_read %d\n", res);
return 1;
}
reg_data[count] = (uint8_t)(res & 0xff);
count++;
}
return 0;
}
EDIT: My first tests validate that i2cReadI2CBlockData can be used also.
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {
int ret = i2cReadI2CBlockData(i2cHnd, reg_addr, (char *)reg_data, length);
return (ret > 0) ? 0 : 1; // all good
}
Then implement the delay_us( uint32_t period ) function. I used the nanosleep from #include <time.h>. The delay_us function's period - after converting it - ends up here.
long secs, nanoSec;
struct timespec req, rem;
req.tv_sec = secs;
req.tv_nsec = nanoSec;
while (nanosleep(&req, &rem));
Right before the good old bmi270_init is called the device gets configured. Here we need to change the maximum size of the chunk we are able to send. Change read_write_len = 128 to M where M is the maximum number of bytes your I2C lib is able to send using i2cWriteI2CBlockData. In my case it's 32.
dev.delay_us = delay_us;
dev.read_write_len = 32; // ***** THIS must be changed according to the used I2C lib ***
dev.intf = BMI2_I2C_INTERFACE;
Last but not least you must open the proper I2C bus where the sensor is. Which usually involves some GPIO initialization. So in my case it is:
init_gpio();
i2c_open();
... call here the function which creates the device and calls bmi270_init(&device), etc ...
... the sensor works, you can have a cookie. ...
i2c_close();
terminate_gpio();
This will produce good config result in address: BMI2_INTERNAL_STATUS_ADDR. Go for the message bits (3..0) particularly value 1 which is message: "init_ok".
01-13-2020 04:36 PM
03-20-2023 12:27 PM
Still having issues with the initialization of the BMI270.
Anyone could be so kind and provide a full working example code?
Regards