Hi,
I'm stuck in the loop of calibration. This is the error that I get from Putty:

It says that I get a TX error.
This is the code that I have for bno055.h:
#ifndef __BNO055_H__
#define __BNO055_H__
#include <stdbool.h>
#include <stdint.h>
/** BNO055 Address A **/
#define BNO055_ADDRESS_A (0x28)
/** BNO055 ID **/
#define BNO055_ID (0xA0)
/** Offsets registers **/
#define NUM_BNO055_OFFSET_REGISTERS (22)
/** A structure to represent offsets **/
typedef struct {
int16_t accel_offset_x;
int16_t accel_offset_y;
int16_t accel_offset_z;
int16_t mag_offset_x;
int16_t mag_offset_y;
int16_t mag_offset_z;
int16_t gyro_offset_x;
int16_t gyro_offset_y;
int16_t gyro_offset_z;
int16_t accel_radius;
int16_t mag_radius;
} bno055_offsets_t;
/** Operation mode settings **/
typedef enum {
OPERATION_MODE_CONFIG = 0X00,
OPERATION_MODE_ACCONLY = 0X01,
OPERATION_MODE_MAGONLY = 0X02,
OPERATION_MODE_GYRONLY = 0X03,
OPERATION_MODE_ACCMAG = 0X04,
OPERATION_MODE_ACCGYRO = 0X05,
OPERATION_MODE_MAGGYRO = 0X06,
OPERATION_MODE_AMG = 0X07,
OPERATION_MODE_IMUPLUS = 0X08,
OPERATION_MODE_COMPASS = 0X09,
OPERATION_MODE_M4G = 0X0A,
OPERATION_MODE_NDOF_FMC_OFF = 0X0B,
OPERATION_MODE_NDOF = 0X0C
} bno055_opmode_t;
/** BNO055 power settings **/
typedef enum {
POWER_MODE_NORMAL = 0X00,
POWER_MODE_LOWPOWER = 0X01,
POWER_MODE_SUSPEND = 0X02
} bno055_powermode_t;
/** A structure to represent revisions **/
typedef struct {
uint8_t accel_rev;
uint8_t mag_rev;
uint8_t gyro_rev;
uint16_t sw_rev;
uint8_t bl_rev;
} bno055_rev_info_t;
/** Vector Mappings **/
typedef enum {
VECTOR_ACCELEROMETER = 0x08,
VECTOR_MAGNETOMETER = 0x0E,
VECTOR_GYROSCOPE = 0x14,
VECTOR_EULER = 0x1A,
VECTOR_LINEARACCEL = 0x28,
VECTOR_GRAVITY = 0x2E
} bno055_vector_type_t;
/** Register addresses **/
typedef enum {
BNO055_PAGE_ID_ADDR = 0X07,
BNO055_CHIP_ID_ADDR = 0x00,
BNO055_ACCEL_REV_ID_ADDR = 0x01,
BNO055_MAG_REV_ID_ADDR = 0x02,
BNO055_GYRO_REV_ID_ADDR = 0x03,
BNO055_SW_REV_ID_LSB_ADDR = 0x04,
BNO055_SW_REV_ID_MSB_ADDR = 0x05,
BNO055_BL_REV_ID_ADDR = 0X06,
/* Accel data register */
BNO055_ACCEL_DATA_X_LSB_ADDR = 0X08,
BNO055_ACCEL_DATA_X_MSB_ADDR = 0X09,
BNO055_ACCEL_DATA_Y_LSB_ADDR = 0X0A,
BNO055_ACCEL_DATA_Y_MSB_ADDR = 0X0B,
BNO055_ACCEL_DATA_Z_LSB_ADDR = 0X0C,
BNO055_ACCEL_DATA_Z_MSB_ADDR = 0X0D,
/* Mag data register */
BNO055_MAG_DATA_X_LSB_ADDR = 0X0E,
BNO055_MAG_DATA_X_MSB_ADDR = 0X0F,
BNO055_MAG_DATA_Y_LSB_ADDR = 0X10,
BNO055_MAG_DATA_Y_MSB_ADDR = 0X11,
BNO055_MAG_DATA_Z_LSB_ADDR = 0X12,
BNO055_MAG_DATA_Z_MSB_ADDR = 0X13,
/* Gyro data registers */
BNO055_GYRO_DATA_X_LSB_ADDR = 0X14,
BNO055_GYRO_DATA_X_MSB_ADDR = 0X15,
BNO055_GYRO_DATA_Y_LSB_ADDR = 0X16,
BNO055_GYRO_DATA_Y_MSB_ADDR = 0X17,
BNO055_GYRO_DATA_Z_LSB_ADDR = 0X18,
BNO055_GYRO_DATA_Z_MSB_ADDR = 0X19,
/* Euler data registers */
BNO055_EULER_H_LSB_ADDR = 0X1A,
BNO055_EULER_H_MSB_ADDR = 0X1B,
BNO055_EULER_R_LSB_ADDR = 0X1C,
BNO055_EULER_R_MSB_ADDR = 0X1D,
BNO055_EULER_P_LSB_ADDR = 0X1E,
BNO055_EULER_P_MSB_ADDR = 0X1F,
/* Quaternion data registers */
BNO055_QUATERNION_DATA_W_LSB_ADDR = 0X20,
BNO055_QUATERNION_DATA_W_MSB_ADDR = 0X21,
BNO055_QUATERNION_DATA_X_LSB_ADDR = 0X22,
BNO055_QUATERNION_DATA_X_MSB_ADDR = 0X23,
BNO055_QUATERNION_DATA_Y_LSB_ADDR = 0X24,
BNO055_QUATERNION_DATA_Y_MSB_ADDR = 0X25,
BNO055_QUATERNION_DATA_Z_LSB_ADDR = 0X26,
BNO055_QUATERNION_DATA_Z_MSB_ADDR = 0X27,
/* Linear acceleration data registers */
BNO055_LINEAR_ACCEL_DATA_X_LSB_ADDR = 0X28,
BNO055_LINEAR_ACCEL_DATA_X_MSB_ADDR = 0X29,
BNO055_LINEAR_ACCEL_DATA_Y_LSB_ADDR = 0X2A,
BNO055_LINEAR_ACCEL_DATA_Y_MSB_ADDR = 0X2B,
BNO055_LINEAR_ACCEL_DATA_Z_LSB_ADDR = 0X2C,
BNO055_LINEAR_ACCEL_DATA_Z_MSB_ADDR = 0X2D,
/* Gravity data registers */
BNO055_GRAVITY_DATA_X_LSB_ADDR = 0X2E,
BNO055_GRAVITY_DATA_X_MSB_ADDR = 0X2F,
BNO055_GRAVITY_DATA_Y_LSB_ADDR = 0X30,
BNO055_GRAVITY_DATA_Y_MSB_ADDR = 0X31,
BNO055_GRAVITY_DATA_Z_LSB_ADDR = 0X32,
BNO055_GRAVITY_DATA_Z_MSB_ADDR = 0X33,
/* Temperature data register */
BNO055_TEMP_ADDR = 0X34,
/* Status registers */
BNO055_CALIB_STAT_ADDR = 0X35,
BNO055_SELFTEST_RESULT_ADDR = 0X36,
BNO055_INTR_STAT_ADDR = 0X37,
BNO055_SYS_CLK_STAT_ADDR = 0X38,
BNO055_SYS_STAT_ADDR = 0X39,
BNO055_SYS_ERR_ADDR = 0X3A,
/* Unit selection register */
BNO055_UNIT_SEL_ADDR = 0X3B,
/* Mode registers */
BNO055_OPR_MODE_ADDR = 0X3D,
BNO055_PWR_MODE_ADDR = 0X3E,
BNO055_SYS_TRIGGER_ADDR = 0X3F,
BNO055_TEMP_SOURCE_ADDR = 0X40,
/* Axis remap registers */
BNO055_AXIS_MAP_CONFIG_ADDR = 0X41,
BNO055_AXIS_MAP_SIGN_ADDR = 0X42,
/* SIC registers */
BNO055_SIC_MATRIX_0_LSB_ADDR = 0X43,
BNO055_SIC_MATRIX_0_MSB_ADDR = 0X44,
BNO055_SIC_MATRIX_1_LSB_ADDR = 0X45,
BNO055_SIC_MATRIX_1_MSB_ADDR = 0X46,
BNO055_SIC_MATRIX_2_LSB_ADDR = 0X47,
BNO055_SIC_MATRIX_2_MSB_ADDR = 0X48,
BNO055_SIC_MATRIX_3_LSB_ADDR = 0X49,
BNO055_SIC_MATRIX_3_MSB_ADDR = 0X4A,
BNO055_SIC_MATRIX_4_LSB_ADDR = 0X4B,
BNO055_SIC_MATRIX_4_MSB_ADDR = 0X4C,
BNO055_SIC_MATRIX_5_LSB_ADDR = 0X4D,
BNO055_SIC_MATRIX_5_MSB_ADDR = 0X4E,
BNO055_SIC_MATRIX_6_LSB_ADDR = 0X4F,
BNO055_SIC_MATRIX_6_MSB_ADDR = 0X50,
BNO055_SIC_MATRIX_7_LSB_ADDR = 0X51,
BNO055_SIC_MATRIX_7_MSB_ADDR = 0X52,
BNO055_SIC_MATRIX_8_LSB_ADDR = 0X53,
BNO055_SIC_MATRIX_8_MSB_ADDR = 0X54,
/* Accelerometer Offset registers */
ACCEL_OFFSET_X_LSB_ADDR = 0X55,
ACCEL_OFFSET_X_MSB_ADDR = 0X56,
ACCEL_OFFSET_Y_LSB_ADDR = 0X57,
ACCEL_OFFSET_Y_MSB_ADDR = 0X58,
ACCEL_OFFSET_Z_LSB_ADDR = 0X59,
ACCEL_OFFSET_Z_MSB_ADDR = 0X5A,
/* Magnetometer Offset registers */
MAG_OFFSET_X_LSB_ADDR = 0X5B,
MAG_OFFSET_X_MSB_ADDR = 0X5C,
MAG_OFFSET_Y_LSB_ADDR = 0X5D,
MAG_OFFSET_Y_MSB_ADDR = 0X5E,
MAG_OFFSET_Z_LSB_ADDR = 0X5F,
MAG_OFFSET_Z_MSB_ADDR = 0X60,
/* Gyroscope Offset registers */
GYRO_OFFSET_X_LSB_ADDR = 0X61,
GYRO_OFFSET_X_MSB_ADDR = 0X62,
GYRO_OFFSET_Y_LSB_ADDR = 0X63,
GYRO_OFFSET_Y_MSB_ADDR = 0X64,
GYRO_OFFSET_Z_LSB_ADDR = 0X65,
GYRO_OFFSET_Z_MSB_ADDR = 0X66,
/* Radius registers */
ACCEL_RADIUS_LSB_ADDR = 0X67,
ACCEL_RADIUS_MSB_ADDR = 0X68,
MAG_RADIUS_LSB_ADDR = 0X69,
MAG_RADIUS_MSB_ADDR = 0X6A
} adafruit_bno055_reg_t;
bool bno055_init(void);
void bno055_set_mode(bno055_opmode_t mode);
void bno055_set_power_mode(bno055_powermode_t mode);
void bno055_get_calibration(uint8_t *system, uint8_t *gyro, uint8_t *accel, uint8_t *mag);
void bno055_get_rev_info(bno055_rev_info_t *info);
int8_t bno055_get_temp(void);
bool bno055_read_vector(bno055_vector_type_t vector_type, int16_t *x, int16_t *y, int16_t *z);
void bno055_set_axis_remap(uint8_t remapcode);
void bno055_set_axis_sign(uint8_t remapsign);
void bno055_enter_suspend_mode(void);
void bno055_enter_normal_mode(void);
#endif // __BNO055_H__
This is the code that I have for bno055.c:
#include "bno055.h"
#include "nrf_drv_twi.h"
#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "nrf_log.h"
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(0);
static ret_code_t read8(uint8_t address, uint8_t reg, uint8_t *value) {
ret_code_t err_code;
err_code = nrf_drv_twi_tx(&m_twi, address, ®, 1, true);
if (err_code != NRF_SUCCESS) {
NRF_LOG_ERROR("I2C TX Error: %d", err_code);
return err_code;
}
err_code = nrf_drv_twi_rx(&m_twi, address, value, 1);
if (err_code != NRF_SUCCESS) {
NRF_LOG_ERROR("I2C RX Error: %d", err_code);
}
return err_code;
}
static ret_code_t write8(uint8_t address, uint8_t reg, uint8_t value) {
ret_code_t err_code;
uint8_t buffer[2] = {reg, value};
err_code = nrf_drv_twi_tx(&m_twi, address, buffer, 2, false);
if (err_code != NRF_SUCCESS) {
NRF_LOG_ERROR("I2C Write Error: %d", err_code);
}
return err_code;
}
bool bno055_init(void) {
uint8_t id;
ret_code_t err_code;
err_code = read8(BNO055_ADDRESS_A, BNO055_CHIP_ID_ADDR, &id);
if (err_code != NRF_SUCCESS || id != BNO055_ID) {
NRF_LOG_INFO("BNO055 ID mismatch: expected 0xA0, got 0x%02x", id);
return false;
}
bno055_set_mode(OPERATION_MODE_CONFIG);
nrf_delay_ms(25);
write8(BNO055_ADDRESS_A, BNO055_SYS_TRIGGER_ADDR, 0x20); // Reset all interrupts
nrf_delay_ms(10);
bno055_set_mode(OPERATION_MODE_NDOF);
nrf_delay_ms(20);
return true;
}
void bno055_set_mode(bno055_opmode_t mode) {
write8(BNO055_ADDRESS_A, BNO055_OPR_MODE_ADDR, mode);
nrf_delay_ms(30);
}
void bno055_set_power_mode(bno055_powermode_t mode) {
write8(BNO055_ADDRESS_A, BNO055_PWR_MODE_ADDR, mode);
nrf_delay_ms(30);
}
void bno055_get_calibration(uint8_t *system, uint8_t *gyro, uint8_t *accel, uint8_t *mag) {
uint8_t calData;
read8(BNO055_ADDRESS_A, BNO055_CALIB_STAT_ADDR, &calData);
*system = (calData >> 6) & 0x03;
*gyro = (calData >> 4) & 0x03;
*accel = (calData >> 2) & 0x03;
*mag = calData & 0x03;
}
void bno055_get_rev_info(bno055_rev_info_t *info) {
read8(BNO055_ADDRESS_A, BNO055_ACCEL_REV_ID_ADDR, &info->accel_rev);
read8(BNO055_ADDRESS_A, BNO055_MAG_REV_ID_ADDR, &info->mag_rev);
read8(BNO055_ADDRESS_A, BNO055_GYRO_REV_ID_ADDR, &info->gyro_rev);
uint8_t sw_rev_lsb, sw_rev_msb;
read8(BNO055_ADDRESS_A, BNO055_SW_REV_ID_LSB_ADDR, &sw_rev_lsb);
read8(BNO055_ADDRESS_A, BNO055_SW_REV_ID_MSB_ADDR, &sw_rev_msb);
info->sw_rev = (uint16_t)((sw_rev_msb << 8) | sw_rev_lsb);
read8(BNO055_ADDRESS_A, BNO055_BL_REV_ID_ADDR, &info->bl_rev);
}
int8_t bno055_get_temp(void) {
int8_t temp;
read8(BNO055_ADDRESS_A, BNO055_TEMP_ADDR, (uint8_t*)&temp);
return temp;
}
bool bno055_read_vector(bno055_vector_type_t vector_type, int16_t *x, int16_t *y, int16_t *z) {
uint8_t buffer[6];
uint8_t reg = (uint8_t)vector_type;
ret_code_t err_code;
err_code = nrf_drv_twi_tx(&m_twi, BNO055_ADDRESS_A, ®, 1, true);
if (err_code != NRF_SUCCESS) {
NRF_LOG_ERROR("I2C TX Error: %d", err_code);
return false;
}
err_code = nrf_drv_twi_rx(&m_twi, BNO055_ADDRESS_A, buffer, 6);
if (err_code != NRF_SUCCESS) {
NRF_LOG_ERROR("I2C RX Error: %d", err_code);
return false;
}
*x = (int16_t)((buffer[0]) | (buffer[1] << 8));
*y = (int16_t)((buffer[2]) | (buffer[3] << 8));
*z = (int16_t)((buffer[4]) | (buffer[5] << 8));
return true;
}
void bno055_set_axis_remap(uint8_t remapcode) {
write8(BNO055_ADDRESS_A, BNO055_AXIS_MAP_CONFIG_ADDR, remapcode);
nrf_delay_ms(10);
}
void bno055_set_axis_sign(uint8_t remapsign) {
write8(BNO055_ADDRESS_A, BNO055_AXIS_MAP_SIGN_ADDR, remapsign);
nrf_delay_ms(10);
}
void bno055_enter_suspend_mode(void) {
bno055_set_power_mode(POWER_MODE_SUSPEND);
}
void bno055_enter_normal_mode(void) {
bno055_set_power_mode(POWER_MODE_NORMAL);
}
And this is my main.c code:
#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "bno055.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#define NRF_LOG_FLOAT_ENABLED 1
#include <math.h>
#define G_CONSTANT 9.81f
#define TWI_INSTANCE_ID 0
#define SDA_PIN 24
#define SCL_PIN 25
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
void twi_master_init(void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t twi_config = {
.scl = SCL_PIN,
.sda = SDA_PIN,
.frequency = NRF_DRV_TWI_FREQ_400K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH
};
err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&m_twi);
}
void perform_calibration(void);
int main(void)
{
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
static int16_t AccValue[3], GyroValue[3];
float acc_x;
float acc_y;
float acc_z;
float gyr_x;
float gyr_y;
float gyr_z;
bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);
twi_master_init();
nrf_delay_ms(1000);
if (!bno055_init())
{
NRF_LOG_INFO("BNO055 initialization failed!!!");
while (1) { nrf_delay_ms(1000); }
}
NRF_LOG_INFO("BNO055 Init Successfully!!!");
// Perform calibration
perform_calibration();
NRF_LOG_INFO("Calibration completed.");
NRF_LOG_INFO("Reading Values from ACC & GYRO");
nrf_delay_ms(2000);
char log_buffer[128];
while (true)
{
if (bno055_read_vector(VECTOR_ACCELEROMETER, &AccValue[0], &AccValue[1], &AccValue[2]))
{
acc_x = ((float)AccValue[0] / 100.0f) * G_CONSTANT; // Convert from mg to m/s^2
acc_y = ((float)AccValue[1] / 100.0f) * G_CONSTANT;
acc_z = ((float)AccValue[2] / 100.0f) * G_CONSTANT;
snprintf(log_buffer, sizeof(log_buffer), "ACC Values: x = %0.1f, y = %0.1f, z = %0.1f (m/s^2)", acc_x, acc_y, acc_z); // m/s^2
NRF_LOG_INFO("%s", NRF_LOG_PUSH(log_buffer));
}
else
{
NRF_LOG_INFO("Reading ACC values Failed!!!");
}
if (bno055_read_vector(VECTOR_GYROSCOPE, &GyroValue[0], &GyroValue[1], &GyroValue[2]))
{
gyr_x = ((float)GyroValue[0] / 16.0f) * (M_PI / 180); // Convert from deg/s to rad/s
gyr_y = ((float)GyroValue[1] / 16.0f) * (M_PI / 180);
gyr_z = ((float)GyroValue[2] / 16.0f) * (M_PI / 180);
snprintf(log_buffer, sizeof(log_buffer), "GYRO Values: x = %0.1f, y = %0.1f, z = %0.1f (rad/s)", gyr_x, gyr_y, gyr_z); // rad/s
NRF_LOG_INFO("%s", NRF_LOG_PUSH(log_buffer));
}
else
{
NRF_LOG_INFO("Reading GYRO values Failed!!!");
}
nrf_delay_ms(100);
}
}
void perform_calibration(void)
{
uint8_t system, gyro, accel, mag;
NRF_LOG_INFO("Starting calibration. Please follow the instructions.");
bno055_set_mode(OPERATION_MODE_CONFIG);
nrf_delay_ms(25);
bno055_set_mode(OPERATION_MODE_NDOF);
nrf_delay_ms(20);
while (1)
{
bno055_get_calibration(&system, &gyro, &accel, &mag);
NRF_LOG_INFO("CALIBRATION: Sys=%d, Gyro=%d, Accel=%d, Mag=%d", system, gyro, accel, mag);
if (system == 3 && gyro == 3 && accel == 3 && mag == 3)
{
NRF_LOG_INFO("Calibration completed.");
break;
}
nrf_delay_ms(500);
}
}
Please help..