Hi
Has anyone developed or worked with a BNO080 using Hilcrest's SH-2 Protocol over TWIM? I'm having real challenges getting consistent responses. I've developed (based on what I can find on the internet) the basics of a library. But every time I run even even the simplest of requests 50% I get NRF_ERROR_TIMEOUT. The other 50% of the time if receive NRFX_TWIM_EVT_DONE and NRFX_TWIM_XFER_TX.
My other question is related to my lack of experience. How do I know (without interrupt) that data is ready to be ready from TWIM?
bno080-twim.h
#define MPU_TWI_SCL_PIN 11 #define MPU_TWI_SDA_PIN 8 #define MPU_TWI_BUFFER_SIZE 32 #define MPU_TWI_TIMEOUT 15000 #define BNO080_TWI_ADDRESS 0x4B #define MPU_ADDRESS 0x68 #define MPU_AK89XX_MAGN_ADDRESS 0x0C //Registers #define CHANNEL_COMMAND 0 #define CHANNEL_EXECUTABLE 1 #define CHANNEL_CONTROL 2 #define CHANNEL_REPORTS 3 #define CHANNEL_WAKE_REPORTS 4 #define CHANNEL_GYRO 5 //All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual //These are used for low level communication with the sensor, on channel 2 #define SHTP_REPORT_COMMAND_RESPONSE 0xF1 #define SHTP_REPORT_COMMAND_REQUEST 0xF2 #define SHTP_REPORT_FRS_READ_RESPONSE 0xF3 #define SHTP_REPORT_FRS_READ_REQUEST 0xF4 #define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8 #define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9 #define SHTP_REPORT_BASE_TIMESTAMP 0xFB #define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD //All the different sensors and features we can get reports from //These are used when enabling a given sensor #define SENSOR_REPORTID_ACCELEROMETER 0x01 #define SENSOR_REPORTID_GYROSCOPE 0x02 #define SENSOR_REPORTID_MAGNETIC_FIELD 0x03 #define SENSOR_REPORTID_LINEAR_ACCELERATION 0x04 #define SENSOR_REPORTID_ROTATION_VECTOR 0x05 #define SENSOR_REPORTID_GRAVITY 0x06 #define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08 #define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09 #define SENSOR_REPORTID_TAP_DETECTOR 0x10 #define SENSOR_REPORTID_STEP_COUNTER 0x11 #define SENSOR_REPORTID_STABILITY_CLASSIFIER 0x13 #define SENSOR_REPORTID_RAW_ACCELEROMETER 0x14 #define SENSOR_REPORTID_RAW_GYROSCOPE 0x15 #define SENSOR_REPORTID_RAW_MAGNETOMETER 0x16 #define SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER 0x1E //Record IDs from figure 29, page 29 reference manual //These are used to read the metadata for each sensor type #define FRS_RECORDID_ACCELEROMETER 0xE302 #define FRS_RECORDID_GYROSCOPE_CALIBRATED 0xE306 #define FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED 0xE309 #define FRS_RECORDID_ROTATION_VECTOR 0xE30B //Command IDs from section 6.4, page 42 //These are used to calibrate, initialize, set orientation, tare etc the sensor #define COMMAND_ERRORS 1 #define COMMAND_COUNTER 2 #define COMMAND_TARE 3 #define COMMAND_INITIALIZE 4 #define COMMAND_DCD 6 #define COMMAND_ME_CALIBRATE 7 #define COMMAND_DCD_PERIOD_SAVE 9 #define COMMAND_OSCILLATOR 10 #define COMMAND_CLEAR_DCD 11 #define CALIBRATE_ACCEL 0 #define CALIBRATE_GYRO 1 #define CALIBRATE_MAG 2 #define CALIBRATE_PLANAR_ACCEL 3 #define CALIBRATE_ACCEL_GYRO_MAG 4 #define CALIBRATE_STOP 5 #define MAX_PACKET_SIZE 28 // Size of TWi Buffer 32-4=28 for the header //128 //Packets can be up to 32k but we don't have that much RAM. #define MAX_METADATA_SIZE 9 //This is in words. There can be many but we mostly only care about the first 9 (Qs, range, etc) // TWI (with transaction manager) initialization. uint32_t twi_config(void); uint32_t twi_scanner(); uint32_t bno080_init();
bno080-twim.c
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "nrf_log.h"
#include "nrfx_twim.h"
#include "nrf_delay.h"
#include "bno080-twim.h"
uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0}; //There are 6 com channels. Each channel has its own seqnum
uint8_t commandSequenceNumber = 0; //Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel
//#define TWI_INSTANCE_ID 0
//#define MAX_PENDING_TRANSACTIONS 5
//NRF_TWI_MNGR_DEF(m_nrf_twi_mngr, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);
static const nrfx_twim_t m_twi_instance = NRFX_TWIM_INSTANCE(0);
volatile static bool twi_tx_done = false;
volatile static bool twi_rx_done = false;
uint8_t twi_tx_buffer[MPU_TWI_BUFFER_SIZE];
static void twi_event_handler(nrfx_twim_evt_t const * p_event, void * p_context)
{
switch(p_event->type)
{
case NRFX_TWIM_EVT_DONE:
NRF_LOG_INFO("NRFX_TWIM_EVT_DONE");
switch(p_event->xfer_desc.type)
{
case NRFX_TWIM_XFER_TX:
NRF_LOG_INFO("NRFX_TWIM_XFER_TX");
twi_tx_done = true;
break;
case NRFX_TWIM_XFER_TXTX:
NRF_LOG_INFO("NRFX_TWIM_XFER_TXTX");
twi_tx_done = true;
break;
case NRFX_TWIM_XFER_RX:
NRF_LOG_INFO("NRFX_TWIM_XFER_RX");
twi_rx_done = true;
break;
case NRFX_TWIM_XFER_TXRX:
NRF_LOG_INFO("NRFX_TWIM_XFER_TXRX");
twi_rx_done = true;
break;
default:
break;
}
break;
case NRFX_TWIM_EVT_ADDRESS_NACK:
break;
case NRFX_TWIM_EVT_DATA_NACK:
break;
default:
break;
}
}
// TWI (with transaction manager) initialization.
uint32_t twi_config(void)
{
uint32_t err_code;
const nrfx_twim_config_t twi_mpu_config = {
.scl = MPU_TWI_SCL_PIN,
.sda = MPU_TWI_SDA_PIN,
.frequency = NRF_TWIM_FREQ_400K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGHEST,
.hold_bus_uninit = true
};
err_code = nrfx_twim_init(&m_twi_instance, &twi_mpu_config, twi_event_handler, NULL);
if(err_code != NRF_SUCCESS) {return err_code;}
nrf_delay_ms(1);
nrfx_twim_enable(&m_twi_instance);
return NRF_SUCCESS;
}
uint32_t twi_scanner()
{
uint32_t err_code;
uint8_t address;
uint8_t sample_data;
for (address = 1; address <= 127; address++)
{
err_code = nrfx_twim_rx(&m_twi_instance, address, &sample_data, sizeof(sample_data));
if (err_code == NRF_SUCCESS)
{
NRF_LOG_INFO("TWI device detected at address 0x%x.", address);
}
}
return NRF_SUCCESS;
}
uint32_t bno080_init()
{
uint32_t err_code;
uint32_t timeout = MPU_TWI_TIMEOUT;
uint16_t packetLength = 6;
uint8_t * txbuffer = malloc(packetLength); //setup the data paxket to send
txbuffer[0] = packetLength & 0xFF; //SHTP Header - Byte 0 - Packet Length LSB
txbuffer[1] = packetLength >> 8; //SHTP Header - Byte 1 - Packet Length MSB
txbuffer[2] = CHANNEL_CONTROL; //SHTP Header - Byte 2 - Channel Number
txbuffer[3] = sequenceNumber[CHANNEL_CONTROL]++; //SHTP Header - Byte 3 - Sequence Number
txbuffer[4] = SHTP_REPORT_PRODUCT_ID_REQUEST; //SHTP Header - Byte 4 - SHTP_REPORT_PRODUCT_ID_REQUEST
txbuffer[5] = 0x0; //SHTP Header - Byte 5 - Reserved
// Setting up transfer
nrfx_twim_xfer_desc_t xfer_desc;
xfer_desc.address = BNO080_TWI_ADDRESS;
xfer_desc.type = NRFX_TWIM_XFER_TX;
xfer_desc.primary_length = packetLength;
xfer_desc.p_primary_buf = txbuffer;
// Transferring
err_code = nrfx_twim_xfer(&m_twi_instance, &xfer_desc, 0);
while((!twi_tx_done) && --timeout);
if(!timeout) return NRF_ERROR_TIMEOUT;
twi_tx_done = false;
return err_code;
}
TWI/TWIM Settings in SDK:
Thanks, been bogged down with this for a few days.