Soil Measurements for pH and moisture
Dependencies: AD7124
Fork of CN0398 by
CN0398.cpp
00001 #include "CN0398.h" 00002 #include "AD7124.h" 00003 #include <mbed.h> 00004 00005 #define RREF (5000.0) 00006 #define TEMP_GAIN (16.0) 00007 #define PT100_RESISTANCE_TO_TEMP(x) ((x-100.0)/(0.385)) 00008 #define _2_23 (1<<23) 00009 00010 #define CALIBRATION_NR_OF_SAMPLES (5) 00011 00012 extern Serial pc; 00013 00014 #define ms_delay (1) 00015 00016 CN0398::CN0398(PinName cs, PinName adp7118enable) : ad7124(cs), ADP7118Enable(adp7118enable), offset_voltage(default_offset_voltage) 00017 { 00018 use_nernst = false; 00019 calibration_ph[0][0] = 4;//default_calibration_ph[0][0]; 00020 calibration_ph[0][1] = 0.169534;//default_calibration_ph[0][1]; 00021 calibration_ph[1][0] = 10;//default_calibration_ph[1][0]; 00022 calibration_ph[1][1] = -0.134135;//default_calibration_ph[1][1]; 00023 solution0 = 0; 00024 solution1 = 0; 00025 } 00026 00027 void CN0398::calibrate_ph_pt0(float temperature) 00028 { 00029 float volt = 0; 00030 for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) { 00031 set_digital_output(P2, true); 00032 int32_t data = read_channel(0); 00033 set_digital_output(P2, false); 00034 volt += data_to_voltage_bipolar(data >> 8, 1, 3.3); 00035 } 00036 volt = volt / CALIBRATION_NR_OF_SAMPLES; 00037 if(temperature < 0) { 00038 calibration_ph[0][0] = ph_temp_lut[solution0][0]; 00039 } else { 00040 for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) { 00041 if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) { 00042 calibration_ph[0][0] = ph_temp_lut[solution0][i]; 00043 break; 00044 } 00045 } 00046 } 00047 calibration_ph[0][1] = volt; 00048 pc.printf("Calibration solution 1 ph: %f with sensor voltage of %f\r\n", calibration_ph[0][0], volt); 00049 } 00050 void CN0398::calibrate_ph_pt1(float temperature) 00051 { 00052 float volt = 0; 00053 for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) { 00054 set_digital_output(P2, true); 00055 int32_t data = read_channel(0); 00056 set_digital_output(P2, false); 00057 volt += data_to_voltage_bipolar(data >> 8, 1, 3.3); 00058 } 00059 00060 volt = volt / CALIBRATION_NR_OF_SAMPLES; 00061 if(temperature < 0) { 00062 calibration_ph[1][0] = ph_temp_lut[solution1][0]; 00063 } else { 00064 for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) { 00065 if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) { 00066 calibration_ph[1][0] = ph_temp_lut[solution1][i]; 00067 break; 00068 } 00069 } 00070 } 00071 calibration_ph[1][1] = volt; 00072 pc.printf("Calibration solution 2 ph: %f with sensor voltage of %f\r\n", calibration_ph[1][0], volt); 00073 } 00074 00075 void CN0398::calibrate_ph_offset() 00076 { 00077 float volt = 0; 00078 for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) { 00079 set_digital_output(P2, true); 00080 int32_t data = read_channel(0); 00081 set_digital_output(P2, false); 00082 volt += data_to_voltage_bipolar(data >> 8, 1, 3.3); 00083 } 00084 offset_voltage = volt / CALIBRATION_NR_OF_SAMPLES; 00085 pc.printf("Offset voltage is: %f \r\n", volt); 00086 } 00087 00088 00089 float CN0398::read_rtd() 00090 { 00091 float temperature = 25.0; 00092 #ifdef TEMPERATURE_SENSOR_PRESENT 00093 int32_t data = read_channel(2); 00094 data = (data >> 8) & 0x00ffffff; 00095 float resistance = ((static_cast<float>(data) - _2_23) * RREF) / (TEMP_GAIN * _2_23); 00096 #ifdef USE_LINEAR_TEMP_EQ 00097 temperature = PT100_RESISTANCE_TO_TEMP(resistance); 00098 #else 00099 00100 #define A (3.9083*pow(10.0,-3.0)) 00101 #define B (-5.775*pow(10.0,-7.0)) 00102 /*if(resistance < 100.0) 00103 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); 00104 else*/ 00105 temperature = ((-A + sqrt(double(pow(A, 2.0) - 4 * B * (1 - resistance / 100.0))) ) / (2 * B)); 00106 #endif 00107 #endif 00108 return temperature; 00109 00110 } 00111 00112 int32_t CN0398::read_channel(uint8_t ch) 00113 { 00114 int32_t data; 00115 enable_channel(ch); 00116 start_single_conversion(); 00117 00118 if (ad7124.WaitForConvReady(10000) == -3) { 00119 pc.printf("TIMEOUT"); 00120 return -1; 00121 } 00122 ad7124.ReadData(&data); 00123 disable_channel(ch); 00124 return data; 00125 00126 } 00127 float CN0398::read_ph(float temperature) 00128 { 00129 float ph = 0; 00130 #ifdef PH_SENSOR_PRESENT 00131 set_digital_output(P2, true); 00132 int32_t data = read_channel(0); 00133 set_digital_output(P2, false); 00134 float volt = data_to_voltage_bipolar(data >> 8, 1, 3.3); 00135 #ifdef DEBUG_MODE 00136 pc.printf("pH sensor voltage - %f\n", volt); 00137 #endif 00138 00139 if(use_nernst) { 00140 ph = -((volt - ZERO_POINT_TOLERANCE) / ((2.303 * AVOGADRO * (temperature + KELVIN_OFFSET)) / FARADAY_CONSTANT) ) + PH_ISO; 00141 } else { 00142 float m = (calibration_ph[1][0] - calibration_ph[0][0]) / (calibration_ph[1][1] - calibration_ph[0][1]); 00143 ph = m * (volt - calibration_ph[1][1] + offset_voltage) + calibration_ph[1][0]; 00144 } 00145 #endif 00146 return ph; 00147 } 00148 float CN0398::read_moist() 00149 { 00150 float moisture = 0; 00151 #ifdef MOISTURE_SENSOR_PRESENT 00152 ADP7118Enable = true; 00153 set_digital_output(P3, true); 00154 wait_ms(SENSOR_SETTLING_TIME); 00155 int32_t data = read_channel(1); 00156 ADP7118Enable = false; 00157 set_digital_output(P3, false); 00158 00159 data = (data >> 8) & 0x00ffffff; 00160 float volt = data_to_voltage(data, 1, 3.3); 00161 #ifdef USE_MANUFACTURER_MOISTURE_EQ 00162 if(volt <= 1.1) { 00163 moisture = 10 * volt - 1; 00164 } else if(volt > 1.1 && volt <= 1.3) { 00165 moisture = 25 * volt - 17.5; 00166 } else if(volt > 1.3 && volt <= 1.82) { 00167 moisture = 48.08 * volt - 47.5; 00168 } else if(volt > 1.82) { 00169 moisture = 26.32 * volt - 7.89; 00170 } 00171 #else 00172 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)); 00173 #endif 00174 if(moisture > 100) moisture = 100; 00175 if(moisture < 0 ) moisture = 0; 00176 #endif 00177 return moisture; 00178 } 00179 00180 float CN0398::data_to_voltage_bipolar(uint32_t data, uint8_t gain, float VREF) 00181 { 00182 data = data & 0xFFFFFF; 00183 return ((data / static_cast<float>(0xFFFFFF / 2)) - 1) * (VREF / gain); 00184 } 00185 00186 float CN0398::data_to_voltage(uint32_t data, uint8_t gain, float VREF) 00187 { 00188 data = data & 0xFFFFFF; 00189 return (data / static_cast<float>(0xFFFFFF)) * (VREF / gain); 00190 } 00191 00192 void CN0398::enable_channel(int channel) 00193 { 00194 AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register 00195 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00196 setValue |= (uint32_t) AD7124_CH_MAP_REG_CH_ENABLE; //Enable channel0 00197 setValue &= 0xFFFF; 00198 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00199 wait_ms(ms_delay); 00200 } 00201 00202 void CN0398::disable_channel(int channel) 00203 { 00204 AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register 00205 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00206 setValue &= (~(uint32_t) AD7124_CH_MAP_REG_CH_ENABLE); //Enable channel0 00207 setValue &= 0xFFFF; 00208 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00209 wait_ms(ms_delay); 00210 } 00211 00212 /* 00213 void CN0398::enable_current_source0(int current_source_channel) 00214 { 00215 AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register 00216 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00217 setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH0(0xF)); 00218 setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(current_source_channel);// set IOUT0 current to 500uA 00219 setValue &= 0xFFFFFF; 00220 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00221 wait_ms(ms_delay); 00222 } 00223 00224 void CN0398::enable_current_source1(int current_source_channel) 00225 { 00226 AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register 00227 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00228 setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH1(0xF)); 00229 setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(current_source_channel);// set IOUT0 current to 500uA 00230 setValue &= 0xFFFFFF; 00231 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00232 wait_ms(ms_delay); 00233 }*/ 00234 00235 void CN0398::set_digital_output(ad_digital_output_t p, bool state) 00236 { 00237 AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register 00238 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00239 if(state) 00240 setValue |= ((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p); 00241 else 00242 setValue &= (~((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p)); 00243 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00244 wait_ms(ms_delay); 00245 } 00246 00247 00248 void CN0398::start_single_conversion() 00249 { 00250 AD7124::ad7124_registers regNr = AD7124::AD7124_ADC_Control; //Select ADC_Control register 00251 uint32_t setValue = ad7124.ReadDeviceRegister(regNr); 00252 setValue &= 0xFFC3; 00253 setValue |= 0x04; //single conversion; 00254 setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS; 00255 setValue &= 0xFFFF; 00256 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC*/ 00257 wait_ms(ms_delay * 10); 00258 } 00259 00260 void CN0398::reset() 00261 { 00262 ad7124.frequency(500000); 00263 ad7124.Reset(); 00264 pc.printf("Reseted AD7124\r\n"); 00265 wait_ms(1000); 00266 } 00267 00268 void CN0398::setup() 00269 { 00270 ad7124.Setup(); 00271 } 00272 00273 void CN0398::init() 00274 { 00275 uint32_t setValue; 00276 enum AD7124::ad7124_registers regNr; 00277 00278 /* Set Config_0 0x19*/ 00279 regNr = AD7124::AD7124_Config_0; //Select Config_0 register - pH 00280 setValue = 0;//ad7124.ReadDeviceRegister(regNr); 00281 setValue |= AD7124_CFG_REG_BIPOLAR; //Select bipolar operation 00282 setValue |= AD7124_CFG_REG_BURNOUT(0); //Burnout current source off 00283 setValue |= AD7124_CFG_REG_REF_BUFP; 00284 setValue |= AD7124_CFG_REG_REF_BUFM; 00285 setValue |= AD7124_CFG_REG_AIN_BUFP; //Buffer AIN5 00286 setValue |= AD7124_CFG_REG_AINN_BUFM; //Buffer AIN4 00287 setValue |= AD7124_CFG_REG_REF_SEL(0); //REFIN1(+)/REFIN1(−). 00288 setValue |= AD7124_CFG_REG_PGA(0); 00289 setValue &= 0xFFFF; 00290 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00291 00292 /* Set Config_0 0x1A*/ 00293 regNr = AD7124::AD7124_Config_1; //Select Config_1 register - Moisture 00294 setValue = 0;//ad7124.ReadDeviceRegister(regNr); 00295 setValue &= ~AD7124_CFG_REG_BIPOLAR; //Select bipolar operation 00296 setValue |= AD7124_CFG_REG_BURNOUT(0); //Burnout current source off 00297 setValue |= AD7124_CFG_REG_REF_BUFP; 00298 setValue |= AD7124_CFG_REG_REF_BUFM; 00299 setValue |= AD7124_CFG_REG_AIN_BUFP; //Buffer AIN5 00300 setValue |= AD7124_CFG_REG_AINN_BUFM; //Buffer AIN4*/ 00301 setValue |= AD7124_CFG_REG_REF_SEL(0); // REFIN1(+)/REFIN1(−). 00302 setValue |= AD7124_CFG_REG_PGA(0); 00303 setValue &= 0xFFFF; 00304 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00305 00306 /* Set Config_0 0x1B*/ 00307 regNr = AD7124::AD7124_Config_2; //Select Config_2 register - temp 00308 setValue = 0;//ad7124.ReadDeviceRegister(regNr); 00309 setValue |= AD7124_CFG_REG_BIPOLAR; //Select bipolar operation 00310 setValue |= AD7124_CFG_REG_BURNOUT(0); //Burnout current source off 00311 setValue |= AD7124_CFG_REG_REF_BUFP; 00312 setValue |= AD7124_CFG_REG_REF_BUFM; 00313 setValue |= AD7124_CFG_REG_AIN_BUFP; //Buffer AIN5 00314 setValue |= AD7124_CFG_REG_AINN_BUFM; //Buffer AIN4 00315 setValue |= AD7124_CFG_REG_REF_SEL(1); //REFIN2(+)/REFIN2(-). 00316 setValue |= AD7124_CFG_REG_PGA(4); // gain 16 00317 setValue &= 0xFFFF; 00318 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00319 00320 /* Set Channel_0 register 0x09*/ 00321 regNr = AD7124::AD7124_Channel_0; // pH reading 00322 setValue = 0; 00323 setValue |= AD7124_CH_MAP_REG_SETUP(0); // Select setup0 00324 setValue |= AD7124_CH_MAP_REG_AINP(6); // Set AIN4 as positive input 00325 setValue |= AD7124_CH_MAP_REG_AINM(7); // Set AIN5 as negative input 00326 setValue &= 0xFFFF; 00327 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00328 00329 regNr = AD7124::AD7124_Channel_1; // Moisture 00330 setValue = 0; 00331 setValue |= AD7124_CH_MAP_REG_SETUP(1); // Select setup0 00332 setValue |= AD7124_CH_MAP_REG_AINP(8); // Set AIN4 as positive input 00333 setValue |= AD7124_CH_MAP_REG_AINM(19); // Set AIN5 as negative input 00334 setValue &= 0xFFFF; 00335 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00336 00337 regNr = AD7124::AD7124_Channel_2; // RTD - gain 16 00338 setValue = 0; 00339 setValue |= AD7124_CH_MAP_REG_SETUP(2); // Select setup0 00340 setValue |= AD7124_CH_MAP_REG_AINP(9); // Set AIN4 as positive input 00341 setValue |= AD7124_CH_MAP_REG_AINM(10); // Set AIN5 as negative input 00342 setValue &= 0xFFFF; 00343 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00344 00345 /* Set IO_Control_1 0x03 */ 00346 regNr = AD7124::AD7124_IOCon1; //Select IO_Control_1 register 00347 //setValue = ad7124.ReadDeviceRegister(regNr); 00348 setValue = 0; 00349 setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL2; // enable AIN3 as digital output 00350 setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL3; // enable AIN4 as digital output 00351 setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(11); // source ain11 00352 setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(12); // source ain12 00353 setValue |= AD7124_IO_CTRL1_REG_IOUT0(0x4);// set IOUT0 current to 500uA 00354 setValue |= AD7124_IO_CTRL1_REG_IOUT1(0x4);// set IOUT0 current to 500uA*/ 00355 setValue &= 0xFFFFFF; 00356 ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC 00357 00358 // Set IO_Control_2 00359 regNr = AD7124::AD7124_IOCon2; //Select IO_Control_2 register 00360 setValue = 0; 00361 setValue |= AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7; // enable AIN3 as digital output 00362 setValue &= 0xFFFFFF; 00363 ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC 00364 00365 00366 /* Set ADC_Control 0x01 */ 00367 regNr = AD7124::AD7124_ADC_Control; //Select ADC_Control register 00368 setValue = ad7124.ReadDeviceRegister(regNr); 00369 setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS; // set data status bit in order to check on which channel the conversion is 00370 setValue &= 0xFFC3; // remove prev mode bits 00371 setValue |= AD7124_ADC_CTRL_REG_MODE(2); 00372 setValue &= 0xFFFF; 00373 ad7124.WriteDeviceRegister(regNr, setValue); // Write data to ADC 00374 wait_ms(ms_delay); 00375 } 00376 00377 00378 00379 00380
Generated on Wed Jul 13 2022 06:25:53 by 1.7.2