A collection of Analog Devices drivers for the mbed platform

For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all

Committer:
Adrian Suciu
Date:
Mon Nov 07 16:27:12 2016 +0200
Revision:
33:c3ec596a29c2
Added CN0391, CN0396 and CN0397 shields

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Adrian Suciu 33:c3ec596a29c2 1
Adrian Suciu 33:c3ec596a29c2 2 #include "AD5270.h"
Adrian Suciu 33:c3ec596a29c2 3 #include <math.h>
Adrian Suciu 33:c3ec596a29c2 4 #include "CN0396.h"
Adrian Suciu 33:c3ec596a29c2 5
Adrian Suciu 33:c3ec596a29c2 6 #define ADC_GAIN AD7798_GAIN_1
Adrian Suciu 33:c3ec596a29c2 7 #define ADC_SPS 0x05 //50SPS
Adrian Suciu 33:c3ec596a29c2 8
Adrian Suciu 33:c3ec596a29c2 9 #define CO_SENS (75 * pow(10, -9)) /* Sensitivity nA/ppm in 400ppm CO 50 to 100 */
Adrian Suciu 33:c3ec596a29c2 10 #define CO_RANGE 1000 /* Range ppm CO limit of performance warranty 1,000 */
Adrian Suciu 33:c3ec596a29c2 11 #define H2S_SENS (700 * pow(10, -9)) /* Sensitivity nA/ppm in 20ppm H2S 450 to 900 */
Adrian Suciu 33:c3ec596a29c2 12 #define H2S_RANGE 100 /* Range ppm H2S limit of performance warranty 100 */
Adrian Suciu 33:c3ec596a29c2 13
Adrian Suciu 33:c3ec596a29c2 14 /* CO side H2S side
Adrian Suciu 33:c3ec596a29c2 15 Temperature Mean Mean*/
Adrian Suciu 33:c3ec596a29c2 16
Adrian Suciu 33:c3ec596a29c2 17 extern Serial pc;
Adrian Suciu 33:c3ec596a29c2 18
Adrian Suciu 33:c3ec596a29c2 19 CN0396::CN0396(PinName csad, PinName csrdac, PinName cstemp) :
Adrian Suciu 33:c3ec596a29c2 20 csad(csad), csrdac(csrdac), cstemp(cstemp), ad(csad), rdac(csrdac), temp(cstemp)
Adrian Suciu 33:c3ec596a29c2 21 {
Adrian Suciu 33:c3ec596a29c2 22
Adrian Suciu 33:c3ec596a29c2 23 }
Adrian Suciu 33:c3ec596a29c2 24
Adrian Suciu 33:c3ec596a29c2 25 void CN0396::data_to_voltage(uint16_t adcValue, float *voltage, int gain_adc)
Adrian Suciu 33:c3ec596a29c2 26 {
Adrian Suciu 33:c3ec596a29c2 27 *voltage = (float)(adcValue * V_REF) / (float)(_2_16 * gain_adc);
Adrian Suciu 33:c3ec596a29c2 28 }
Adrian Suciu 33:c3ec596a29c2 29
Adrian Suciu 33:c3ec596a29c2 30 void CN0396::data_to_voltage_bipolar(uint16_t adcValue, float *voltage, int gain_adc)
Adrian Suciu 33:c3ec596a29c2 31 {
Adrian Suciu 33:c3ec596a29c2 32 *voltage = ((static_cast<float>(adcValue) / _2_15) - 1.0) * (V_REF / static_cast<float>(gain_adc));
Adrian Suciu 33:c3ec596a29c2 33 }
Adrian Suciu 33:c3ec596a29c2 34
Adrian Suciu 33:c3ec596a29c2 35 float CN0396::get_feedback_resistor_value(float sensitivity, float range)
Adrian Suciu 33:c3ec596a29c2 36 {
Adrian Suciu 33:c3ec596a29c2 37 return 1.2 / (sensitivity * range);
Adrian Suciu 33:c3ec596a29c2 38 }
Adrian Suciu 33:c3ec596a29c2 39
Adrian Suciu 33:c3ec596a29c2 40 void CN0396::configure_feedback_resistors(float resistance1, float resistance2)
Adrian Suciu 33:c3ec596a29c2 41 {
Adrian Suciu 33:c3ec596a29c2 42 uint16_t R1 = rdac.calc_RDAC(resistance1);
Adrian Suciu 33:c3ec596a29c2 43 uint16_t R2 = rdac.calc_RDAC(resistance2);
Adrian Suciu 33:c3ec596a29c2 44
Adrian Suciu 33:c3ec596a29c2 45 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 46 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface
Adrian Suciu 33:c3ec596a29c2 47 rdac.write_cmd(AD5270::WRITE_CTRL_REG, AD5270::RDAC_WRITE_PROTECT, false); // RDAC register write protect - allow update of wiper position through digital interface
Adrian Suciu 33:c3ec596a29c2 48 csrdac = true;
Adrian Suciu 33:c3ec596a29c2 49 wait_us(2);
Adrian Suciu 33:c3ec596a29c2 50 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 51 rdac.write_cmd(AD5270::WRITE_RDAC, R2, false); // write data to the RDAC register
Adrian Suciu 33:c3ec596a29c2 52 rdac.write_cmd(AD5270::WRITE_RDAC, R1, false); // write data to the RDAC register
Adrian Suciu 33:c3ec596a29c2 53 csrdac = true;
Adrian Suciu 33:c3ec596a29c2 54 wait_us(2);
Adrian Suciu 33:c3ec596a29c2 55 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 56 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface
Adrian Suciu 33:c3ec596a29c2 57 rdac.write_cmd(AD5270::WRITE_CTRL_REG, 0, false); // RDAC register write protect - allow update of wiper position through digital interface
Adrian Suciu 33:c3ec596a29c2 58 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 59 wait_us(2);
Adrian Suciu 33:c3ec596a29c2 60 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 61 rdac.write_reg(AD5270::HI_Z_Cmd, false);
Adrian Suciu 33:c3ec596a29c2 62 rdac.write_reg(AD5270::HI_Z_Cmd, false);
Adrian Suciu 33:c3ec596a29c2 63 csrdac = true;
Adrian Suciu 33:c3ec596a29c2 64 wait_us(2);
Adrian Suciu 33:c3ec596a29c2 65 csrdac = false;
Adrian Suciu 33:c3ec596a29c2 66 rdac.write_reg(AD5270::NO_OP_cmd, false);
Adrian Suciu 33:c3ec596a29c2 67 rdac.write_reg(AD5270::NO_OP_cmd, false);
Adrian Suciu 33:c3ec596a29c2 68 csrdac = true;
Adrian Suciu 33:c3ec596a29c2 69 }
Adrian Suciu 33:c3ec596a29c2 70
Adrian Suciu 33:c3ec596a29c2 71 void CN0396::init()
Adrian Suciu 33:c3ec596a29c2 72 {
Adrian Suciu 33:c3ec596a29c2 73 // set rdac
Adrian Suciu 33:c3ec596a29c2 74
Adrian Suciu 33:c3ec596a29c2 75 pc.printf("Computing resistor values \r\n");
Adrian Suciu 33:c3ec596a29c2 76
Adrian Suciu 33:c3ec596a29c2 77 resistance1 = get_feedback_resistor_value(CO_SENS, CO_RANGE );
Adrian Suciu 33:c3ec596a29c2 78 resistance0 = get_feedback_resistor_value(H2S_SENS, H2S_RANGE);
Adrian Suciu 33:c3ec596a29c2 79
Adrian Suciu 33:c3ec596a29c2 80 pc.printf("R1 = %f\r\nR2=%f\r\n", resistance0, resistance1);
Adrian Suciu 33:c3ec596a29c2 81 pc.printf("Configuring feedback resistors\r\n");
Adrian Suciu 33:c3ec596a29c2 82 configure_feedback_resistors(resistance1, resistance1);
Adrian Suciu 33:c3ec596a29c2 83 pc.printf("Done\r\n");
Adrian Suciu 33:c3ec596a29c2 84 // config temp
Adrian Suciu 33:c3ec596a29c2 85 pc.printf("Configuring temperature sensor\r\n");
Adrian Suciu 33:c3ec596a29c2 86 temp.reset();
Adrian Suciu 33:c3ec596a29c2 87 temp.write_config(0x90);
Adrian Suciu 33:c3ec596a29c2 88 pc.printf("Done\r\n");
Adrian Suciu 33:c3ec596a29c2 89
Adrian Suciu 33:c3ec596a29c2 90 pc.printf("Configuring ADC\r\n");
Adrian Suciu 33:c3ec596a29c2 91 ad.reset();
Adrian Suciu 33:c3ec596a29c2 92 if(ad.init()) {
Adrian Suciu 33:c3ec596a29c2 93 ad.set_coding_mode(AD7798_UNIPOLAR);
Adrian Suciu 33:c3ec596a29c2 94 ad.set_mode(AD7798_MODE_SINGLE);
Adrian Suciu 33:c3ec596a29c2 95 ad.set_gain(ADC_GAIN);
Adrian Suciu 33:c3ec596a29c2 96 ad.set_filter(ADC_SPS);
Adrian Suciu 33:c3ec596a29c2 97 ad.set_reference(AD7798_REFDET_ENA);
Adrian Suciu 33:c3ec596a29c2 98 pc.printf("ADC Config succesful\r\n");
Adrian Suciu 33:c3ec596a29c2 99 } else {
Adrian Suciu 33:c3ec596a29c2 100 pc.printf("ADC Config failed\r\n");
Adrian Suciu 33:c3ec596a29c2 101
Adrian Suciu 33:c3ec596a29c2 102 }
Adrian Suciu 33:c3ec596a29c2 103
Adrian Suciu 33:c3ec596a29c2 104
Adrian Suciu 33:c3ec596a29c2 105 }
Adrian Suciu 33:c3ec596a29c2 106
Adrian Suciu 33:c3ec596a29c2 107 float CN0396::compensate_ppm(float result, float temp, sensor_type_t sensor)
Adrian Suciu 33:c3ec596a29c2 108 {
Adrian Suciu 33:c3ec596a29c2 109 for(uint8_t i = 1; i < COMPENSATION_TABLE_SIZE; i++) {
Adrian Suciu 33:c3ec596a29c2 110 if(temp < ppm_compensation[i].temp && temp > ppm_compensation[i - 1].temp) {
Adrian Suciu 33:c3ec596a29c2 111 float compensation_coef;
Adrian Suciu 33:c3ec596a29c2 112 if(sensor == H2S_SENSOR) {
Adrian Suciu 33:c3ec596a29c2 113 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;
Adrian Suciu 33:c3ec596a29c2 114 } else {
Adrian Suciu 33:c3ec596a29c2 115 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;
Adrian Suciu 33:c3ec596a29c2 116 }
Adrian Suciu 33:c3ec596a29c2 117
Adrian Suciu 33:c3ec596a29c2 118 return (result * compensation_coef) / 100.0;
Adrian Suciu 33:c3ec596a29c2 119 }
Adrian Suciu 33:c3ec596a29c2 120 }
Adrian Suciu 33:c3ec596a29c2 121 }
Adrian Suciu 33:c3ec596a29c2 122 void CN0396::read()
Adrian Suciu 33:c3ec596a29c2 123 {
Adrian Suciu 33:c3ec596a29c2 124 uint16_t data0, data1;
Adrian Suciu 33:c3ec596a29c2 125 // read temperature
Adrian Suciu 33:c3ec596a29c2 126 uint16_t temp_data = temp.read_temp();
Adrian Suciu 33:c3ec596a29c2 127 float temp = 0;
Adrian Suciu 33:c3ec596a29c2 128
Adrian Suciu 33:c3ec596a29c2 129 if(temp_data & 0x8000) {
Adrian Suciu 33:c3ec596a29c2 130 temp = (temp_data - 65536) / (128.0);
Adrian Suciu 33:c3ec596a29c2 131 } else {
Adrian Suciu 33:c3ec596a29c2 132 temp = temp_data / (128.0);
Adrian Suciu 33:c3ec596a29c2 133 }
Adrian Suciu 33:c3ec596a29c2 134
Adrian Suciu 33:c3ec596a29c2 135 // read channels
Adrian Suciu 33:c3ec596a29c2 136 ad.set_channel(0);
Adrian Suciu 33:c3ec596a29c2 137 ad.read_data(0, &data0);
Adrian Suciu 33:c3ec596a29c2 138 float volt0;
Adrian Suciu 33:c3ec596a29c2 139 data_to_voltage(data0, &volt0);
Adrian Suciu 33:c3ec596a29c2 140 float result0 = (volt0 / resistance0) / CO_SENS;
Adrian Suciu 33:c3ec596a29c2 141 ad.set_channel(1);
Adrian Suciu 33:c3ec596a29c2 142 ad.read_data(1, &data1);
Adrian Suciu 33:c3ec596a29c2 143 float volt1;
Adrian Suciu 33:c3ec596a29c2 144 data_to_voltage(data1, &volt1);
Adrian Suciu 33:c3ec596a29c2 145 float result1 = (volt1 / resistance1) / H2S_SENS;
Adrian Suciu 33:c3ec596a29c2 146 // compute ppm based on formula
Adrian Suciu 33:c3ec596a29c2 147 // return ppm
Adrian Suciu 33:c3ec596a29c2 148 result0 = compensate_ppm(result0, temp, CO_SENSOR);
Adrian Suciu 33:c3ec596a29c2 149 result1 = compensate_ppm(result1, temp, H2S_SENSOR);
Adrian Suciu 33:c3ec596a29c2 150
Adrian Suciu 33:c3ec596a29c2 151 pc.printf("%f %f %f \r\n", temp, result0, result1);
Adrian Suciu 33:c3ec596a29c2 152 }