nRF5 SDK is not maintained anymore
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LM75B sensor mode transition failure

Hi, I'm using NXP LM75B temprature sensor based on nRF SDK's example code.

I would like to save power on this sensor.

I have prepared the code as follows:

/* Mode for LM75B. */
#define LM75B_MODE_NORMAL   0U
#define LM75B_MODE_SHUTDOWN 1U // Add

/**
 * @brief Function for setting sleep mode on LM75B temperature sensor.
 */
void LM75B_sdn_mode(void)
{
    ret_code_t err_code;

    /* Writing to LM75B_REG_CONF "1" set temperature sensor in SHUTDOWN mode. */
    uint8_t reg[2] = {LM75B_REG_CONF, LM75B_MODE_SHUTDOWN};
    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;
    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);
}

Following main() is work fine:

/**@brief Function for application main entry.
 */
int main(void)
{	
    uint32_t err_code;
    LmHandlerErrorStatus_t lm_Error_code;
	
    // Initialize logs.
    log_init();
    NRF_LOG_INFO("LoRaWan end-device started.");
	
    // Initialize clocks & power
    nrf_drv_clock_init();
    nrf_drv_clock_lfclk_request(NULL);
    nrf_pwr_mgmt_init();

    // Enable nRF52 DCDC
    NRF_POWER->DCDCEN = 1;

    // Initialize Scheduler and timer
    timers_init();

    // Initialize NVM
    NvmDataMgmtInit();
  		
    // Initialize TWI
    twi_init();

    // Initialize LM75B
    LM75B_set_mode();
    nrf_delay_ms(200);

    // Initialize LoRa chip.
    err_code = lora_hardware_init();
    APP_ERROR_CHECK(err_code);

    // Initialize transmission periodicity variable
    TxPeriodicity = APP_TX_DUTYCYCLE + randr(-APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND);
	
    // Initialize LoRaWan
    lm_Error_code = LmHandlerInit(&LmHandlerCallbacks, &LmHandlerParams);
    APP_ERROR_CHECK_BOOL(lm_Error_code == LORAMAC_HANDLER_SUCCESS);

    // Set system maximum tolerated rx error in milliseconds
    LmHandlerSetSystemMaxRxError(20);

    // The LoRa-Alliance Compliance protocol package should always be initialized and activated.
    LmHandlerPackageRegister(PACKAGE_ID_COMPLIANCE, &LmhpComplianceParams);

    // Start Join procedure
    LmHandlerJoin();

    StartTxProcess(LORAMAC_HANDLER_TX_ON_TIMER);
		
    // Enter main loop.
    for (;;)
    {
        // Process the LoRaMac events
        LmHandlerProcess();

        // Process application uplinks management
        UplinkProcess();

        // Process events managed by the scheduler
        app_sched_execute();

        if (IsMacProcessPending == 1)
        {
            // Clear flag and prevent MCU to go into low power modes.
            IsMacProcessPending = 0;
        }
        else
        {
            if (NRF_LOG_PROCESS() == false)
            {
                nrf_pwr_mgmt_run();
            }	
        }
    }
}

And the following code is also work fine (This is only a function test. No sensor is used.):

    // Initialize LM75B
//    LM75B_set_mode();
//    nrf_delay_ms(200);
    LM75B_sdn_mode();
    nrf_delay_ms(200);

But the following code stops with some error. (Normal mode -> Shutdown mode transition test.):

    // Initialize LM75B
    LM75B_set_mode();
    nrf_delay_ms(200);
    LM75B_sdn_mode();
    nrf_delay_ms(200);

I don't think the problem is caused by AD conversion timing since I put in 200mSec weighting.

I believe I am making a basic oversight. Do you know what the problem is?

thanks,

tyro

Parents
  • Hi,

    Try to modify LM75B_sdn_mode() by adding the following line before the first call to nrf_drv_twi_tx():

    m_xfer_done = false;

    If you have not changed LM75B_set_mode() from the default example, this flag is not cleared at the end of the function. When you call nrf_drv_twi_tx() in your new function and go to the while-loop to wait for the flag, the flag is already set and the function will not wait for the transfer to complete. When you call nrf_drv_twi_tx() the second time in this function, the first transfer is not completed, and the driver will report an error.

    Best regards,
    Jørgen

  • The advice I received solved the problem for now. The current consumption at power save state is 3uA. Switching the operation mode is now unified with LM75B_set_mode() using an argument.

    void LM75B_set_mode(bool opmode)
    {
        ret_code_t err_code;
    
        /* Writing to LM75B_REG_CONF "0" to Normal, "1" to SHUTDOWN mode. */
        uint8_t reg[2] = {LM75B_REG_CONF, opmode};
        m_xfer_done = false;
        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;
        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);
    }

    However, the details are still questionable.

    If NRF_LOG_INFO() is removed from follwing function, an [NRF_ERROR_BUSY] error occurs again.

    static void PrepareTxFrame(void)
    {
        if (LmHandlerIsBusy()) return;
    
        do { __WFE(); } while (m_xfer_done == false);
        NRF_LOG_INFO("PrepareTxFrame"); // <- If this line is removed, an error occurs.
        LM75B_set_mode(0);
        nrf_delay_ms(100);
    
        do { __WFE(); } while (m_xfer_done == false);
    
        read_sensor_data();
        NRF_LOG_FLUSH();
        LM75B_set_mode(1);
    
        uint8_t msg[8];
        msg[0] = 0x03; // 1byte Data Channel:3
        msg[1] = 0x67; // 1byte Data Type:Temperature Sensor
        msg[2] = tempC * 10 / 0x100; // 2byte
        msg[3] = fmodf(tempC * 10, 0x100);
        msg[4] = 0x05; // 1byte Data Channel:5
        msg[5] = 0x67; // 1byte Data Type:Temperature Sensor
        msg[6] = 0x00; // 2byte
        msg[7] = 0xFF; // example) 00FF 255 -> 25.5C
    
        AppData.Port = 2;
        memcpy(AppData.Buffer, msg, sizeof(msg));
        AppData.BufferSize = sizeof(msg);
    
        LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed);
    }

    It works correctly without the immediately preceding do...while syntax.

    Basically I am satisfied with the reduction in current consumption achieved. But it is curious that NRF_LOG_INFO syntax buys time to complete the TWI transfer.

    tyro

Reply
  • The advice I received solved the problem for now. The current consumption at power save state is 3uA. Switching the operation mode is now unified with LM75B_set_mode() using an argument.

    void LM75B_set_mode(bool opmode)
    {
        ret_code_t err_code;
    
        /* Writing to LM75B_REG_CONF "0" to Normal, "1" to SHUTDOWN mode. */
        uint8_t reg[2] = {LM75B_REG_CONF, opmode};
        m_xfer_done = false;
        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;
        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);
    }

    However, the details are still questionable.

    If NRF_LOG_INFO() is removed from follwing function, an [NRF_ERROR_BUSY] error occurs again.

    static void PrepareTxFrame(void)
    {
        if (LmHandlerIsBusy()) return;
    
        do { __WFE(); } while (m_xfer_done == false);
        NRF_LOG_INFO("PrepareTxFrame"); // <- If this line is removed, an error occurs.
        LM75B_set_mode(0);
        nrf_delay_ms(100);
    
        do { __WFE(); } while (m_xfer_done == false);
    
        read_sensor_data();
        NRF_LOG_FLUSH();
        LM75B_set_mode(1);
    
        uint8_t msg[8];
        msg[0] = 0x03; // 1byte Data Channel:3
        msg[1] = 0x67; // 1byte Data Type:Temperature Sensor
        msg[2] = tempC * 10 / 0x100; // 2byte
        msg[3] = fmodf(tempC * 10, 0x100);
        msg[4] = 0x05; // 1byte Data Channel:5
        msg[5] = 0x67; // 1byte Data Type:Temperature Sensor
        msg[6] = 0x00; // 2byte
        msg[7] = 0xFF; // example) 00FF 255 -> 25.5C
    
        AppData.Port = 2;
        memcpy(AppData.Buffer, msg, sizeof(msg));
        AppData.BufferSize = sizeof(msg);
    
        LmHandlerSend(&AppData, LmHandlerParams.IsTxConfirmed);
    }

    It works correctly without the immediately preceding do...while syntax.

    Basically I am satisfied with the reduction in current consumption achieved. But it is curious that NRF_LOG_INFO syntax buys time to complete the TWI transfer.

    tyro

Children
No Data
Related