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.