double calc_voc_BME(){ //Read register with humidity settings, rewrite setting over-sampling to 1x uint8_t humdity_settings = read_register(0x77,0x72); uint8_t new_settings = ((humdity_settings >> 3) << 3) | 0b001; write_register(0x77,0x72,new_settings); //Set temperature and pressure over-sampling to 1x write_register(0x77,0x74,0b00100100); //Set gas_wait_0 (address 0x64) to 0x59. This corresponds to 100 ms timing write_register(0x77,0x64,0x59); //Calculate target heater resistance based off setting temperature to 300C: //Get parameters uint8_t par_g1 = read_register(0x77,0xED); uint8_t par_g2_lsb = read_register(0x77,0xEB); uint8_t par_g2_msb = read_register(0x77,0xEC); uint8_t par_g3 = read_register(0x77,0xEE); uint8_t res_heat_range_full = read_register(0x77,0x02); //just bits <5:4> int8_t res_heat_val = read_register(0x77,0x00); //Combine parameters, par_g2 most and least significant bits, and get bits 5 and 4 from res_heat_range uint16_t par_g2 = (par_g2_msb<<8) | par_g2_lsb; //To get bits 5 and 4, take the right half of the left half to just get the 2 bits: uint8_t res_heat_range = ((res_heat_range_full >> 4) & 0b0011); //Set target temperature to 200: double target_temp = 300; //Get ambient temperature to be included in calculation below: double amb_temp = calc_temp_BME(); //Do actual calculation to get res_heat_0: double var1 = ((double)par_g1 / 16.0) + 49.0; double var2 = (((double)par_g2 / 32768.0) * 0.0005) + 0.00235; double var3 = (double)par_g3 / 1024.0; double var4 = var1 * (1.0 + (var2 * (double)target_temp)); double var5 = var4 + (var3 * (double)amb_temp); uint8_t res_heat_0 = (uint8_t)(3.4 * ((var5 * (4.0 / (4.0 + (double)res_heat_range)) * (1.0/(1.0 + ((double)res_heat_val * 0.002)))) - 25)); //Set res_heat_0 (0x5A) to the res_heat_0 value calculated write_register(0x77,0x5A,res_heat_0); //Set nb_conv<3:0> (0x71 <3:0>) to 0x0 AND run_gas_h (0x71 bit 6) to 1, first by reading register, replacing the necessary bits, then rewriting uint8_t ctrl_gas = read_register(0x77,0x71); uint8_t ctrl_gas_7_6 = ctrl_gas >> 6; uint8_t ctrl_gas_4_0 = ctrl_gas & 0b00011111; //Replace bit 5 with 1 uint8_t mid_ctrl_gas = (((ctrl_gas_7_6 << 1) | 1) << 5) | ctrl_gas_4_0; //Replace bits 3:0 with 0s uint8_t final_ctrl_gas = (mid_ctrl_gas >> 4) << 4; write_register(0x77,0x71,final_ctrl_gas); //Set mode<1:0> to 0b01 (forced mode), keeping over-sampling at 1x write_register(0x77,0x74,0b00100101); vTaskDelay(50 / portTICK_PERIOD_MS); //Check new_data uint8_t meas_status = read_register(0x77,0x3f); uint8_t new_data = meas_status >> 7; printf("\nnew_data: %x\n", new_data); //Get gas_valid_r(0x4f bit 5) and heat_stab_r (0x4f bit 4) as indicators of if read was successful uint8_t gas_r_lsb = read_register(0x77,0x4f); uint8_t heat_stab_r = (gas_r_lsb & 0x00011111) >> 4; uint8_t gas_valid_r = (gas_r_lsb & 0x00111111) >> 5; printf("\nheat_stab_r: %x", heat_stab_r); printf("\ngas_valid_r: %x\n", gas_valid_r); //Calculate VOC //Get all needed values through reading registers uint8_t gas_adc_lsb_gas_range = read_register(0x77,0x2D); uint8_t gas_adc_msb = read_register(0x77,0x2C); //gas_adc lsb is in bits 7:6 of register 2d uint8_t gas_adc_lsb = gas_adc_lsb_gas_range >> 6; //gas_range is in bits 3:0 of register 2d uint8_t gas_range = gas_adc_lsb_gas_range & 0x0F; //Combine msb and lsb for gas_adc int8_t gas_adc = (gas_adc_msb << 2) | gas_adc_lsb; //Perform calculation uint32_t var1_1 = UINT32_C(262144) >> gas_range; uint32_t var2_1 = (int32_t)gas_adc - INT32_C(512); var2_1 *= INT32_C(3); var2_1 = INT32_C(4096) + var2_1; double gas_res = 1000000.0f * (float)var1_1 / (float)var2_1; return gas_res; }