CN0396 (4-Wire Electrochemical Dual Toxic Gas Sensing System)
Dependencies: AD5270 AD7798 ADT7310
CN0396.cpp
00001 00002 #include "AD5270.h" 00003 #include <math.h> 00004 #include "CN0396.h" 00005 00006 #define ADC_GAIN AD7798_GAIN_1 00007 #define ADC_SPS 0x05 //50SPS 00008 00009 #define CO_SENS (75 * pow(10.0, -9.0)) /* Sensitivity nA/ppm in 400ppm CO 50 to 100 */ 00010 #define CO_RANGE 1000 /* Range ppm CO limit of performance warranty 1,000 */ 00011 #define H2S_SENS (700 * pow(10.0, -9.0)) /* Sensitivity nA/ppm in 20ppm H2S 450 to 900 */ 00012 #define H2S_RANGE 100 /* Range ppm H2S limit of performance warranty 100 */ 00013 00014 00015 //CN0396:: 00016 00017 00018 /* CO side H2S side 00019 Temperature Mean Mean*/ 00020 00021 extern Serial pc; 00022 00023 00024 CN0396::ppm_compensation_t ppm_compensation_init[COMPENSATION_TABLE_SIZE] = { 00025 { -30 , 29.9 , 82.3 }, 00026 { -20 , 38.8 , 84.6 }, 00027 { -10 , 53.7 , 88.6 }, 00028 {0 , 69.6 , 92.2 }, 00029 {10 , 84.9 , 96.2 }, 00030 {20 , 100.0 , 100.0}, 00031 {30 , 112.7 , 103.1}, 00032 {40 , 123.7 , 105.6}, 00033 {50 , 133.1 , 107.4} 00034 }; 00035 CN0396::CN0396(PinName csad, PinName csrdac, PinName cstemp) : 00036 csad(csad), csrdac(csrdac), cstemp(cstemp), ad(csad), rdac(csrdac), temp(cstemp) 00037 { 00038 memcpy(ppm_compensation,ppm_compensation_init,COMPENSATION_TABLE_SIZE*sizeof(ppm_compensation_t)); 00039 } 00040 00041 void CN0396::data_to_voltage(uint16_t adcValue, float *voltage, int gain_adc) 00042 { 00043 *voltage = (float)(adcValue * V_REF) / (float)(_2_16 * gain_adc); 00044 } 00045 00046 void CN0396::data_to_voltage_bipolar(uint16_t adcValue, float *voltage, int gain_adc) 00047 { 00048 *voltage = ((static_cast<float>(adcValue) / _2_15) - 1.0) * (V_REF / static_cast<float>(gain_adc)); 00049 } 00050 00051 float CN0396::get_feedback_resistor_value(float sensitivity, float range) 00052 { 00053 return 1.2 / (sensitivity * range); 00054 } 00055 00056 void CN0396::configure_feedback_resistors(float resistance1, float resistance2) 00057 { 00058 uint16_t R1 = rdac.calc_RDAC(resistance1); 00059 uint16_t R2 = rdac.calc_RDAC(resistance2); 00060 00061 csrdac = false; 00062 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface 00063 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface 00064 csrdac = true; 00065 wait_us(2); 00066 csrdac = false; 00067 rdac.write_cmd(AD5270::WRITE_RDAC, R2, false); // write data to the RDAC register 00068 rdac.write_cmd(AD5270::WRITE_RDAC, R1, false); // write data to the RDAC register 00069 csrdac = true; 00070 wait_us(2); 00071 csrdac = false; 00072 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface 00073 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface 00074 csrdac = false; 00075 wait_us(2); 00076 csrdac = false; 00077 rdac.write_reg(AD5270::HI_Z_Cmd, false); 00078 rdac.write_reg(AD5270::HI_Z_Cmd, false); 00079 csrdac = true; 00080 wait_us(2); 00081 csrdac = false; 00082 rdac.write_reg(AD5270::NO_OP_cmd, false); 00083 rdac.write_reg(AD5270::NO_OP_cmd, false); 00084 csrdac = true; 00085 } 00086 00087 void CN0396::init() 00088 { 00089 // set rdac 00090 00091 pc.printf("Computing resistor values \r\n"); 00092 00093 resistance1 = get_feedback_resistor_value(CO_SENS, CO_RANGE ); 00094 resistance0 = get_feedback_resistor_value(H2S_SENS, H2S_RANGE); 00095 00096 pc.printf("R1 = %f\r\nR2=%f\r\n", resistance0, resistance1); 00097 pc.printf("Configuring feedback resistors\r\n"); 00098 configure_feedback_resistors(resistance1, resistance1); 00099 pc.printf("Done\r\n"); 00100 // config temp 00101 pc.printf("Configuring temperature sensor\r\n"); 00102 temp.reset(); 00103 temp.write_config(0x90); 00104 pc.printf("Done\r\n"); 00105 00106 pc.printf("Configuring ADC\r\n"); 00107 ad.reset(); 00108 if(ad.init()) { 00109 ad.set_coding_mode(AD7798_UNIPOLAR); 00110 ad.set_mode(AD7798_MODE_SINGLE); 00111 ad.set_gain(ADC_GAIN); 00112 ad.set_filter(ADC_SPS); 00113 ad.set_reference(AD7798_REFDET_ENA); 00114 pc.printf("ADC Config succesful\r\n"); 00115 } else { 00116 pc.printf("ADC Config failed\r\n"); 00117 00118 } 00119 00120 00121 } 00122 00123 float CN0396::compensate_ppm(float result, float temp, sensor_type_t sensor) 00124 { 00125 for(uint8_t i = 1; i < COMPENSATION_TABLE_SIZE; i++) { 00126 if(temp < ppm_compensation[i].temp && temp > ppm_compensation[i - 1].temp) { 00127 float compensation_coef; 00128 if(sensor == H2S_SENSOR) { 00129 compensation_coef = (((temp - (ppm_compensation[i - 1].temp )) * (ppm_compensation[i].H2S_percent - ppm_compensation[i - 1].H2S_percent)) / (ppm_compensation[i].temp - ppm_compensation[i - 1].temp)) + ppm_compensation[i - 1].H2S_percent; 00130 } else { 00131 compensation_coef = (((temp - (ppm_compensation[i - 1].temp )) * (ppm_compensation[i].CO_percent - ppm_compensation[i - 1].CO_percent)) / (ppm_compensation[i].temp - ppm_compensation[i - 1].temp)) + ppm_compensation[i - 1].CO_percent; 00132 } 00133 00134 return (result * compensation_coef) / 100.0; 00135 } 00136 } 00137 } 00138 void CN0396::read() 00139 { 00140 uint16_t data0, data1; 00141 // read temperature 00142 uint16_t temp_data = temp.read_temp(); 00143 float temp = 0; 00144 00145 if(temp_data & 0x8000) { 00146 temp = (temp_data - 65536) / (128.0); 00147 } else { 00148 temp = temp_data / (128.0); 00149 } 00150 00151 // read channels 00152 ad.set_channel(0); 00153 ad.read_data(0, &data0); 00154 float volt0; 00155 data_to_voltage(data0, &volt0); 00156 float result0 = (volt0 / resistance0) / CO_SENS; 00157 ad.set_channel(1); 00158 ad.read_data(1, &data1); 00159 float volt1; 00160 data_to_voltage(data1, &volt1); 00161 float result1 = (volt1 / resistance1) / H2S_SENS; 00162 // compute ppm based on formula 00163 // return ppm 00164 result0 = compensate_ppm(result0, temp, CO_SENSOR); 00165 result1 = compensate_ppm(result1, temp, H2S_SENSOR); 00166 00167 pc.printf("%f %f %f \r\n", temp, result0, result1); 00168 }
Generated on Fri Jul 15 2022 03:23:55 by 1.7.2