How to convert the gas resistance of bme680 sensor to IAQ in thingy53

Hi 
I am working on thingy53, Using Hello world application    NCS- 1.9.1

So I have enable the bme680 sensor of thingy53

I received the values for temp, pressure, humidity, gas resistance. ------How to change this gas resistance to IAQ value in thingy53-----  

This is my main.c 

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <drivers/sensor.h>

void main(void)
{
	
	const struct device *bme = DEVICE_DT_GET_ONE(bosch_bme680);
	struct sensor_value temp, press, humidity, gas_res;


	if (!device_is_ready(bme)) {
		printk("sensor: device not ready.\n");
		return;
	}
	printk("Device %p name is %s\n", bme, bme->name);

	while (1) {
		k_sleep(K_MSEC(3000));

		sensor_sample_fetch(bme);
		sensor_channel_get(bme, SENSOR_CHAN_AMBIENT_TEMP, &temp);
		sensor_channel_get(bme, SENSOR_CHAN_PRESS, &press);
		sensor_channel_get(bme, SENSOR_CHAN_HUMIDITY, &humidity);
		sensor_channel_get(bme, SENSOR_CHAN_GAS_RES, &gas_res);

		printk("T: %d.%06d | P: %d.%06d | H: %d.%06d | G: %d.%06d\n",
				temp.val1, temp.val2, press.val1, press.val2,
				humidity.val1, humidity.val2, gas_res.val1,
				gas_res.val2);
	}
}

And this is the output on RTT monitor

I have gone through many tickets but didn't find a solution.

Please help

Parents Reply Children
  • I followed every step as rtlab said.

    I am facing  error  " error: '../libs/lib_bsec/src/libalgobsec.a', needed by 'zephyr/zephyr_pre0.elf', missing and no known rule to make it"  when I add these lines in my CMake

     zephyr_library_import(lib_bsec ${CMAKE_CURRENT_SOURCE_DIR}/libs/lib_bsec/src/libalgobsec.a)
     target_include_directories(app PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libs/lib_bsec/include)
     target_link_libraries(lib_bsec INTERFACE kernel)
     target_link_libraries(app PRIVATE lib_bsec)

    I am on step of adding  bsec_sensor_control(); to my file 

  • The error indicates that the library was not found. Maybe the library path is incorrect. Either way, please try to link in the library like I did in this modified hello world sample:

     hello_world_with_static_lib.zip

    You should not need to use a Makefile as suggested in rtlab's answer. 

  • Hi 
    Thank you for being so helpful

    I have tested according to your suggestion, and now that error is resolved but facing another error

    Please have a look at my CMake list now

    # SPDX-License-Identifier: Apache-2.0
    
    cmake_minimum_required(VERSION 3.20.0)
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(peripheral)
    
    target_sources(app PRIVATE
      src/main.c
      src/bms_serial.c
     )
    
    
    set(LIB_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/BSEC_2.2.0.0_Generic_Release_30052022/algo/normal_version/bin/gcc/Cortex_M33)
    target_include_directories(app PUBLIC ${LIB_DIR})
    
    zephyr_library_link_libraries(${LIB_DIR}/libalgobsec.a)

    I have added CONFIG_NEWLIB_LIBC=y in prj as well

    Here is my bme688.c file 

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <kernel.h>
    #include <drivers/sensor.h>
    #include <sys/printk.h>
    #include "D:/firmware/zephyr/samples/bluetooth/peripheral/BSEC_2.2.0.0_Generic_Release_30052022/algo/normal_version/bin/gcc/Cortex_M33/bsec_interface.h"
    
    // #include <logging/log.h>
    // #define LOG_MODULE_NAME bme680_sensor
    // LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    char temperature[10];
    char pressure[10];
    char humidity_sensor[10];
    char aqi[10];
    static struct bt_conn *current_conn;
    
    void env_sensor(char flash_buffer[])
    {
    	const struct device *bme = DEVICE_DT_GET_ONE(bosch_bme680);
    	struct sensor_value temp, press, humidity, gas_res;
    	char ble_tx_string[50];
    	int ret;
    	int64_t unix_timestamp_ns = 0;
    	float iaq = 0.0f;
    	float static_iaq = 0.0f;
        
    
    	if (!device_is_ready(bme)) {
    		printk("BME680: device not ready./n");
    		return;
    	}
    	
    		sensor_sample_fetch(bme);
    		sensor_channel_get(bme, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    		sensor_channel_get(bme, SENSOR_CHAN_PRESS, &press);
    		sensor_channel_get(bme, SENSOR_CHAN_HUMIDITY, &humidity);
    		sensor_channel_get(bme, SENSOR_CHAN_GAS_RES, &gas_res);
    
    		
            snprintk(temperature,10,"%d.%02d",temp.val1, temp.val2);
    		snprintk(pressure,10,"%d.%02d",press.val1, press.val2);
    		snprintk(humidity_sensor,10,"%d.%02d",humidity.val1, humidity.val2);
    		snprintk(aqi,15,"%d.%02d",gas_res.val1,gas_res.val2);
    
    
    		bsec_init();
    			// Allocate variables
    			uint8_t serialized_settings[BSEC_MAX_PROPERTY_BLOB_SIZE];
    			uint32_t n_serialized_settings_max = BSEC_MAX_PROPERTY_BLOB_SIZE;
    			uint8_t work_buffer[BSEC_MAX_WORKBUFFER_SIZE];
    			uint32_t n_work_buffer = BSEC_MAX_WORKBUFFER_SIZE;
    		ret = bsec_set_configuration(serialized_settings, n_serialized_settings_max, work_buffer, n_work_buffer);
    		
    			bsec_sensor_configuration_t requested_virtual_sensors[0];
    			uint8_t n_requested_virtual_sensors = 1;
    			requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ;
    			requested_virtual_sensors[0].sample_rate = BSEC_SAMPLE_RATE_LP;
    			// Allocate a struct for the returned physical sensor settings
    			bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
    			uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
    		bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings, &n_required_sensor_settings);
    			date_time_now(&unix_timestamp_ns);
    			unix_timestamp_ns = unix_timestamp_ns/1000000;
    			bsec_bme_settings_t run_gas[1];
    		bsec_sensor_control(unix_timestamp_ns,run_gas);
    
    		 // Allocate input and output memory
    		bsec_input_t input[3];
    		uint8_t n_input = 3;
    		bsec_output_t output[2];
    		uint8_t  n_output=2;
    
    		bsec_library_return_t status;
    
    		// Populate the input structs, assuming the we have timestamp (ts), 
    		// gas sensor resistance (R), temperature (T), and humidity (rH) available
    		// as input variables
    		input[0].sensor_id = BSEC_INPUT_GASRESISTOR;
    		input[0].signal = gas_res.val1;
    		input[0].time_stamp= unix_timestamp_ns;   
    		input[1].sensor_id = BSEC_INPUT_TEMPERATURE;   
    		input[1].signal = temp.val1;   
    		input[1].time_stamp= unix_timestamp_ns;   
    		input[2].sensor_id = BSEC_INPUT_HUMIDITY;
    		input[2].signal = humidity.val1;
    		input[2].time_stamp= unix_timestamp_ns;   
    
    			
    		// Invoke main processing BSEC function
    		status = bsec_do_steps( input, n_input, output, &n_output );
    
    		// Iterate through the BSEC output data, if the call succeeded
    		if(status == BSEC_OK)
    		{
    			for(int i = 0; i < n_output; i++)
    			{   
    				switch(output[i].sensor_id)
    				{
    					case BSEC_OUTPUT_IAQ:
    						iaq = output[i].signal;
    						// Retrieve the IAQ results from output[i].signal
    						// and do something with the data
    						break;
    					case BSEC_OUTPUT_STATIC_IAQ:
    						static_iaq = output[i].signal;
    						// Retrieve the static IAQ results from output[i].signal
    						// and do something with the data
    						break;
    					
    				}
    			}
    		}
    
    		
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"temp %s",temperature);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,20,"temp %s#",temperature);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"hum %s",humidity_sensor);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(humidity_sensor)+15,"hum %s#",humidity_sensor);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"atmp %s",pressure);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(pressure)+15,"atmp %s#",pressure);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"bsec_iaq %s",aqi);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(aqi)+20,"bsec_iaq %s#",aqi);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    		// printk("T: %d.%d | P: %d.%02d | H: %d.%02d | G: %d.%02d/n",
    		// 		temp.val1, temp.val2, press.val1, press.val2,
    		// 		humidity.val1, humidity.val2, gas_res.val1,
    		// 		gas_res.val2);
    	}
    	
    

    If you look into this I have not used the variable of lines 106 and 111, I will replace the AQI with these variables later. 

    Please help as this is a very important task which has been pending for 2 months

  • Hi,

    The linker errors indicate that your app is built with the FPU enabled. In that case, you must use the FPU enabled variant of the library located in /algo/normal_version/bin/gcc/Cortex_M33and not the one in /algo/normal_version/bin/gcc/Cortex_M33. 

  • Thanks, now the build is successful,

    The modified bme688 file is attached below, there are two problems 

    1. CPU is not recognising if(status == BSEC_OK) as true, so therefore not moving in.

    2. When I am printing the iaq = output[i].signal;  it is showing the 50 value constantly, I have observed that the gas resistance is Constant all the time at  12917167

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <kernel.h>
    #include <drivers/sensor.h>
    #include <sys/printk.h>
    #include "D:/firmware/zephyr/samples/bluetooth/peripheral/BSEC_2.2.0.0_Generic_Release_30052022/algo/normal_version/bin/gcc/Cortex_M33/bsec_interface.h"
    
    // #include <logging/log.h>
    // #define LOG_MODULE_NAME bme680_sensor
    // LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    char temperature[10];
    char pressure[10];
    char humidity_sensor[10];
    char aqi[10];
    static struct bt_conn *current_conn;
    
    void env_sensor(char flash_buffer[])
    {
    	const struct device *bme = DEVICE_DT_GET_ONE(bosch_bme680);
    	struct sensor_value temp, press, humidity, gas_res;
    	char ble_tx_string[50];
    	int ret;
    	int64_t unix_timestamp = 0;
    	float unix_timestamp_ns = 0.0f;
    	float iaq = 0.0f;
    	float static_iaq = 0.0f;
        
    
    	if (!device_is_ready(bme)) {
    		printk("BME680: device not ready./n");
    		return;
    	}
    	
    		sensor_sample_fetch(bme);
    		sensor_channel_get(bme, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    		sensor_channel_get(bme, SENSOR_CHAN_PRESS, &press);
    		sensor_channel_get(bme, SENSOR_CHAN_HUMIDITY, &humidity);
    		sensor_channel_get(bme, SENSOR_CHAN_GAS_RES, &gas_res);
    
    		
            snprintk(temperature,10,"%d.%02d",temp.val1, temp.val2);
    		snprintk(pressure,10,"%d.%02d",press.val1, press.val2);
    		snprintk(humidity_sensor,10,"%d.%02d",humidity.val1, humidity.val2);
    		snprintk(aqi,15,"%d.%02d",gas_res.val1,gas_res.val2);
    
    
    		bsec_init();
    			// Allocate variables
    			uint8_t serialized_settings[BSEC_MAX_PROPERTY_BLOB_SIZE];
    			uint32_t n_serialized_settings_max = BSEC_MAX_PROPERTY_BLOB_SIZE;
    			uint8_t work_buffer[BSEC_MAX_WORKBUFFER_SIZE];
    			uint32_t n_work_buffer = BSEC_MAX_WORKBUFFER_SIZE;
    		ret = bsec_set_configuration(serialized_settings, n_serialized_settings_max, work_buffer, n_work_buffer);
    		
    			bsec_sensor_configuration_t requested_virtual_sensors[1];
    			uint8_t n_requested_virtual_sensors = 1;
    			requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ;
    			requested_virtual_sensors[0].sample_rate = BSEC_SAMPLE_RATE_LP;
    			// Allocate a struct for the returned physical sensor settings
    			bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
    			uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
    		bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings, &n_required_sensor_settings);
    			date_time_now(&unix_timestamp);
    			unix_timestamp_ns = unix_timestamp*1000000;
    			bsec_bme_settings_t run_gas[1];
    		bsec_sensor_control(unix_timestamp_ns,run_gas);
    
    		// Allocate input and output memory
    		bsec_input_t input[3];
    		uint8_t n_input = 3;
    		bsec_output_t output[2];
    		uint8_t  n_output=2;
    
    		bsec_library_return_t status;
    
    		// Populate the input structs, assuming the we have timestamp (ts), 
    		// gas sensor resistance (R), temperature (T), and humidity (rH) available
    		// as input variables
    		input[0].sensor_id = BSEC_INPUT_GASRESISTOR;
    		input[0].signal = gas_res.val1;
    		input[0].time_stamp= unix_timestamp_ns;   
    		input[1].sensor_id = BSEC_INPUT_TEMPERATURE;   
    		input[1].signal = temp.val1;   
    		input[1].time_stamp= unix_timestamp_ns;   
    		input[2].sensor_id = BSEC_INPUT_HUMIDITY;
    		input[2].signal = humidity.val1;
    		input[2].time_stamp= unix_timestamp_ns;   
    
    			
    		// Invoke main processing BSEC function
    		status = bsec_do_steps( input, n_input, output, &n_output );
    
    		// Iterate through the BSEC output data, if the call succeeded
    		if(status == BSEC_OK)
    		{
    			for(int i = 0; i < n_output; i++)
    			{   
    				switch(output[i].sensor_id)
    				{
    					case BSEC_OUTPUT_IAQ:
    						iaq = output[i].signal;
    						// Retrieve the IAQ results from output[i].signal
    						// and do something with the data
    						break;
    					case BSEC_OUTPUT_STATIC_IAQ:
    						static_iaq = output[i].signal;
    						// Retrieve the static IAQ results from output[i].signal
    						// and do something with the data
    						break;
    					
    				}
    			}
    		}
    
    			// printk("IAQ = %f\n",output[0].signal);
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"temp %s",temperature);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,20,"temp %s#",temperature);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"hum %s",humidity_sensor);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(humidity_sensor)+15,"hum %s#",humidity_sensor);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"atmp %s",pressure);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(pressure)+15,"atmp %s#",pressure);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    
    			memset(ble_tx_string,'/0',50);			
    			if(current_conn != NULL){
    				sprintf(ble_tx_string,"bsec_iaq %s",aqi);
    				bt_nus_send (NULL,ble_tx_string, strlen(ble_tx_string));}
    			else {
    				snprintk(ble_tx_string,sizeof(aqi)+20,"bsec_iaq %s#",aqi);k_msleep(500);
    				snprintk(flash_buffer+strlen(flash_buffer),strlen(ble_tx_string)+1,ble_tx_string);}
    		// printk("T: %d.%d | P: %d.%02d | H: %d.%02d | G: %d.%02d/n",
    		// 		temp.val1, temp.val2, press.val1, press.val2,
    		// 		humidity.val1, humidity.val2, gas_res.val1,
    		// 		gas_res.val2);
    	}
    	
    

    Please help

    Edited:- I read in the docs bsec_bme_settings_t::next_call field is used to determine the frequency between measurements.   Please goto line 71 in above file,you will see I have only added run_gas[1], should I need to add more, If yes then what to add and what to write in the respective fields 

    P.S- I only need IAQ 

Related