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

nrf_drv_twi_rx can't read correct data, but always only zero.

I'm trying to read temperature sensor data through TWI (I2C) from SHT3x using NRF52-DK and SDK v16.0.
Observing an oscillator, the address and the return value with CLK looks correct, but the buffered read data (rx_buf[]) by nrf_drv_twi_rx is zero.
That result is not different between before and after the waiting "while ( m_xfer_done == false );"
What should I check and correct?


sdk_config.h

NRFX_TWIM_ENABLED 1
NRFX_TWI_ENABLED 1
TWI_ENABLED 1
TWI0_ENABLED 1
TWI0_USE_EASY_DMA 1


static volatile bool       m_xfer_done = false;
static uint8_t             rx_buf[6] = {0};
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);


void twi_init (void)
{
    ret_code_t err_code;

    /** TWI driver configuration */
    const nrf_drv_twi_config_t twi_config = {
        .scl                   = TWI_SCL_PIN,
        .sda                   = TWI_SDA_PIN,
        .frequency             = NRF_DRV_TWI_FREQ_100K,
        .interrupt_priority    = APP_IRQ_PRIORITY_HIGH,
        .clear_bus_init        = false
    };

    /** Initializing TWI Driver. */
    err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
    NRF_LOG_INFO(" -- nrf_drv_twi_init(): Return %d.", err_code );
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            m_xfer_done = true;
            break;
        default:
            break;
    }
}

void SHT3x_readout(void)
{
    ret_code_t err_code;
    uint8_t reg[2] = {0};

    // Measurement Command
    nrf_delay_ms(100);
    reg[0] = 0x24;
    reg[1] = 0x00;
    m_xfer_done = false;

    err_code = nrf_drv_twi_tx( &m_twi, 0x45, reg, 2, false );
    NRF_LOG_INFO(" -- Function set: Return %d, m_xfer_done %d.", err_code, (uint16_t)m_xfer_done );
    APP_ERROR_CHECK( err_code );
    while ( m_xfer_done == false );

    // Readout of Measurement Results
    nrf_delay_ms(100);
    memset(rx_buf, 0, sizeof(rx_buf));
    err_code = nrf_drv_twi_rx( &m_twi, 0x45, rx_buf, 6 ); 
    APP_ERROR_CHECK( err_code );

    NRF_LOG_INFO(" -- Function read: Return %d.", err_code );
    NRF_LOG_INFO("                   0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.",
                       rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3], rx_buf[4], rx_buf[5] );

    while ( m_xfer_done == false );

    NRF_LOG_INFO(" -- Function read: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.",
                       rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3], rx_buf[4], rx_buf[5] );
}


Results on UART:

  app:  -- nrf_drv_twi_init(): Return 0.
  app:  -- Function set: Return 0, m_xfer_done 0.
  app:  -- Function read: Return 0.
  app:                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00.
  app:  -- Function read: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00.

Parents
  • Hi,

    It looks like you are forgetting to set your 'm_xfer_done' flag to 'false' before calling nrf_drv_twi_rx().  Try to do that and let me know if it still doesn't work.

    Here is another example that samples temp and humidity with the sht3x in case you are interested:

    /**
     * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup tw_sensor_example main.c
     * @{
     * @ingroup nrf_twi_example
     * @brief TWI Sensor Example main file.
     *
     * This file contains the source code for a sample application using TWI.
     *
     */
    
    #include <stdio.h>
    #include "boards.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* Common addresses definition for temperature sensor. */
    #define SHT3x_ADDRESS                   (0x45U)
    #define SHT3x_MEAS_CMD_H                {0x2c, 0x06}                       /**<Start high repeatability measurement with clock stretching*/
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    
    /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    __STATIC_INLINE void data_handler(nrf_drv_twi_evt_t const * p_event)
    {
        uint16_t      raw_value;
        float         temperature;
        uint16_t      humidity;
        
        /* Raw data conversion. We are ignoring the checksum value here */ 
        raw_value = uint16_big_decode(&p_event->xfer_desc.p_secondary_buf[0]); /* Swap byte order to little endian */
        
        temperature = 175 * (uint16_t)raw_value / 65535.0f -45.0f;
    
        raw_value = uint16_big_decode(&p_event->xfer_desc.p_secondary_buf[3]);
        humidity = 100.0f * raw_value / 65535.0f;
        
        NRF_LOG_INFO("Temperature: "NRF_LOG_FLOAT_MARKER" Celsius degrees.", NRF_LOG_FLOAT(temperature));
        NRF_LOG_INFO("Humidity: %d%%", humidity);
    }
    
    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
                {
                    data_handler(p_event);
                }
                break;
            case NRF_DRV_TWI_EVT_ADDRESS_NACK:
                NRF_LOG_WARNING("Received NRF_DRV_TWI_EVT_ADDRESS_NACK event");
                break;
            case NRF_DRV_TWI_EVT_DATA_NACK:
                NRF_LOG_WARNING("Received NRF_DRV_TWI_EVT_DATA_NACK event");
                break;
            default:
                break;
        }
    }
    
    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_sht3x_config = {
           .scl                = ARDUINO_SCL_PIN,
           .sda                = ARDUINO_SDA_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_sht3x_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    /**
     * @brief Function for reading data from temperature sensor.
     */
    static void read_sensor_data()
    {  
        uint32_t err_code;
        static uint8_t twim_rx_buf[6];
        static uint8_t twim_tx_buf[] = SHT3x_MEAS_CMD_H;
    
        nrf_drv_twi_xfer_desc_t xfer_desc = NRF_DRV_TWI_XFER_DESC_TXRX(
            SHT3x_ADDRESS, twim_tx_buf, sizeof(twim_tx_buf), twim_rx_buf, sizeof(twim_rx_buf));
    
        err_code = nrf_drv_twi_xfer(&m_twi, &xfer_desc, NRF_DRV_TWI_FLAG_TX_NO_STOP);
        if (err_code == NRF_ERROR_BUSY)
        {
            NRF_LOG_INFO("TWIM driver is busy");
        }
        else
        {
            APP_ERROR_CHECK(err_code);
        }
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("\r\nTWI SHT3x example started.");
        NRF_LOG_FLUSH();
        twi_init();
    
        while (true)
        {
            nrf_delay_ms(500);
            read_sensor_data();
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */

Reply
  • Hi,

    It looks like you are forgetting to set your 'm_xfer_done' flag to 'false' before calling nrf_drv_twi_rx().  Try to do that and let me know if it still doesn't work.

    Here is another example that samples temp and humidity with the sht3x in case you are interested:

    /**
     * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup tw_sensor_example main.c
     * @{
     * @ingroup nrf_twi_example
     * @brief TWI Sensor Example main file.
     *
     * This file contains the source code for a sample application using TWI.
     *
     */
    
    #include <stdio.h>
    #include "boards.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* Common addresses definition for temperature sensor. */
    #define SHT3x_ADDRESS                   (0x45U)
    #define SHT3x_MEAS_CMD_H                {0x2c, 0x06}                       /**<Start high repeatability measurement with clock stretching*/
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    
    /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    __STATIC_INLINE void data_handler(nrf_drv_twi_evt_t const * p_event)
    {
        uint16_t      raw_value;
        float         temperature;
        uint16_t      humidity;
        
        /* Raw data conversion. We are ignoring the checksum value here */ 
        raw_value = uint16_big_decode(&p_event->xfer_desc.p_secondary_buf[0]); /* Swap byte order to little endian */
        
        temperature = 175 * (uint16_t)raw_value / 65535.0f -45.0f;
    
        raw_value = uint16_big_decode(&p_event->xfer_desc.p_secondary_buf[3]);
        humidity = 100.0f * raw_value / 65535.0f;
        
        NRF_LOG_INFO("Temperature: "NRF_LOG_FLOAT_MARKER" Celsius degrees.", NRF_LOG_FLOAT(temperature));
        NRF_LOG_INFO("Humidity: %d%%", humidity);
    }
    
    /**
     * @brief TWI events handler.
     */
    void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
        switch (p_event->type)
        {
            case NRF_DRV_TWI_EVT_DONE:
                if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
                {
                    data_handler(p_event);
                }
                break;
            case NRF_DRV_TWI_EVT_ADDRESS_NACK:
                NRF_LOG_WARNING("Received NRF_DRV_TWI_EVT_ADDRESS_NACK event");
                break;
            case NRF_DRV_TWI_EVT_DATA_NACK:
                NRF_LOG_WARNING("Received NRF_DRV_TWI_EVT_DATA_NACK event");
                break;
            default:
                break;
        }
    }
    
    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_sht3x_config = {
           .scl                = ARDUINO_SCL_PIN,
           .sda                = ARDUINO_SDA_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_100K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_sht3x_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    /**
     * @brief Function for reading data from temperature sensor.
     */
    static void read_sensor_data()
    {  
        uint32_t err_code;
        static uint8_t twim_rx_buf[6];
        static uint8_t twim_tx_buf[] = SHT3x_MEAS_CMD_H;
    
        nrf_drv_twi_xfer_desc_t xfer_desc = NRF_DRV_TWI_XFER_DESC_TXRX(
            SHT3x_ADDRESS, twim_tx_buf, sizeof(twim_tx_buf), twim_rx_buf, sizeof(twim_rx_buf));
    
        err_code = nrf_drv_twi_xfer(&m_twi, &xfer_desc, NRF_DRV_TWI_FLAG_TX_NO_STOP);
        if (err_code == NRF_ERROR_BUSY)
        {
            NRF_LOG_INFO("TWIM driver is busy");
        }
        else
        {
            APP_ERROR_CHECK(err_code);
        }
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("\r\nTWI SHT3x example started.");
        NRF_LOG_FLUSH();
        twi_init();
    
        while (true)
        {
            nrf_delay_ms(500);
            read_sensor_data();
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */

Children
Related