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

Read LPS22HB Pressure sensor values with TWI on NRF52840

I am trying to integrate a pressure sensor with our system and Nordic has libraries for LPS22HB sensor. I ordered STEVAL-MET001V1 from ST and try to modify the TWI-sensor examples under SDK15.2 peripherals examples, but only got incorrect readings. I also looked into Thingy 52 pressure sensing codes and tried with drv_lps22hb library, but get all 0 readings. There is another library lps22hb in the SDK but it seems to be harder to work with (sorry I am still learning). I have pasted some of the key codes here and wondering what is the problem. I don't understand what the set_mode() function does in the example, but I keep it anyhow.  I just need a simple reading function to get the data whenever I call. Thank you for your help.

By the way, for LPS22HB, there are three addresses 0x28, 0x29 and 0x2A for pressure, two addresses 0x2B and 0x2C for temperature according to ST's documents.

/* TWI instance ID. */
#define TWI_INSTANCE_ID     0

/* Common addresses definition for temperature sensor. */
#define LM75B_ADDR         0x5DU// (0x90U >> 1)

#define PRESS_OUT_XL_REG    0x28U
#define PRESS_OUT_L_REG      0x29U
#define PRESS_OUT_H_REG      0x2AU
#define TEMP_OUT_L_REG     0x2BU
#define TEMP_OUT_H_REG       0x2CU
/* Mode for LM75B. */
#define NORMAL_MODE 0U

/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;
/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

void LM75B_set_mode(void)
{
    ret_code_t err_code;

    /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
    uint8_t reg[2] = {PRESS_OUT_XL_REG, NORMAL_MODE};
    err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    /* Writing to pointer byte. */
    reg[0] = PRESS_OUT_XL_REG;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, 1, false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_lm75b_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_lm75b_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
    
    static uint32_t reg_read(uint8_t reg_addr, uint8_t * p_reg_val)
{
    m_xfer_done = false;

    uint32_t err_code;

    err_code = nrf_drv_twi_tx( &m_twi,
                               LM75B_ADDR,
                               &reg_addr,
                               1,
                               false );
       while (m_xfer_done == false);
            m_xfer_done = false; 
    err_code = nrf_drv_twi_rx( &m_twi,
                               LM75B_ADDR,
                               p_reg_val,
                               sizeof(p_reg_val));
    APP_ERROR_CHECK(err_code);
    return NRF_SUCCESS;
}

uint32_t lps22hb_pressure_get()
{
    uint32_t err_code;
    uint8_t  press_xl;
    uint8_t  press_l;
    uint8_t  press_h;
    uint8_t  temp_l;
    uint8_t  temp_h;
    uint32_t pressure;
    err_code = reg_read(PRESS_OUT_XL_REG, &press_xl);

    err_code = reg_read(PRESS_OUT_L_REG, &press_l);

    err_code = reg_read(PRESS_OUT_H_REG, &press_h);
    err_code = reg_read(TEMP_OUT_L_REG, &temp_l);

    err_code = reg_read(TEMP_OUT_H_REG, &temp_h);

    pressure = ((uint32_t)press_h << 16) + ((uint32_t)press_l << 8) + press_xl; // To calculate p(hPa) = *p_pressure(LSB) / 4096(LSB/hPa).
    NRF_LOG_INFO("Pressure: %d hPa.", pressure/4096);
    return NRF_SUCCESS;
}

/**
 * @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 sensor example started.");
    NRF_LOG_FLUSH();
    twi_init();
    LM75B_set_mode();

    while (true)
    {
        nrf_delay_ms(1000);

        do
        {
            __WFE();
        }while (m_xfer_done == false);

       lps22hb_pressure_get();
        NRF_LOG_FLUSH();
    }
}
}

Parents
  • Hi,

    The driver in the SDK is cleaner and easier to use (though we do not provide any example). I recommend you use it (<SDK>components\drivers_ext\lps22hb\). It has a decent API and handles all low-level stuff for you. You should refer to the lps22hb.h header file for the (doxygen) documentation.

  • Thanks Einar, I have tried the driver in the SDK, but since I am not familiar with TWI, it did not work for me. I think I have missed something. Can you briefly describe the items needed to achieve my goal with the SDK drivers?

    I also went back and tried to modify the previous code and I managed to read the correct reading out of the register, but it is not updating new data. Can you check what might be the problem? I suspect it is the control register issue (there are three for LPS22hb). Thanks.

    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* Common addresses definition for temperature sensor. */
    #define LM75B_ADDR         0x5DU// (0x90U >> 1)
    
    #define LM75B_REG_TEMP      0x28U
    #define LM75B_REG_CON1      0x10U
    #define LM75B_REG_CON2     0x11U
    #define LM75B_REG_TOS       0x03U
    
    /* Mode for LM75B. */
    #define NORMAL_MODE 0U
    
    /* Indicates if operation on TWI has ended. */
    static volatile bool m_xfer_done = false;
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    /* Buffer for samples read from temperature sensor. */
    static uint8_t m_sample;
    
    
    void LM75B_enable(void)
    {
        ret_code_t err_code;
    
        /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
        uint8_t reg[2] = {LM75B_REG_CON1, 10U};
        err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, sizeof(reg), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    }
    
    /**
     * @brief Function for setting active mode on MMA7660 accelerometer.
     */
    void LM75B_set_mode(void)
    {
        ret_code_t err_code;
    
        /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
        uint8_t reg[2] = {LM75B_REG_CON2, 1U};
        err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, sizeof(reg), false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
        /* Writing to pointer byte. */
        reg[0] = LM75B_REG_TEMP+3;
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, 1, false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    }
    
    /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    __STATIC_INLINE void data_handler(uint8_t temp)
    {
        NRF_LOG_INFO("Temperature: %x Celsius degrees.", temp);
    }
    
    /**
     * @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_RX)
                {
                    data_handler(m_sample);
                }
                m_xfer_done = true;
                break;
            default:
                break;
        }
    }
    
    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_lm75b_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_lm75b_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()
    {
        m_xfer_done = false;
        ret_code_t err_code;
        
        err_code = nrf_drv_twi_rx(&m_twi, LM75B_ADDR, &m_sample, sizeof(m_sample));
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    }
    
    /**
     * @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 sensor example started.");
        NRF_LOG_FLUSH();
        twi_init();
        LM75B_set_mode();
    
        while (true)
        {
            nrf_delay_ms(500);
    
            do
            {
                __WFE();
            }while (m_xfer_done == false);
    
            read_sensor_data();
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */

  • Hi,

    Just one thing before we continue. Is the sensor a LM75B or a LPS22HB? I am confused as the question text refers to LPS22HB but the code refers to LM75B.

  • It is LPS22HB. I just followed the example of TWI_Sensor but did not change the texts. Sorry about the confusion.

Reply Children
Related