Soil Measurements for pH and moisture

Dependencies:   AD7124

Dependents:   cn0398-helloworld

Fork of CN0398 by Analog Devices

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

Files at this revision

API Documentation at this revision

Comitter:
adisuciu
Date:
Mon Oct 24 15:27:31 2016 +0000
Child:
1:712abd52fa0a
Commit message:
Initial revision

Changed in this revision

CN0398.cpp Show annotated file Show diff for this revision Revisions of this file
CN0398.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CN0398.cpp	Mon Oct 24 15:27:31 2016 +0000
@@ -0,0 +1,379 @@
+#include "CN0398.h"
+#include "AD7124.h"
+#include <mbed.h>
+
+#define RREF (5000.0)
+#define TEMP_GAIN (16.0)
+#define PT100_RESISTANCE_TO_TEMP(x) ((x-100.0)/(0.385))
+#define _2_23 (1<<23)
+
+#define CALIBRATION_NR_OF_SAMPLES (5)
+
+extern Serial pc;
+
+#define ms_delay (1)
+
+CN0398::CN0398(PinName cs, PinName adp7118enable) : ad7124(cs), ADP7118Enable(adp7118enable), offset_voltage(default_offset_voltage)
+{
+    calibration_ph[0][0] = default_calibration_ph[0][0];
+    calibration_ph[0][1] = default_calibration_ph[0][1];
+    calibration_ph[1][0] = default_calibration_ph[1][0];
+    calibration_ph[1][1] = default_calibration_ph[1][1];
+    solution0 = 0;
+    solution1 = 0;
+}
+
+void CN0398::calibrate_ph_pt0(float temperature)
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+    volt = volt / CALIBRATION_NR_OF_SAMPLES;
+    if(temperature < 0) {
+        calibration_ph[0][0] = ph_temp_lut[solution0][0];
+    } else {
+        for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) {
+            if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) {
+                calibration_ph[0][0] = ph_temp_lut[solution0][i];
+                break;
+            }
+        }
+    }
+    calibration_ph[0][1] = volt;
+    pc.printf("Calibration solution 1 ph: %f with sensor voltage of %f\r\n", calibration_ph[0][0], volt);
+}
+void CN0398::calibrate_ph_pt1(float temperature)
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+
+    volt = volt / CALIBRATION_NR_OF_SAMPLES;
+    if(temperature < 0) {
+        calibration_ph[1][0] = ph_temp_lut[solution1][0];
+    } else {
+        for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) {
+            if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) {
+                calibration_ph[1][0] = ph_temp_lut[solution1][i];
+                break;
+            }
+        }
+    }
+    calibration_ph[1][1] = volt;
+    pc.printf("Calibration solution 2 ph: %f with sensor voltage of %f\r\n", calibration_ph[1][0], volt);
+}
+
+void CN0398::calibrate_ph_offset()
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+    offset_voltage = volt / CALIBRATION_NR_OF_SAMPLES;
+    pc.printf("Offset voltage is: %f \r\n", volt);
+}
+
+
+float CN0398::read_rtd()
+{
+    float temperature = 25.0;
+#ifdef TEMPERATURE_SENSOR_PRESENT
+    int32_t data = read_channel(2);
+    data = (data >> 8) & 0x00ffffff;
+    float resistance = ((static_cast<float>(data) - _2_23) * RREF) / (TEMP_GAIN * _2_23);
+#ifdef USE_LINEAR_TEMP_EQ
+    temperature = PT100_RESISTANCE_TO_TEMP(resistance);
+#else
+
+#define A (3.9083*pow(10,-3))
+#define B (-5.775*pow(10,-7))
+    /*if(resistance < 100.0)
+        temperature = -242.02 + 2.228 * resistance + (2.5859 * pow(10, -3)) * pow(resistance, 2) - (48260 * pow(10, -6)) * pow(resistance, 3) - (2.8183 * pow(10, -3)) * pow(resistance, 4) + (1.5243 * pow(10, -10)) * pow(resistance, 5);
+    else*/
+    temperature = ((-A + sqrt(double(pow(A, 2) - 4 * B * (1 - resistance / 100.0))) ) / (2 * B));
+#endif
+#endif
+    return temperature;
+
+}
+
+int32_t CN0398::read_channel(uint8_t ch)
+{
+    int32_t data;
+    enable_channel(ch);
+    start_single_conversion();
+
+    if (ad7124.WaitForConvReady(10000) == -3) {
+        pc.printf("TIMEOUT");
+        return -1;
+    }
+    ad7124.ReadData(&data);
+    disable_channel(ch);
+    return data;
+
+}
+float CN0398::read_ph(float temperature)
+{
+    float ph = 0;
+#ifdef PH_SENSOR_PRESENT
+    set_digital_output(P2, true);
+    int32_t data = read_channel(0);
+    set_digital_output(P2, false);
+    float volt = data_to_voltage_bipolar(data >> 8, 1, 3.3);
+#ifdef DEBUG_MODE
+    pc.printf("pH sensor voltage - %f\n", volt);
+#endif
+
+    if(use_nernst) {
+        ph  = -((volt - ZERO_POINT_TOLERANCE) / ((2.303 * AVOGADRO * (temperature + KELVIN_OFFSET)) / FARADAY_CONSTANT) ) + PH_ISO;
+    } else {
+        float m =  (calibration_ph[1][0] - calibration_ph[0][0]) / (calibration_ph[1][1] - calibration_ph[0][1]);
+        ph = m * (volt - calibration_ph[1][1] + offset_voltage) + calibration_ph[1][0];
+    }
+#endif
+    return ph;
+}
+float CN0398::read_moist()
+{
+    float moisture = 0;
+#ifdef MOISTURE_SENSOR_PRESENT
+    ADP7118Enable = true;
+    set_digital_output(P3, true);
+    wait_ms(SENSOR_SETTLING_TIME);
+    int32_t data = read_channel(1);
+    ADP7118Enable = false;
+    set_digital_output(P3, false);
+
+    data = (data >> 8) & 0x00ffffff;
+    float volt = data_to_voltage(data, 1, 3.3);
+#ifdef USE_MANUFACTURER_MOISTURE_EQ
+    if(volt <= 1.1) {
+        moisture = 10 * volt - 1;
+    } else if(volt > 1.1 && volt <= 1.3) {
+        moisture = 25 * volt - 17.5;
+    } else if(volt > 1.3 && volt <= 1.82) {
+        moisture = 48.08 * volt - 47.5;
+    } else if(volt > 1.82) {
+        moisture = 26.32 * volt - 7.89;
+    }
+#else
+    moisture = -1.18467 + 21.5371 * volt - 110.996 * (pow(volt, 2)) + 397.025 * (pow(volt, 3)) - 666.986 * (pow(volt, 4)) + 569.236 * (pow(volt, 5)) - 246.005 * (pow(volt, 6)) + 49.4867 * (pow(volt, 7)) - 3.37077 * (pow(volt, 8));
+#endif
+    if(moisture > 100) moisture = 100;
+    if(moisture < 0 ) moisture = 0;
+#endif
+    return moisture;
+}
+
+float CN0398::data_to_voltage_bipolar(uint32_t data, uint8_t gain, float VREF)
+{
+    data = data & 0xFFFFFF;
+    return ((data / static_cast<float>(0xFFFFFF / 2)) - 1) * (VREF / gain);
+}
+
+float CN0398::data_to_voltage(uint32_t data, uint8_t gain, float VREF)
+{
+    data = data & 0xFFFFFF;
+    return (data / static_cast<float>(0xFFFFFF)) * (VREF / gain);
+}
+
+void CN0398::enable_channel(int channel)
+{
+    AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue |= (uint32_t) AD7124_CH_MAP_REG_CH_ENABLE;  //Enable channel0
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+void CN0398::disable_channel(int channel)
+{
+    AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= (~(uint32_t) AD7124_CH_MAP_REG_CH_ENABLE);  //Enable channel0
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+/*
+void CN0398::enable_current_source0(int current_source_channel)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH0(0xF));
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(current_source_channel);// set IOUT0 current to 500uA
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+void CN0398::enable_current_source1(int current_source_channel)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH1(0xF));
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(current_source_channel);// set IOUT0 current to 500uA
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}*/
+
+void CN0398::set_digital_output(ad_digital_output_t p, bool state)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    if(state)
+        setValue |= ((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p);
+    else
+        setValue &= (~((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p));
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+
+void CN0398::start_single_conversion()
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_ADC_Control; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= 0xFFC3;
+    setValue |= 0x04;               //single conversion;
+    setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS;
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC*/
+    wait_ms(ms_delay * 10);
+}
+
+void CN0398::reset()
+{
+    ad7124.frequency(500000);
+    ad7124.Reset();
+    pc.printf("Reseted AD7124\r\n");
+    wait_ms(1000);
+}
+
+void CN0398::setup()
+{
+    ad7124.Setup();
+}
+
+void CN0398::init()
+{
+    uint32_t setValue;
+    enum AD7124::ad7124_registers regNr;
+
+    /* Set Config_0 0x19*/
+    regNr = AD7124::AD7124_Config_0;               //Select Config_0 register - pH
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4
+    setValue |= AD7124_CFG_REG_REF_SEL(0); //REFIN1(+)/REFIN1(−).
+    setValue |= AD7124_CFG_REG_PGA(0);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Config_0 0x1A*/
+    regNr = AD7124::AD7124_Config_1;               //Select Config_1 register - Moisture
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4*/
+    setValue |= AD7124_CFG_REG_REF_SEL(0); // REFIN1(+)/REFIN1(−).
+    setValue |= AD7124_CFG_REG_PGA(0);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Config_0 0x1B*/
+    regNr = AD7124::AD7124_Config_2;               //Select Config_2 register - temp
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4
+    setValue |= AD7124_CFG_REG_REF_SEL(1); //REFIN2(+)/REFIN2(-).
+    setValue |= AD7124_CFG_REG_PGA(4); // gain 16
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Channel_0 register 0x09*/
+    regNr = AD7124::AD7124_Channel_0;  // pH reading
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(0);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(6);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(7);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    regNr = AD7124::AD7124_Channel_1; // Moisture
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(1);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(8);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(19);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    regNr = AD7124::AD7124_Channel_2; // RTD - gain 16
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(2);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(9);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(10);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set IO_Control_1 0x03 */
+    regNr = AD7124::AD7124_IOCon1;               //Select IO_Control_1 register
+    //setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue = 0;
+    setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL2; // enable AIN3 as digital output
+    setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL3; // enable AIN4 as digital output
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(11); // source ain11
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(12); // source ain12
+    setValue |= AD7124_IO_CTRL1_REG_IOUT0(0x4);// set IOUT0 current to 500uA
+    setValue |= AD7124_IO_CTRL1_REG_IOUT1(0x4);// set IOUT0 current to 500uA*/
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC
+
+    // Set IO_Control_2
+    regNr = AD7124::AD7124_IOCon2;               //Select IO_Control_2 register
+    setValue = 0;
+    setValue |= AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7; // enable AIN3 as digital output
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC
+
+
+    /* Set ADC_Control 0x01 */
+    regNr = AD7124::AD7124_ADC_Control;            //Select ADC_Control register
+    setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS; // set data status bit in order to check on which channel the conversion is
+    setValue &= 0xFFC3; // remove prev mode bits
+    setValue |= AD7124_ADC_CTRL_REG_MODE(2);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CN0398.h	Mon Oct 24 15:27:31 2016 +0000
@@ -0,0 +1,235 @@
+#ifndef _CN0398_H_
+#define _CN0398_H_
+#include "AD7124.h"
+
+/**
+ * @brief Calibration solutions enum
+ */
+enum {
+    ACETATE,
+    BORATE,
+    CAOH2,
+    CARBONATE,
+    CITRATE,
+    HCL,
+    OXALATE,
+    PHOSPHATE0,
+    PHOSPHATE1,
+    PHOSPHATE2,
+    PHTHALATE,
+    TARTRATE,
+    TRIS,
+    PH4,
+    PH10,
+    NUMBER_OF_SOLUTIONS
+};
+
+/**
+ * @brief Calibration solutions strings
+ */
+const char solutions[NUMBER_OF_SOLUTIONS][20] = {
+    "ACETATE",
+    "BORATE",
+    "CAOH2",
+    "CARBONATE",
+    "CITRATE",
+    "HCL",
+    "OXALATE",
+    "PHOSPHATE0",
+    "PHOSPHATE1",
+    "PHOSPHATE2",
+    "PHTHALATE",
+    "TARTRATE",
+    "TRIS",
+    "PH4",
+    "PH10"
+};
+#define NUMBER_OF_TEMPERATURE_ENTRIES 31
+
+// *INDENT-OFF*
+/**
+ * @brief Calibration temperatures
+ */
+const uint8_t ph_temperatures[NUMBER_OF_TEMPERATURE_ENTRIES] =
+{
+		0 ,		5 ,		10,		15,		18,		19,		20,		21,		22,		23,		24,		25,
+		26,		27,		28,		29,		30,		35,		37,		40,		45,		50,		55,		60,
+		65,		70,		75,		80,		85,		90,		95,
+};
+
+/**
+ * @brief Calibration solutions temperature to ph look-up tables
+ */
+const float ph_temp_lut[NUMBER_OF_SOLUTIONS][NUMBER_OF_TEMPERATURE_ENTRIES]
+{
+/* ACETATE    */ {4.667, 4.66, 4.655, 4.652, 4.651, 4.651, 4.65, 4.65, 4.65, 4.65, 4.65, 4.65, 4.65, 4.651, 4.651, 4.651, 4.652, 4.655, 4.656, 4.659, 4.666, 4.673, 4.683, 4.694, 4.706, 4.72, 4.736, 4.753, 4.772, 4.793, 4.815},
+/* BORATE     */ {9.464, 9.395, 9.332, 9.276, 9.245, 9.235, 9.225, 9.216, 9.207, 9.197, 9.189, 9.18, 9.171, 9.163, 9.155, 9.147, 9.139, 9.102, 9.088, 9.068, 9.038, 9.01, 8.985, 8.962, 8.941, 8.921, 8.902, 8.884, 8.867, 8.85, 8.833},
+/* CAOH2      */ {13.424, 13.207, 13.003, 12.81, 12.699, 12.663, 12.627, 12.592, 12.557, 12.522, 12.488, 12.454, 12.42, 12.387, 12.354, 12.322, 12.289, 12.133, 12.072, 11.984, 11.841, 11.705, 11.574, 11.449	},
+/* CARBONATE  */ {10.317, 10.245, 10.179, 10.118, 10.084, 10.073, 10.062, 10.052, 10.042, 10.032, 10.022, 10.012, 10.002, 9.993, 9.984, 9.975, 9.966, 9.925, 9.91, 9.889, 9.857, 9.828},
+/* CITRATE    */ {3.863, 3.84, 3.82, 3.803, 3.793, 3.791, 3.788, 3.785, 3.783, 3.78, 3.778, 3.776, 3.774, 3.772, 3.77, 3.768, 3.766, 3.759, 3.756, 3.754, 3.75, 3.749},
+/* HCL        */ {1.082, 1.085, 1.087, 1.089, 1.09, 1.091, 1.091, 1.092, 1.092, 1.093, 1.093, 1.094, 1.094, 1.094, 1.095, 1.095, 1.096, 1.098, 1.099, 1.101, 1.103, 1.106, 1.108, 1.111, 1.113, 1.116, 1.119, 1.121, 1.124, 1.127, 1.13},
+/* OXALATE    */ {1.666, 1.668, 1.67, 1.672, 1.674, 1.675, 1.675, 1.676, 1.677, 1.678, 1.678, 1.679, 1.68, 1.681, 1.681, 1.682, 1.683, 1.688, 1.69, 1.694, 1.7, 1.707, 1.715, 1.723, 1.732, 1.743, 1.754, 1.765, 1.778, 1.792, 1.806},
+/* PHOSPHATE0 */ {6.984, 6.951, 6.923, 6.9, 6.888, 6.884, 6.881, 6.877, 6.874, 6.871, 6.868, 6.865, 6.862, 6.86, 6.857, 6.855, 6.853, 6.844, 6.841, 6.838, 6.834, 6.833, 6.833, 6.836, 6.84, 6.845, 6.852, 6.859, 6.867, 6.876, 6.886},
+/* PHOSPHATE1 */ {7.118, 7.087, 7.059, 7.036, 7.024, 7.02, 7.016, 7.013, 7.009, 7.006, 7.003, 7, 6.997, 6.994, 6.992, 6.989, 6.987, 6.977, 6.974, 6.97, 6.965, 6.964, 6.965, 6.968, 6.974, 6.982, 6.992, 7.004, 7.018, 7.034, 7.052},
+/* PHOSPHATE2 */ {7.534, 7.5, 7.472, 7.448, 7.436, 7.432, 7.429, 7.425, 7.422, 7.419, 7.416, 7.413, 7.41, 7.407, 7.405, 7.402, 7.4, 7.389, 7.386, 7.38, 7.373, 7.367},
+/* PHTHALATE  */ {4, 3.998, 3.997, 3.998, 3.999, 4, 4.001, 4.001, 4.002, 4.003, 4.004, 4.005, 4.006, 4.007, 4.008, 4.009, 4.011, 4.018, 4.022, 4.027, 4.038, 4.05, 4.064, 4.08, 4.097, 4.116, 4.137, 4.159, 4.183, 4.208, 4.235},
+/* TARTRATE   */ {3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.556, 3.555, 3.554, 3.553, 3.552, 3.549, 3.548, 3.547, 3.547, 3.549, 3.554, 3.56, 3.569, 3.58, 3.593, 3.61, 3.628, 3.65, 3.675},
+/* TRIS       */ {8.471, 8.303, 8.142, 7.988, 7.899, 7.869, 7.84, 7.812, 7.783, 7.755, 7.727, 7.699, 7.671, 7.644, 7.617, 7.59, 7.563, 7.433, 7.382, 7.307, 7.186, 7.07},
+/* PH4        */ {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+/* PH10       */ {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
+};
+// *INDENT-ON*
+
+#define TEMPERATURE_SENSOR_PRESENT
+#define MOISTURE_SENSOR_PRESENT
+#define PH_SENSOR_PRESENT
+
+//#define USE_LINEAR_TEMP_EQ
+//#define USE_MANUFACTURER_MOISTURE_EQ
+
+
+#define ZERO_POINT_TOLERANCE (0.003)
+#define PH_ISO (7)
+#define AVOGADRO (8.314)
+#define FARADAY_CONSTANT (96485.0)
+#define KELVIN_OFFSET (273.1)
+
+
+
+
+/**
+ * @brief the CN0398 shield class
+ */
+class CN0398
+{
+private:
+public:
+    /**
+     * @brief CN0398 constructor
+     * @param cs - CN0398 external ADC chip select pin
+     * @param swctrl0 - CN0398 ADP7118 enable pin
+     */
+    CN0398(PinName cs, PinName swctrl0);
+
+    /**
+     * @brief reads the temperature sensor
+     * @return temperature
+     */
+    float read_rtd();
+    /**
+     * @brief reads the pH sensor
+     * @param temperature(optional) - environment temperature
+     * @return reading of the pH sensor corrected with temperature(if provided)
+     */
+    float read_ph(float temperature = 25.0);
+
+    /**
+     * @brief reads the moisture sensor
+     * @return reading of the moisture sensor
+     */
+    float read_moist();
+
+    typedef enum {
+        P1 = 0,
+        P2 = 1,
+        P3 = 2,
+        P4 = 3
+    } ad_digital_output_t;
+
+    /**
+     * @brief reads the ADC channel
+     * @param ch channel to be read
+     * @return ADC reading in counts
+     */
+    int32_t read_channel(uint8_t ch);
+
+    /**
+     * @brief converts counts to voltage - unipolar conversion
+     * @param data in counts
+     * @param gain(optional) - default 1
+     * @param VREF(optional) - default 2.5 - reference voltage
+     * @return voltage
+     */
+    float data_to_voltage(uint32_t data, uint8_t gain = 1, float VREF = 2.5);
+
+    /**
+    * @brief converts counts to voltage - bipolar conversion
+    * @param data in counts
+    * @param gain(optional) - default 1
+    * @param VREF(optional) - default 2.5 - reference voltage
+    * @return voltage
+    */
+    float data_to_voltage_bipolar(uint32_t data, uint8_t gain = 1, float VREF = 2.5);
+
+    /**
+     *	@brief enables an ADC channel
+     *	@param channel - channel to be enabled
+     */
+    void enable_channel(int channel);
+    /**
+      *	@brief disables an ADC channel
+      *	@param channel - channel to be disabled
+      */
+    void disable_channel(int channel);
+
+    /**
+     * @brief performs pt 0 calibration. ph probe should be in calibration solution before calling this method
+     * @param temp - environment temperature
+     */
+    void calibrate_ph_pt0(float temperature = 25.0);
+
+    /**
+    * @brief performs pt 1 calibration. ph probe should be in calibration solution before calling this method
+    * @param temp - environment temperature
+    */
+    void calibrate_ph_pt1(float temperature = 25.0);
+
+    /**
+     * @brief performs offset calibration. pH probes should be shorted before calling this method
+     *
+     */
+    void calibrate_ph_offset();
+
+    /* void enable_current_source0(int current_source_channel);
+     void enable_current_source1(int current_source_channel);*/
+
+    /**
+     * @brief toggles the digital outputs on or off
+     * @param p - digital output
+     * @param state - state of the output
+     */
+    void set_digital_output(ad_digital_output_t p, bool state);
+
+    /**
+     * @brief triggers ADC start of single conversion
+     */
+    void start_single_conversion();
+
+    /**
+     * @brief resets the digital interface of the ADC
+     */
+    void reset();
+
+    /**
+     * @brief initializes the ADC
+     */
+    void setup();
+
+    /**
+     *  @brief configures the ADC for the CN0398 application
+     */
+    void init();
+
+    AD7124 ad7124;
+    DigitalOut ADP7118Enable;
+
+    bool use_nernst = false;
+    const float default_offset_voltage = 0;
+    const uint16_t SENSOR_SETTLING_TIME = 400; /*in ms*/
+    float offset_voltage;
+    float default_calibration_ph[2][2] = {{4, 0.169534}, {10,  -0.134135}};
+    float calibration_ph[2][2];
+    uint8_t solution0, solution1;
+
+};
+#endif