This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI Troubles With nRF51 DK and MMA8452 Accelerometer

I have an accelerometer that utilizes IC2 (NXP MMA8452Q) that I am trying to integrate with the nRF51 DK. The accelerometer is on a breakout board, and is wired up very simply using the SCL, SDA, and the power supply pins. I am basing the implementation on the BLE Central - BLE App UART example, as I am using that for another part of the project. The SDK is 12.1. I do not have a logic analyzer or scope.

The problem that I am seeing is that I'm not receiving any TWI events after using the nrf_drv_twi_rx() function. Sometimes, when I call this function, the nRF51 DK stalls or resets. Also, curisously, I am seeing two NRF_DRV_TWI_EVT_DONE events after calling the nrf_drv_twi_tx() function to wake and setup the accelerometer.

At this point, I would like to "wake" the accelerometer by writing 0x33 to the CTRL_REG1 register. After that, I would like to read the WHO_AM_I register to verify I2C/TWI operation. I should receive back a known byte value. So far, I have not seen any rx events.

I have tried both (0x1DU) and (0x1DU >> 1) for the acceleromter address.

Below is a typical printf log, and code is attached with some BLE central functions taken out for readability. What am I doing wrong?

Start TWI
TWI Initialized
twi_handler event.
NRF_DRV_TWI_EVT_DONE:
MMA8452 Setup and Wake Complete.
twi_handler event.
NRF_DRV_TWI_EVT_DONE:
WHO_AM_I Tx
twi_handler event.
NRF_DRV_TWI_EVT_DONE:
WHO_AM_I Tx
read_data() done

main_TWI_sample.c

  • Which error code does nrf_drv_twi_rx return? Have you verified that the ARDUINO_SCL_PIN and ARDUINO_SDA_PIN defines correspond to the pins you have connected to the MMA8452?

  • Bjorn, nrf_drv_twi_rx is returning "NRF_SUCCESS".

    Here are the defines for the pins, which do line up with the SCL and SDA pins on the nRF51 DK.

    // Arduino board mappings
    #define ARDUINO_SCL_PIN             7     // SCL signal pin
    #define ARDUINO_SDA_PIN             30    // SDA signal pin
    

    This morning, the same code appears to working with nrf_drv_twi_rx, but it is returning 0xff, not 0x2a, which is what it should be seeing.....

  • One thing I noticed is that you should add while (m_xfer_done == false); after the last nrf_drv_twi_rx() n read_data(). I do not think that this should matter since you have a 2second delay in the main loop, but better safe than sorry. Are the I2C lines on the MMA8452Q break-out board properly grounded?

  • Bjorn, I added the (m_xfer_done == false); like you had mentioned. I also de-soldered the wires to the breakout board and rewired with hookup wires that go directly to the headers on the DK. It does seem more consistent now. No resets for stalls. Below is what I'm seeing over UART. I still do not appear to be getting my expected WHO_AM_I value, though.

    Start TWI
    TWI Initialized
    wake errtwi_handler event.
    NRF_DRV_TWI_EVT_DONE:
    _code is 0
    MMA8452 Setup and Wake Complete.
    WHO_AM_I Tx
    tx errtwi_handler event.
    NRF_DRV_TWI_EVT_DONE:
    _code is 0
    WHO_AM_I Tx
    rx errtwi_handler event.
    NRF_DRV_TWI_EVT_DONWHO_AM_I Tx
    tx errtwi_handler event.
    NRF_DRV_TWI_EVT_DONE:
    _code is 0
    WHO_AM_I Tx
    rtwi_handler event.
    NRF_DRV_TWI_EVT_DONE:
    Data Read: 0xff
    x err_code is 0
    read_data() done
    

    Repeating....

  • I found the problem and got it working. In the nrf_drv_twi_tx call inside the data_read() function, I had the no_stop parameter set to false. When I set it to true, I was receiving the correct WHO_AM_I response.

    Below is the updated function for those who come across the same problem.

    /**
     * @brief Function for reading data from the accelerometer.
     */
    static void read_data()
    {
    		ret_code_t err_code;
    		uint8_t addr8 = WHO_AM_I;
    	
    		printf("WHO_AM_I Tx\r\n");
    
            m_xfer_done = false;
    		err_code = nrf_drv_twi_tx(&m_twi, MMA8452_ADDR, &addr8, 1, true);
    		printf("tx err_code is %d\r\n", err_code);
    		while (m_xfer_done == false);	
    
    		printf("WHO_AM_I Rx\r\n");
    	
    		m_xfer_done = false;
    		err_code = nrf_drv_twi_rx(&m_twi, MMA8452_ADDR, &m_sample, 1);
    		APP_ERROR_CHECK(err_code);
    		printf("rx err_code is %d\r\n", err_code);
    
    		while (m_xfer_done == false);	
    	
    		printf("read_data() done\r\n");
    }
    
Related