A collection of Analog Devices drivers for the mbed platform
Embed:
(wiki syntax)
Show/hide line numbers
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