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..