Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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, -9)) /* 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, -9)) /* Sensitivity nA/ppm in 20ppm H2S 450 to 900 */ 00012 #define H2S_RANGE 100 /* Range ppm H2S limit of performance warranty 100 */ 00013 00014 /* CO side H2S side 00015 Temperature Mean Mean*/ 00016 00017 extern Serial pc; 00018 00019 CN0396::CN0396(PinName csad, PinName csrdac, PinName cstemp) : 00020 csad(csad), csrdac(csrdac), cstemp(cstemp), ad(csad), rdac(csrdac), temp(cstemp) 00021 { 00022 00023 } 00024 00025 void CN0396::data_to_voltage(uint16_t adcValue, float *voltage, int gain_adc) 00026 { 00027 *voltage = (float)(adcValue * V_REF) / (float)(_2_16 * gain_adc); 00028 } 00029 00030 void CN0396::data_to_voltage_bipolar(uint16_t adcValue, float *voltage, int gain_adc) 00031 { 00032 *voltage = ((static_cast<float>(adcValue) / _2_15) - 1.0) * (V_REF / static_cast<float>(gain_adc)); 00033 } 00034 00035 float CN0396::get_feedback_resistor_value(float sensitivity, float range) 00036 { 00037 return 1.2 / (sensitivity * range); 00038 } 00039 00040 void CN0396::configure_feedback_resistors(float resistance1, float resistance2) 00041 { 00042 uint16_t R1 = rdac.calc_RDAC(resistance1); 00043 uint16_t R2 = rdac.calc_RDAC(resistance2); 00044 00045 csrdac = false; 00046 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface 00047 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface 00048 csrdac = true; 00049 wait_us(2); 00050 csrdac = false; 00051 rdac.write_cmd(AD5270::WRITE_RDAC, R2, false); // write data to the RDAC register 00052 rdac.write_cmd(AD5270::WRITE_RDAC, R1, false); // write data to the RDAC register 00053 csrdac = true; 00054 wait_us(2); 00055 csrdac = false; 00056 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface 00057 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface 00058 csrdac = false; 00059 wait_us(2); 00060 csrdac = false; 00061 rdac.write_reg(AD5270::HI_Z_Cmd, false); 00062 rdac.write_reg(AD5270::HI_Z_Cmd, false); 00063 csrdac = true; 00064 wait_us(2); 00065 csrdac = false; 00066 rdac.write_reg(AD5270::NO_OP_cmd, false); 00067 rdac.write_reg(AD5270::NO_OP_cmd, false); 00068 csrdac = true; 00069 } 00070 00071 void CN0396::init() 00072 { 00073 // set rdac 00074 00075 pc.printf("Computing resistor values \r\n"); 00076 00077 resistance1 = get_feedback_resistor_value(CO_SENS, CO_RANGE ); 00078 resistance0 = get_feedback_resistor_value(H2S_SENS, H2S_RANGE); 00079 00080 pc.printf("R1 = %f\r\nR2=%f\r\n", resistance0, resistance1); 00081 pc.printf("Configuring feedback resistors\r\n"); 00082 configure_feedback_resistors(resistance1, resistance1); 00083 pc.printf("Done\r\n"); 00084 // config temp 00085 pc.printf("Configuring temperature sensor\r\n"); 00086 temp.reset(); 00087 temp.write_config(0x90); 00088 pc.printf("Done\r\n"); 00089 00090 pc.printf("Configuring ADC\r\n"); 00091 ad.reset(); 00092 if(ad.init()) { 00093 ad.set_coding_mode(AD7798_UNIPOLAR); 00094 ad.set_mode(AD7798_MODE_SINGLE); 00095 ad.set_gain(ADC_GAIN); 00096 ad.set_filter(ADC_SPS); 00097 ad.set_reference(AD7798_REFDET_ENA); 00098 pc.printf("ADC Config succesful\r\n"); 00099 } else { 00100 pc.printf("ADC Config failed\r\n"); 00101 00102 } 00103 00104 00105 } 00106 00107 float CN0396::compensate_ppm(float result, float temp, sensor_type_t sensor) 00108 { 00109 for(uint8_t i = 1; i < COMPENSATION_TABLE_SIZE; i++) { 00110 if(temp < ppm_compensation[i].temp && temp > ppm_compensation[i - 1].temp) { 00111 float compensation_coef; 00112 if(sensor == H2S_SENSOR) { 00113 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; 00114 } else { 00115 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; 00116 } 00117 00118 return (result * compensation_coef) / 100.0; 00119 } 00120 } 00121 } 00122 void CN0396::read() 00123 { 00124 uint16_t data0, data1; 00125 // read temperature 00126 uint16_t temp_data = temp.read_temp(); 00127 float temp = 0; 00128 00129 if(temp_data & 0x8000) { 00130 temp = (temp_data - 65536) / (128.0); 00131 } else { 00132 temp = temp_data / (128.0); 00133 } 00134 00135 // read channels 00136 ad.set_channel(0); 00137 ad.read_data(0, &data0); 00138 float volt0; 00139 data_to_voltage(data0, &volt0); 00140 float result0 = (volt0 / resistance0) / CO_SENS; 00141 ad.set_channel(1); 00142 ad.read_data(1, &data1); 00143 float volt1; 00144 data_to_voltage(data1, &volt1); 00145 float result1 = (volt1 / resistance1) / H2S_SENS; 00146 // compute ppm based on formula 00147 // return ppm 00148 result0 = compensate_ppm(result0, temp, CO_SENSOR); 00149 result1 = compensate_ppm(result1, temp, H2S_SENSOR); 00150 00151 pc.printf("%f %f %f \r\n", temp, result0, result1); 00152 }
Generated on Tue Jul 12 2022 17:59:52 by
1.7.2
CN0357 - Toxic gas measurement
CN0216 - Weight Scale