Using BSEC with RAK431&1906 - IAQ not changing

RAK4631+1906 , RUI3, AT+VER=RUI_4.1.1_RAK4631
Mac OS, Arduino IDE
Code taken from the SmartFarm example and modified for the use with BSEC.

I am using the BSEC library to send temp, hum, pressure, and IAQ to TTN. I can obtain all the values from the sensor; however, the IAQ value remains at the initial value of 50. When using the basic.ino example for the BSEC library, everything works as expected, however in combination with LoRa the iaq value does not change any more.

type or paste code here

```cpp
/*************************************
 * Download RAK1901/RAK1902 library from https://downloads.rakwireless.com/RUI/RUI3/Library/
 * Besides, install them into Arduino IDE
 *************************************/

#include "bsec.h"
#include <CayenneLPP.h>

#define DEBUG false

// Helper functions declarations
void checkIaqSensorStatus(void);
void errLeds(void);

DynamicJsonDocument jsonBuffer(4096);
CayenneLPP lpp(51);
JsonArray root = jsonBuffer.to<JsonArray>();


void uplink_routine();

#define SMART_FARM_PERIOD   (30000)
/*************************************

   LoRaWAN band setting:
     RAK_REGION_EU433
     RAK_REGION_CN470
     RAK_REGION_RU864
     RAK_REGION_IN865
     RAK_REGION_EU868
     RAK_REGION_US915
     RAK_REGION_AU915
     RAK_REGION_KR920
     RAK_REGION_AS923

 *************************************/
#define SMART_FARM_BAND     (RAK_REGION_EU868)
#define SMART_FARM_DEVEUI   {XXXXXXXXXX....}
#define SMART_FARM_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define SMART_FARM_APPKEY   {XXXXXXXXXX...}

/** Temperature & Humidity sensor **/

Bsec iaqSensor;
String output;
/** Packet buffer for sending */
uint8_t collected_data[64] = { 0 };







void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
    if (data->BufferSize > 0) {
        Serial.println("Something received!");
        for (int i = 0; i < data->BufferSize; i++) {
            Serial.printf("%x", data->Buffer[i]);
        }
        Serial.print("\r\n");
    }
}

void joinCallback(int32_t status)
{
    Serial.printf("Join status: %d\r\n", status);
}

void sendCallback(int32_t status)
{
    if (status == 0) {
        Serial.println("Successfully sent");
    } else {
        Serial.println("Sending failed");
    }
}

void setup()
{
    Serial.begin(115200);
    delay(1000);
    pinMode(LED_BUILTIN, OUTPUT);
    iaqSensor.begin(BME68X_I2C_ADDR_LOW, Wire);
    output = "\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix);
    Serial.println(output);
    checkIaqSensorStatus();

    bsec_virtual_sensor_t sensorList[13] = {
    BSEC_OUTPUT_IAQ,
    BSEC_OUTPUT_STATIC_IAQ,
    BSEC_OUTPUT_CO2_EQUIVALENT,
    BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
    BSEC_OUTPUT_RAW_TEMPERATURE,
    BSEC_OUTPUT_RAW_PRESSURE,
    BSEC_OUTPUT_RAW_HUMIDITY,
    BSEC_OUTPUT_RAW_GAS,
    BSEC_OUTPUT_STABILIZATION_STATUS,
    BSEC_OUTPUT_RUN_IN_STATUS,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
    BSEC_OUTPUT_GAS_PERCENTAGE
  };
    
    iaqSensor.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
    checkIaqSensorStatus();
     
  
    Serial.println("RAKwireless Smart Farm Example");
    Serial.println("------------------------------------------------------");
  
    // OTAA Device EUI MSB first
    uint8_t node_device_eui[8] = SMART_FARM_DEVEUI;
    // OTAA Application EUI MSB first
    uint8_t node_app_eui[8] = SMART_FARM_APPEUI;
    // OTAA Application Key MSB first
    uint8_t node_app_key[16] = SMART_FARM_APPKEY;
  
    if (!api.system.lpm.set(1)) {
        Serial.printf("LoRaWan Smart Farm - set low power mode is incorrect! \r\n");
        return;
    }
  
    if (!api.lorawan.nwm.set()) {
        Serial.printf("LoRaWan Smart Farm - set network working mode is incorrect! \r\n");
        return;
    }
  
    if (!api.lorawan.appeui.set(node_app_eui, 8)) {
        Serial.printf("LoRaWan Smart Farm - set application EUI is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.appkey.set(node_app_key, 16)) {
        Serial.printf("LoRaWan Smart Farm - set application key is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.deui.set(node_device_eui, 8)) {
        Serial.printf("LoRaWan Smart Farm - set device EUI is incorrect! \r\n");
        return;
    }
  
    if (!api.lorawan.band.set(SMART_FARM_BAND)) {
        Serial.printf("LoRaWan Smart Farm - set band is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
        Serial.printf("LoRaWan Smart Farm - set device class is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.njm.set(RAK_LORA_OTAA))	// Set the network join mode to OTAA
    {
        Serial.printf("LoRaWan Smart Farm - set network join mode is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.join())	// Join to Gateway
    {
        Serial.printf("LoRaWan Smart Farm - join fail! \r\n");
        return;
    }
  
    Serial.println("++++++++++++++++++++++++++");
    Serial.println("RUI3 Environment Sensing");
    Serial.println("++++++++++++++++++++++++++");
  

   // Print the header
    output = "Timestamp [ms], IAQ, IAQ accuracy, Static IAQ, CO2 equivalent, breath VOC equivalent, raw temp[°C], pressure [hPa], raw relative humidity [%], gas [Ohm], Stab Status, run in status, comp temp[°C], comp humidity [%], gas percentage";
    Serial.println(output);

    /** Wait for Join success */
    while (api.lorawan.njs.get() == 0) {
        Serial.print("Wait for LoRaWAN join...");
        api.lorawan.join();
        delay(10000);
    }
  
    if (!api.lorawan.adr.set(true)) {
        Serial.printf("LoRaWan Smart Farm - set adaptive data rate is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.rety.set(1)) {
        Serial.printf("LoRaWan Smart Farm - set retry times is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.cfm.set(1)) {
        Serial.printf("LoRaWan Smart Farm - set confirm mode is incorrect! \r\n");
        return;
    }
  
    /** Check LoRaWan Status*/
    Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF");	// Check Duty Cycle status
    Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED");	// Check Confirm status
    uint8_t assigned_dev_addr[4] = { 0 };
    api.lorawan.daddr.get(assigned_dev_addr, 4);
    Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]);	// Check Device Address
    Serial.printf("Uplink period is %ums\r\n", SMART_FARM_PERIOD);
    Serial.println("");
    api.lorawan.registerRecvCallback(recvCallback);
    api.lorawan.registerJoinCallback(joinCallback);
    api.lorawan.registerSendCallback(sendCallback);
    if (api.system.timer.create(RAK_TIMER_0, (RAK_TIMER_HANDLER)uplink_routine, RAK_TIMER_PERIODIC) != true) {
        Serial.printf("LoRaWan Smart Farm - Creating timer failed.\r\n");
        return;
    }
    if (api.system.timer.start(RAK_TIMER_0, SMART_FARM_PERIOD, NULL) != true) {
        Serial.printf("LoRaWan Smart Farm - Starting timer failed.\r\n");
        return;
    }
}

void uplink_routine()
{
    /** Get sensor RAK1906 values */
      unsigned long time_trigger = millis();
      if (iaqSensor.run()) { // If new data is available
        digitalWrite(LED_BUILTIN, LOW);
        // Print the header
        output = "Timestamp [ms], IAQ, IAQ accuracy, Static IAQ, CO2 equivalent, breath VOC equivalent, raw temp[°C], pressure [hPa], raw relative humidity [%], gas [Ohm], Stab Status, run in status, comp temp[°C], comp humidity [%], gas percentage";
        Serial.println(output);
        output = String(time_trigger);
        output += ", " + String(iaqSensor.iaq);
        output += ", " + String(iaqSensor.iaqAccuracy);
        output += ", " + String(iaqSensor.staticIaq);
        output += ", " + String(iaqSensor.co2Equivalent);
        output += ", " + String(iaqSensor.breathVocEquivalent);
        output += ", " + String(iaqSensor.rawTemperature);
        output += ", " + String(iaqSensor.pressure);
        output += ", " + String(iaqSensor.rawHumidity);
        output += ", " + String(iaqSensor.gasResistance);
        output += ", " + String(iaqSensor.stabStatus);
        output += ", " + String(iaqSensor.runInStatus);
        output += ", " + String(iaqSensor.temperature);
        output += ", " + String(iaqSensor.humidity);
        output += ", " + String(iaqSensor.gasPercentage);
        
        Serial.println(output);
        digitalWrite(LED_BUILTIN, HIGH);
      } else {
        checkIaqSensorStatus();
      }
    float temp_f = iaqSensor.temperature;
    float humid_f = iaqSensor.humidity;
    float press_f = (iaqSensor.pressure / 100);
    float gas_f = iaqSensor.staticIaq;

    // Add battery voltage
    float battery_reading = 0.0;
	  for (int i = 0; i < 10; i++)
	  {
		  battery_reading += api.system.bat.get(); // get battery voltage
	  }
	  battery_reading = battery_reading / 10;
	 
    Serial.printf("T %.2f H %.2f P %.2f G %.2f B %.2f\r\n", temp_f, humid_f, press_f, gas_f, battery_reading);
  
   
/** Cayenne Low Power LPP Payload */

  lpp.reset();
  lpp.addTemperature(3, temp_f);
  lpp.addRelativeHumidity(4,humid_f);
  lpp.addBarometricPressure(5,press_f);
  lpp.addAnalogInput(6, gas_f);
  lpp.addAnalogInput(7, battery_reading);


    uint8_t data_len = 0;
    
    data_len = lpp.getSize();
    Serial.println("Data Packet:");
    Serial.print("Bytes sent : ");
    Serial.println(data_len);

  uint8_t *payload = lpp.getBuffer();

  for (unsigned char i = 0; i < data_len; i++)
  {
    Serial.print("0x");
    Serial.print(payload[i], HEX);
    Serial.print(" ");
  }
  
    Serial.println("---------------------");
  
  
  
    /** Send the data package */
    if (api.lorawan.send(data_len, lpp.getBuffer(), 2, true, 1)) {
        Serial.println("Sending is requested");
    } else {
        Serial.println("Sending failed");
    }
}

void loop()
{
    /* Destroy this busy loop and use timer to do what you want instead,
     * so that the system thread can auto enter low power mode by api.system.lpm.set(1); */
    api.system.scheduler.task.destroy();
}
// Helper function definitions
void checkIaqSensorStatus(void)
{
  if (iaqSensor.bsecStatus != BSEC_OK) {
    if (iaqSensor.bsecStatus < BSEC_OK) {
      output = "BSEC error code : " + String(iaqSensor.bsecStatus);
      Serial.println(output);
      for (;;)
        errLeds(); /* Halt in case of failure */
    } else {
      output = "BSEC warning code : " + String(iaqSensor.bsecStatus);
      Serial.println(output);
    }
  }

  if (iaqSensor.bme68xStatus != BME68X_OK) {
    if (iaqSensor.bme68xStatus < BME68X_OK) {
      output = "BME68X error code : " + String(iaqSensor.bme68xStatus);
      Serial.println(output);
      for (;;)
        errLeds(); /* Halt in case of failure */
    } else {
      output = "BME68X warning code : " + String(iaqSensor.bme68xStatus);
      Serial.println(output);
    }
  }
}

void errLeds(void)
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

How long do you let it run?
BSEC library from Bosch takes a long time before you get a valid output. It can be up to 3 hours.

Hi Bernd,

Running for about 2h+. I will update the post after 5h in case nothing changes.

You really have to be patient.
This is from a test I run last year. Comparison of the Bosch BSEC algo with an open-source alternative.
It took more than a day for the IAQ to finally change.

Hi, I was waiting for 48h but no change of iaq value. I figured that the bsec2 code does not work with the RUI3 smartfarm example. So I tried to change the firmware back to the original factory delivered bsp firmware version. but now i am unable to compile the environment monitoring sample any more. I am getting the error message ‘collect2.exe: error: ld returned 1 exit status’. the file Info_UF2 reads: ‘UF2 Bootloader 0.4.3
Model: WisBlock RAK4631 Board
Board-ID: WisBlock-RAK4631-Board
Date: May 20 2023
Ver: 0.4.3
SoftDevice: S140 6.1.1’
which seems to me, that the bootloader change was successful. I tried on Mac OS as well, but there I got the error message that my Python is missing some local. So now I am stuck. slight_smile. Before I changed the firmware, I was running the besc2 code without the smartfarm example and got values after 1-2 min; hence board and sensor are working fine. I just got somehow messed up with the firmware.