Weird log value format regarding temperature in Zigbee Weather Station application - bug?

Hello,

I've recently was checking out the Zigbee Weather Station application running on the Thingy53 and have spotted a weirdly formatted log message regarding temperature measurement.
Looks like the value was logged before it was converted to float so the sign character may be present in wrong place or possibly even duplicated. I think LOG_INF should be moved after the value is converted.

NCS tag: v2.9.0

Best regards,

Sebastian

Parents Reply
  • Sensor is working fine, only when temperature measured is below 0*C, log format has this issue.This is because how a sensor stores the value:

    And in the log the measurement is printed as two values (integer and fractional) - when temperature is below 0*C, fractional part can be negative and will be printed with minus character.

    So the temperature can be displayed as: [0.-980000] or [-1.-210000] but should be [-0.980000] or [-1.210000]

Children
  • Hi Sebastian,

    Good catch. I have reported it internally and will get back to you when I have an update.

    Best regards,
    Marte

  • Hi Sebastian,

    The developers confirmed that this was a bug. This will be fixed in the next release of the Zigbee add-on. In the meantime, here is the sensor.c file with the fix.

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/logging/log.h>
    
    #include "sensor.h"
    
    /*
     * Sensor value is represented as having an integer and a fractional part,
     * and can be obtained using the formula val1 + val2 * 10^(-6).
     */
    #define SENSOR_VAL2_DIVISOR 1000000
    
    LOG_MODULE_DECLARE(app, CONFIG_ZIGBEE_WEATHER_STATION_LOG_LEVEL);
    
    static const struct device *sensor;
    
    /*
     * Sensor value is represented as having an integer and a fractional part,
     * and can be obtained using the formula val1 + val2 * 10^(-6). Negative
     * values also adhere to the above formula, but may need special attention.
     * Here are some examples of the value representation:
     *
     *      0.5: val1 =  0, val2 =  500000
     *     -0.5: val1 =  0, val2 = -500000
     *     -1.0: val1 = -1, val2 =  0
     *     -1.5: val1 = -1, val2 = -500000
     */
    static float convert_sensor_value(struct sensor_value value)
    {
    	float result = 0.0f;
    
    	/* Determine sign */
    	result = (value.val1 < 0 || value.val2 < 0) ? -1.0f : 1.0f;
    
    	/* Use absolute values */
    	value.val1 = value.val1 < 0 ? -value.val1 : value.val1;
    	value.val2 = value.val2 < 0 ? -value.val2 : value.val2;
    
    	/* Calculate value */
    	result *= (value.val1 + value.val2 / (float)SENSOR_VAL2_DIVISOR);
    
    	return result;
    }
    
    int sensor_init(void)
    {
    	int err = 0;
    
    	if (sensor) {
    		LOG_WRN("Sensor already initialized");
    	} else {
    		sensor = DEVICE_DT_GET(DT_INST(0, bosch_bme680));
    		if (!sensor) {
    			LOG_ERR("Failed to get device");
    			err = ENODEV;
    		}
    	}
    
    	return err;
    }
    
    int sensor_update_measurements(void)
    {
    	int err = 0;
    
    	if (sensor) {
    		err = sensor_sample_fetch(sensor);
    	} else {
    		LOG_ERR("Sensor not initialized");
    		err = ENODEV;
    	}
    
    	return err;
    }
    
    int sensor_get_temperature(float *temperature)
    {
    	int err = 0;
    
    	if (temperature) {
    		if (sensor) {
    			struct sensor_value sensor_temperature;
    
    			err = sensor_channel_get(sensor,
    						 SENSOR_CHAN_AMBIENT_TEMP,
    						 &sensor_temperature);
    			if (err) {
    				LOG_ERR("Failed to get sensor channel: %d", err);
    			} else {
    				*temperature = convert_sensor_value(sensor_temperature);
    				LOG_INF("Sensor    T:%9.3f [*C]", *temperature);
    			}
    		} else {
    			LOG_ERR("Sensor not initialized");
    			err = ENODEV;
    		}
    	} else {
    		LOG_ERR("NULL param");
    		err = EINVAL;
    	}
    
    	return err;
    }
    
    int sensor_get_pressure(float *pressure)
    {
    	int err = 0;
    
    	if (pressure) {
    		if (sensor) {
    			struct sensor_value sensor_pressure;
    
    			err = sensor_channel_get(sensor,
    						 SENSOR_CHAN_PRESS,
    						 &sensor_pressure);
    			if (err) {
    				LOG_ERR("Failed to get sensor channel: %d", err);
    			} else {
    				*pressure = convert_sensor_value(sensor_pressure);
    				LOG_INF("Sensor    P:%9.3f [kPa]", *pressure);
    			}
    		} else {
    			LOG_ERR("Sensor not initialized");
    			err = ENODEV;
    		}
    	} else {
    		LOG_ERR("NULL param");
    		err = EINVAL;
    	}
    
    	return err;
    }
    
    int sensor_get_humidity(float *humidity)
    {
    	int err = 0;
    
    	if (humidity) {
    		if (sensor) {
    			struct sensor_value sensor_humidity;
    
    			err = sensor_channel_get(sensor,
    						 SENSOR_CHAN_HUMIDITY,
    						 &sensor_humidity);
    			if (err) {
    				LOG_ERR("Failed to get sensor channel: %d", err);
    			} else {
    				*humidity = convert_sensor_value(sensor_humidity); 
    				LOG_INF("Sensor    H:%9.3f [%%]", *humidity);
    			}
    		} else {
    			LOG_ERR("Sensor not initialized");
    			err = ENODEV;
    		}
    	} else {
    		LOG_ERR("NULL param");
    		err = EINVAL;
    	}
    
    	return err;
    }
    

    Best regards,
    Marte

Related