A collection of Analog Devices drivers for the mbed platform

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CN0396.cpp Source File

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 }