Internal temperature measurement with Zephyr

Hi,

using the example from  STM32 Temperature Sensor I was able to create a working program that displayed the MCU die temperature in degrees Celsius every second.

After measuring the duration of the sensor_sample_fetch() function, it turned out to be about 400 us. In the nRF52832 Product Specification, the duration of temperature measurement is 36 us so I guess that there is a problem here, because the measurement time should not be an order of magnitude greater than in the specification, even despite the use of drivers.I thought that since the previous function fetch all channels, I would try to use sensor_sample_fetch_chan(), which may reduce the function duration, but the timing result was the same as using sensor_sample_fetch().

Should sensor_sample_fetch() really take so long, or can't it be shortened in some way?

I care about efficient operation and low power consumption of the device I am developing so I am very concerned about reducing the temperature measurement time.
Without using any drivers the function duration is as expected and takes no more than 40 us. In the future I plan to add BT communication to the project so I can't use this solution because it conflicts with Soft Device.
Using NRFX drivers the function duration is also about 40 us, but I can't use them either for the reason mentioned above.

  • Hi,

    If you are planning to add BLE functionality to the project, can you check if mpsl_temperature_get() gives faster run time?

    400us sound very long for getting a temperature reading. Can you post the sample you used for testing this? 

    Best regards,
    Jørgen

  • Hi, Jørgen here is code that uses sensor_sample_fetch_chan():

    #include <zephyr/zephyr.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/sensor.h>
    #include <zephyr/logging/log.h>
    
    LOG_MODULE_REGISTER(Info, LOG_LEVEL_INF);
    
    static const struct device *temp_dev = DEVICE_DT_GET_ANY(nordic_nrf_temp);
    
    /*** Time measure functions ***/
    void Duration_Timer_Init()
    {
    	NRF_TIMER4->TASKS_START = 1;
    	NRF_TIMER4->PRESCALER = 1;
    }
    
    void Duration_Timer_Start()
    {
    	NRF_TIMER4->TASKS_CLEAR = 1;
    	NRF_TIMER4->TASKS_CAPTURE[0] = 1;
    }
    
    void Duration_Timer_Stop()
    {
    	NRF_TIMER4->TASKS_CAPTURE[1] = 1;
    	uint32_t start = NRF_TIMER4->CC[0];
    	uint32_t stop = NRF_TIMER4->CC[1];
    	LOG_INF("Function duration [us]: %d", (stop - start) >> 3);	
    }
    
    /*** Performs a temperature measurement of the MCU and returns its value in degrees C ***/
    static int16_t Temperature_Sensor_Get_Data()
    {
    	struct sensor_value temp_value;
    	int err;
    
    	Duration_Timer_Start();
        err = sensor_sample_fetch_chan(temp_dev, SENSOR_CHAN_DIE_TEMP);
    	Duration_Timer_Stop();
    
        if(err) 
            LOG_ERR("sensor_sample_fetch failed with error: %d", err);
    
        err = sensor_channel_get(temp_dev, SENSOR_CHAN_DIE_TEMP, &temp_value);
        if(err) 
            LOG_ERR("sensor_channel_get failed with error: %d", err);
    
        return temp_value.val1;
    }
    
    /*** Main ***/
    void main(void)
    {
    	Duration_Timer_Init();
    
    	while(1)
    	{
    		k_msleep(1000);
    		LOG_INF("MCU temperature [C]: %d", Temperature_Sensor_Get_Data());
    	}
    }

    and here is the log:

    [00:00:02.001,159] <inf> Info: Function duration [us]: 480
    [00:00:02.001,190] <inf> Info: MCU temperature [C]: 23
    [00:00:03.001,739] <inf> Info: Function duration [us]: 481
    [00:00:03.001,770] <inf> Info: MCU temperature [C]: 23
    [00:00:04.002,319] <inf> Info: Function duration [us]: 480
    [00:00:04.002,319] <inf> Info: MCU temperature [C]: 23

    prj.conf:

    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_SHOW_COLOR=y
    
    # Enable multithreading
    CONFIG_MULTITHREADING=y
    
    # TIMER 4
    CONFIG_NRFX_TIMER4=y
    
    # Sensor
    CONFIG_SENSOR=y
    
    # Enable internal oscillator
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
    
    # Enable MPU
    CONFIG_ARM_MPU=y
    
    # Enable hardware stack protection
    CONFIG_HW_STACK_PROTECTION=y
    
    # Configure GPIO as pin RESET
    CONFIG_GPIO_AS_PINRESET=y

    I don't know why, but it seems that the addition of the CONFIG_BT=y in the prj.conf reduces the duration of this function from 480 us to 38 us. The mpsl_temperature_get() also takes 38 us. The problem seems to be solved, thank you for your help.

Related