POC Breath using SMD commercial sensors
Dependencies: iAQ_Core Adafruit_SGP30_mbed mbed BME680
main.cpp
- Committer:
- christodoulos
- Date:
- 2020-06-14
- Revision:
- 10:aad246b57873
- Parent:
- 9:81d1b4833516
File content as of revision 10:aad246b57873:
#include "mbed.h" #include "flow.h" #include <math.h> #include "iAQ_Core.h" #include "Adafruit_SGP30.h" #include"BME680.h" ///////////////////////// // In this version of the program developed for the Breath project, flow and CO2, as well as 8 channel sensors, // are measured in a separate .h file called: "flow.h" which is included in the // main code. So 10 sets of data is streamed using a serial connection (TTL cable or Bluetooth) // without any intruption. // This version is especially suitable to be used for KST. // Also, a solenoid would be turned on and off based on calculating the standard deviation in CO2 profile. // // START POINT: calculates SD for 9 samples of CO2, if it's grater than 0.02 it enables the solenoid. // END POINT: calculates SD for 9 samples of CO2, if it's grater thatn 0.05 it disables the solenoid. // // You can easily change the threshold of Standard deviation to detect plateau // // Generated by: Mehrnaz Javadipour ////////////////////////// Serial ttl(PC_12,PD_2); //TTL cable TX,RX DigitalOut sol(PC_5); //Solenoid: Digital Output PwmOut led(PB_6); Timer stream; ///SENSOR SETUP/// BME680 myBME680 ( PC_1,PC_0, 400000 ); //BME680 iAQ_Core myiAQ_Core ( PB_11_ALT0,PB_10_ALT0, iAQ_Core::iAQ_Core_ADDRESS ); //iAQ-Core C Adafruit_SGP30 sgp30(PB_14,PB_13); // SGP30 I2C ZMODtemp(PB_9, PB_8); //ZMOD and Si7050 iAQ_Core::iAQ_Core_status_t aux; iAQ_Core::iAQ_Core_data_t myiAQ_Core_data; ///BME680 EXTRA FUNCTIONS/// Ticker newReading; uint32_t myState = 0; //@brief FUNCTION PROTOTYPES void changeDATA ( void ); void user_delay_ms ( uint32_t period ); int8_t user_i2c_read ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ); int8_t user_i2c_write ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ); void changeDATA ( void ) { myState = 1; } void user_delay_ms ( uint32_t period ) { wait( 0.01 ); } int8_t user_i2c_read ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) { int8_t rslt = 0; // Return 0 for Success, non-zero for failure uint32_t aux = 0; aux = myBME680._i2c.write ( dev_id, (char*)®_addr, 1, true ); aux = myBME680._i2c.read ( dev_id, (char*)®_data[0], len ); if ( aux == 0 ) { rslt = 0; } else { rslt = 0xFF; } return rslt; } int8_t user_i2c_write ( uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len ) { int8_t rslt = 0; // Return 0 for Success, non-zero for failure uint32_t aux = 0; char cmd[16] = { 0 }; uint32_t i = 0; // Prepare the data to be sent cmd[0] = reg_addr; for ( i = 1; i <= len; i++ ) { cmd[i] = reg_data[i - 1]; } // Write data aux = myBME680._i2c.write ( dev_id, &cmd[0], len + 1, false ); if ( aux == 0 ) { rslt = 0; } else { rslt = 0xFF; } return rslt; } ///END SENSOR SETUP/// int main() { ttl.baud(115200); //baudrate for the serial connection, 9600 for hc05 115200 for rn ttl.printf("$");//enter command mode only for rn wait(0.5); ttl.printf("$$");//enter command mode wait(0.5); ttl.printf("SN,POC Breath\r");//set new name wait(0.5); ttl.printf("SS,C0\r");//set transparent uart wait(0.5); ttl.printf("&,86DA9DA1FBA2\r");//Assign mac wait(0.5); ttl.printf("---\r");//enter data mode wait(0.5); ///SENSOR INITIALISATION/// ///IAQ DOESN'T REQUIRE INITIALISATION/// ///SGP30/// sgp30.begin();//begin sgp30 sgp30.IAQinit();//initialise sgp30 ///BME680// struct bme680_dev gas_sensor; gas_sensor.dev_id = BME680_I2C_ADDR_PRIMARY; gas_sensor.intf = BME680_I2C_INTF; gas_sensor.read = user_i2c_read; gas_sensor.write = user_i2c_write; gas_sensor.delay_ms = user_delay_ms; // amb_temp can be set to 25 prior to configuring the gas sensor // or by performing a few temperature readings without operating the gas sensor. gas_sensor.amb_temp = 25; int8_t rslt = BME680_OK; rslt = myBME680.bme680_init ( &gas_sensor ); uint8_t set_required_settings; // Set the temperature, pressure and humidity settings gas_sensor.tph_sett.os_hum = BME680_OS_2X; gas_sensor.tph_sett.os_pres = BME680_OS_4X; gas_sensor.tph_sett.os_temp = BME680_OS_8X; gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3; // Set the remaining gas sensor settings and link the heating profile gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; // Create a ramp heat waveform in 3 steps gas_sensor.gas_sett.heatr_temp = 320; // degree Celsius gas_sensor.gas_sett.heatr_dur = 150; // milliseconds // Select the power mode // Must be set before writing the sensor configuration gas_sensor.power_mode = BME680_FORCED_MODE; // Set the required sensor settings needed set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; // Set the desired sensor configuration rslt = myBME680.bme680_set_sensor_settings ( set_required_settings, &gas_sensor ); // Set the power mode rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); // Get the total measurement duration so as to sleep or wait till the measurement is complete uint16_t meas_period; myBME680.bme680_get_profile_dur ( &meas_period, &gas_sensor ); struct bme680_field_data data; newReading.attach( &changeDATA, 1 ); // the address of the function to be attached ( changeDATA ) and the interval ( 1s ) //END BME680/// ///ZMOD AND TEMP/// int ZMODTEMPaddr=0x80; //si7050 8bit address char wTemp[1]; wTemp[0]=0xE3; //Hold master mode char rTemp[2]; //Temperature returns MSB and LSB //assume MBS in rTemp[0] and LSB in rTemp[1] char wInit[2]; wInit[0]=0xE6; //User register 1 wInit[1]=0x00; //Set 14 bit resolution, other read-ony registers shouldn't be affected ZMODtemp.write(ZMODTEMPaddr,wInit,2); ///END ZMOD AND TEMP/// ///END SENSOR INITIALISATION/// flow(); //calling flow from flow.h carbon(); //calling CO2 from flow.h s1(); //calling 8 channels from flow.h s2(); s3(); s4(); s5(); s6(); s7(); s8(); getTemp(); //calling Temperature from flow.h ////////////////////////////// // I defined a flag for each section of specific functions, so by enabling the // flag the section starts and by disabling the flag it finishes the section. // at the end of the program, I reset the flags so it would be ready for the next loop. ///////////////////////////// int bf=0; //FLAG for detecting base flow int i=0; float bfArray[4]; //sampling flow for finding the average base flow float sf=0; //sum of flow samples for calculating base flow float fv=0; //final value of base flow int measurement_started=0; //FLAG for starting calculations after detecting breath int solstart=0; //FLAG for starting calculations for detecting plateau int m=0; int myArray[9]; //sampling 9 values of CO2 unsigned int sum=0; //sum of 9 samples of CO2 int avg=0; //average of 9 samples of CO2 int difSum=0; //used for the Standard deviation algorithm long double var=0.0; //used for the Standard deviation algorithm float sigma=0.0; //final value for standar deviation int flags=0; //FLAG for keep taking samples from CO2 profile when it's too early to detect plateau int solend=0; //FLAG for ending calculations for detecting plateau unsigned int sum2=0; //same as before; used for finding standard deviation long double var2=0.0; float sigma2=0.0; int difSum2=0; int avg2=0; int flage=0; //FLAG for keep taking samples from CO2 profile when it's too early to finish plateau int fin=0; wait(1); sol=1;//sol off 1 while(1) { //led=0.4f; //an LED is fully turned on at the beginning, the brightness will be reduced when the plateau is detected. //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset wait(0.01); if (bf==0) { //finding base flow before breath for(i=0; i<4; i++) { bfArray[i]=flow(); sf+=bfArray[i]; } fv=sf/4; //fv=fv+0.2; fv=0.1; //ttl.printf("set\n"); bf=1; } //Starts calculations when it detects breathing into the device: if ((flow()>fv) and (measurement_started ==0)) { stream.start(); measurement_started = 1; } //Starts detecting plateau: if ((measurement_started == 1) and (solstart==0)) { //Takes 9 samples of CO2: //I have also included printing the values inside the loops so we don't loose any data during calculatins. for(m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset myArray[m]=carbon(); wait(0.1); } while(flags==0) { //While "flags" is enabled, keeps calculating the standard deviation. for(int m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset sum+=myArray[m]; wait(0.1); } avg=sum/9; for(int m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset difSum+=(myArray[m]-avg)*(myArray[m]-avg); //Find sum of difference between value X and mean wait(0.1); } var=difSum/9; sigma=sqrt(var); if (sigma<0.02) { //if SD is less than 0.02 it means that it is too early to start the plateau //So we shift all but the first sample and define the new set of arrays: for(int m=0; m<8; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset myArray[m]=myArray[m+1]; //Shift all CO2 values to the left by 1 value wait(0.1); } myArray[8]=carbon(); //assign a new value for the 9th sample } //The new set of arrays are now generated and is sent back to be used for preveious SD calculations. //If sigma for the new set is still small, a newer set will be generated and replaced //Otherwise, it's accepted and will turn on the solenoid: else { sol=0; //Solenoid is ON 0 //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), 100.00,s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(),0.00,s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset //led=0.4f; //The brightness is reduced to half during the plateau wait(0.1); flags=1; //breakes the while loop } } solend=1; //prepares the next section for finishing the plateau solstart =1; } if ((measurement_started == 1) and (solend==1)) { // same process happens for finishing the plateau: for(m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset myArray[m]=carbon(); wait(0.1); } while(flage==0) { for(int m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset sum2+=myArray[m]; wait(0.1); } avg2=sum2/9; for(int m=0; m<9; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset difSum2+=(myArray[m]-avg2)*(myArray[m]-avg2); wait(0.1); } var2=difSum2/9; sigma2=sqrt(var2); if (sigma2<0.05) { // here we defined the end threshold to be 0.05, it can be changed later based on experiment results for(int m=0; m<8; m++) { //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset myArray[m]=myArray[m+1]; wait(0.1); } myArray[8]=carbon(); } else { sol=1; //Solenoid is OFF 1 //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(), 100.00,s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), 0.00,s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset wait(0.1); flage=1; //breakes the loop } } //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(),carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset //led=0.4f; //LED is back to full brightness bf=0; //reset the detecting base flow flag fin=1; //enables the next section flag } if(carbon()<2.00 && fin ==1) { //User has to wait for the CO2 level to drop less than 2% before testing again. //Once it is less than 2%, all the flags and parameters used in calculations are reset //ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f\n",getTemp(),flow(),carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read()); //chemical sensor myiAQ_Core.iAQ_Core_GetNewReading ( &myiAQ_Core_data ); //Measurement from iAQ-Core C wait(0.1); sgp30.IAQmeasure();//Measurement from SGP30 rslt = myBME680.bme680_get_sensor_data ( &data, &gas_sensor ); //Measurement for BME680 ZMODtemp.write(ZMODTEMPaddr,wInit,2); //maybe? ZMODtemp.write(ZMODTEMPaddr,wTemp,1); ZMODtemp.read(ZMODTEMPaddr,rTemp,2); //Returns 2 bytes float temp_code=(rTemp[0]<<8)+rTemp[1]; float SiTemp=((175.72*temp_code)/65536)-46.85; ttl.printf("tt%.2f,ff%.2f,cc%.2f,sa%i,sb%i,sc%i,sd%i,se%i,sf%i,sg%i,sh%i,ti%.2f,ic%d,iv%d,ir%d,gc%d,gv%d,br%d,bt%.2f,bh%.2f,bp%.2f,zi%f,zh%f,zc%f,st%.2f\n",0.00,flow(), carbon(),s1(),s2(),s3(),s4(),s5(),s6(),s7(),s8(),stream.read(),myiAQ_Core_data.pred, myiAQ_Core_data.Tvoc, myiAQ_Core_data.resistance, sgp30.eCO2,sgp30.TVOC, data.gas_resistance,( data.temperature/100.0f ), ( data.humidity / 1000.0f ), ( data.pressure / 100.0f ),0.00,0.00,0.00,SiTemp); //Results after 5 mins of ON rslt = myBME680.bme680_set_sensor_mode ( &gas_sensor ); //BME680 reset stream.reset(); stream.stop(); measurement_started =0; solstart=0; sum=0; var=0.0; sigma=0.0; difSum=0; sum2=0; var2=0.0; sigma2=0.0; difSum2=0; avg2=0; avg=0; flags=0; flage=0; fin=0; } } }