Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
calibration.cpp
00001 #include "cisme.h" 00002 #include "calibration.h" 00003 #include "lcd.h" 00004 #include "adc.h" 00005 #include "debug.h" 00006 #include "presens.h" 00007 #include "pump.h" 00008 #include "wifi_events.h" 00009 00010 #define PUMP_NUM_LEVELS 10 00011 #define PUMP_NUM_MEASUREMENTS 10 00012 #define PUMP_MATRIX_NUM_ROWS 3 00013 00014 float calibrationTemperature(float temperature) 00015 { 00016 NVIC_EnableIRQ(UART1_IRQn); 00017 00018 lcdClear(); 00019 lcdWrite(0, 0, JUSTIFICATION_CENTER, "Temp Calibration"); 00020 lcdWrite(1, 0, JUSTIFICATION_CENTER, "Single Point"); 00021 lcdWrite(2, 0, JUSTIFICATION_CENTER, "ISFET Temp"); 00022 lcdWrite(3, 0, JUSTIFICATION_CENTER, "When Stable"); 00023 lcdWrite(4, 0, JUSTIFICATION_CENTER, "Voltage"); 00024 00025 for (unsigned char n = 0; n < 4; n++) { 00026 adcGetData(); 00027 lcdWrite(5, 0, JUSTIFICATION_CENTER, "%2.6f", pHT); 00028 wait(0.2); 00029 } 00030 00031 lcdClear(); 00032 lcdWrite(0, 0, JUSTIFICATION_CENTER, "Temp Calibration"); 00033 lcdWrite(1, 0, JUSTIFICATION_CENTER, "Single Point"); 00034 lcdWrite(2, 0, JUSTIFICATION_CENTER, "100 points, 15 seconds"); 00035 lcdWrite(3, 0, JUSTIFICATION_CENTER, "Temp(C) Value"); 00036 lcdWrite(4, 0, JUSTIFICATION_CENTER, "%2.4f", temperature); 00037 lcdWrite(5, 0, JUSTIFICATION_CENTER, "Temp Voltage"); 00038 00039 float PHTEMPa = 0; 00040 for (unsigned char i = 1; i < 101; i++) { 00041 adcGetData(); 00042 PHTEMPa += pHT; 00043 lcdWrite(6, 0, JUSTIFICATION_CENTER, "%2.6f", PHTEMPa / i); 00044 wifiEventsSendTempCalDataInd(temperature, PHTEMPa / i); 00045 DEBUG1("PHTEMPa %f", PHTEMPa); 00046 } 00047 00048 PHTEMPa /= 100; 00049 NVIC_EnableIRQ(UART1_IRQn); 00050 float Rthermc = 20000.0 / ((2.5 / PHTEMPa) - 1.0); 00051 INFO("PHTEMP %f", Rthermc); 00052 00053 lcdWrite(6, 0, JUSTIFICATION_CENTER, "%2.6f", pHT); 00054 INFO("PHTEMPave %1.6f", PHTEMPa); 00055 00056 float bValue = (temperature / Rthermc) - (A / Rthermc) - (( C / Rthermc) * log10(Rthermc)) - ((D / Rthermc) * pow(log10(Rthermc), 3)); 00057 00058 INFO("Bval %1.6f", bValue); 00059 lcdWrite(7, 0, JUSTIFICATION_CENTER, "%2.6f", bValue); 00060 00061 return bValue; 00062 } 00063 00064 void calibrationTemperatureSave(float bValue) 00065 { 00066 B = bValue; 00067 00068 FILE* isfet = fopen("/" FSNAME "/Parameters/isfet.sys","w"); 00069 if (isfet == NULL) { 00070 lcdClear(); 00071 ERROR("Could not open file for write"); 00072 lcdWrite(4, 0, JUSTIFICATION_CENTER, "isfet File Missing"); 00073 } 00074 00075 INFO("Aval %1.6f Bval %1.6f Cval %1.6f Dval %1.6f", A, B, C, D); 00076 fprintf(isfet, "%f,%f,%f,%f", A, B, C, D); 00077 fclose(isfet); 00078 } 00079 00080 void calibrationO2(void) 00081 { 00082 PRESENS_SET_SACU(LEDCurrent); 00083 00084 // Open Parameter File 00085 FILE* param = fopen("/" FSNAME "/Parameters/dsparams.sys", "w"); 00086 00087 fprintf(param, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d", 00088 a, b, c, PresCal, PhaseCal2, TempCal2, PhaseCal1, TempCal1, LEDCurrent, 00089 PHBUFFERF, PHTEMPF, PHTEMPKF, PHVOLTSF, MSINGLEPT, EOSINGLEPT, UNIT, debugGetCurrLvl()); 00090 fclose(param); 00091 } 00092 00093 void calibrationPh(float phBuffer, float* phTemp, float* slope, float* eo, float* phVolts) 00094 { 00095 const double F = 96487.0; 00096 const double R = 8.31451; 00097 00098 lcdClear(); 00099 lcdWrite(0, 0, JUSTIFICATION_CENTER, "Temp Calibration"); 00100 lcdWrite(1, 0, JUSTIFICATION_CENTER, "Single Point"); 00101 lcdWrite(2, 0, JUSTIFICATION_CENTER, "ISFET pH"); 00102 lcdWrite(3, 0, JUSTIFICATION_CENTER, "When Stable"); 00103 lcdWrite(4, 0, JUSTIFICATION_CENTER, "Voltage"); 00104 00105 for (int m = 0; m < 4; m++) { 00106 adcGetData(); 00107 lcdWrite(5, 0, JUSTIFICATION_CENTER, "%2.6f", pHNoGain); 00108 DEBUG1("pHNoGain %f", pHNoGain); 00109 } 00110 00111 // Calibrate 00112 lcdClear(); 00113 lcdWrite(0, 0, JUSTIFICATION_CENTER, "pH Auto Calibration"); 00114 lcdWrite(1, 0, JUSTIFICATION_CENTER, "Single Point"); 00115 lcdWrite(2, 0, JUSTIFICATION_CENTER, "100 points, 15 seconds"); 00116 lcdWrite(3, 0, JUSTIFICATION_ABSOLUTE, "pH Buffer Value"); 00117 lcdWrite(4, 0, JUSTIFICATION_CENTER, " %2.4f", phBuffer); 00118 lcdWrite(5, 0, JUSTIFICATION_ABSOLUTE, "pH Measured Voltage"); 00119 00120 float PHValue1 = 0; 00121 float PHTEMPa = 0; 00122 for (int i = 1; i < 101; i++) { 00123 wait (0.1); 00124 adcGetData(); 00125 float pHActual = pHNoGain; 00126 PHValue1 += pHNoGain; 00127 PHTEMPa += PHTEMP; 00128 00129 lcdWrite(6, 0, JUSTIFICATION_CENTER," %2.6f", PHValue1 / i); 00130 lcdWrite(7, 0, JUSTIFICATION_CENTER, "%2.6f", pHNoGain); 00131 wifiEventsSendPhCalDataInd(phBuffer, pHNoGain, PHValue1 / i); 00132 DEBUG2("pHActual %f PHValue1 %f PHTEMP %f PHTEMPa %f", 00133 pHActual, PHValue1, PHTEMP, PHTEMPa); 00134 } 00135 00136 PHValue1 /= 100; 00137 PHTEMPa /= 100; 00138 00139 lcdWrite(6, 0, JUSTIFICATION_ABSOLUTE, "%2.6f", PHValue1); 00140 00141 INFO("PHTEMPave %1.6f PHValue1 ave %1.6f", PHTEMPa, PHValue1); 00142 00143 *phTemp = PHTEMPa; 00144 *slope = R * (PHTEMPa + 273.15) / F * 2.302585; 00145 *eo = (double)PHValue1 - (*slope) * (double)phBuffer; 00146 00147 if (phVolts != NULL) { 00148 *phVolts = PHValue1; 00149 } 00150 } 00151 00152 void calibrationPhSave(void) 00153 { 00154 // Open Parameter File 00155 FILE* param = fopen("/" FSNAME "/Parameters/dsparams.sys", "w"); 00156 if (param == NULL) { 00157 lcdClear(); 00158 lcdWrite(4, 0, JUSTIFICATION_CENTER, "Dsprams File Missing"); 00159 return; 00160 } 00161 00162 fprintf(param, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d", 00163 a, b, c, PresCal, PhaseCal2, TempCal2, PhaseCal1, TempCal1, LEDCurrent, 00164 PHBUFFERF, PHTEMPF, PHTEMPKF, PHVOLTSF, MSINGLEPT, EOSINGLEPT, UNIT, debugGetCurrLvl()); 00165 fclose(param); 00166 lcdWrite(0, 0, JUSTIFICATION_CENTER, "Wait 2 seconds"); 00167 wait(2.0); 00168 lcdClear(); 00169 lcdWrite(4, 0, JUSTIFICATION_CENTER, "Restarting"); 00170 wait(0.5); 00171 pumpSet(PUMP_OFF_INTENSITY); 00172 mbed_reset(); 00173 } 00174 00175 void calibrationPump(float* a, float* b, float* c) 00176 { 00177 static const uint8_t intensity[PUMP_NUM_LEVELS] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 99}; 00178 00179 double matrix[PUMP_MATRIX_NUM_ROWS][PUMP_MATRIX_NUM_ROWS + 1] = {0.0}; 00180 00181 for (int intenIx = 0; intenIx < PUMP_NUM_LEVELS; intenIx++) { 00182 00183 double rpm = 0.0; 00184 pumpSet(intensity[intenIx]); 00185 for (int measIx = 0; measIx < PUMP_NUM_MEASUREMENTS; measIx++) { 00186 rpm += pumpSpeed(); 00187 DEBUG1("Pump calibration: intensity=%u, average RPM=%f", intensity[intenIx], rpm / (measIx + 1)); 00188 wifiEventsSendPumpCalDataInd(intensity[intenIx], rpm / (measIx + 1)); 00189 } 00190 00191 rpm /= PUMP_NUM_MEASUREMENTS; 00192 00193 matrix[0][1] += rpm; 00194 matrix[0][2] += rpm * rpm; 00195 matrix[1][2] += rpm * rpm * rpm; 00196 matrix[2][2] += rpm * rpm * rpm * rpm; 00197 matrix[0][3] += intensity[intenIx]; 00198 matrix[1][3] += intensity[intenIx] * rpm; 00199 matrix[2][3] += intensity[intenIx] * rpm * rpm; 00200 } 00201 00202 pumpSet(PUMP_OFF_INTENSITY); 00203 00204 matrix[0][0] = PUMP_NUM_LEVELS; 00205 matrix[1][0] = matrix[0][1]; 00206 matrix[1][1] = matrix[0][2]; 00207 matrix[2][0] = matrix[1][1]; 00208 matrix[2][1] = matrix[1][2]; 00209 00210 // Pivoting 00211 for (int col = 0; col + 1 < PUMP_MATRIX_NUM_ROWS; col++) { 00212 if (matrix[col][col] == 0) { 00213 // Find non-zero coefficient 00214 int swapRow = col + 1; 00215 for (; swapRow < PUMP_MATRIX_NUM_ROWS; swapRow++) { 00216 if (matrix[swapRow][col] != 0) { 00217 break; 00218 } 00219 } 00220 00221 if (matrix[swapRow][col] != 0) { // Found a non-zero coefficient? 00222 // Yes, then swap it with the above 00223 for (int i = 0; i < PUMP_MATRIX_NUM_ROWS + 1; i++) { 00224 double tmp = matrix[swapRow][i]; 00225 matrix[swapRow][i] = matrix[col][i]; 00226 matrix[col][i] = tmp; 00227 } 00228 } else { 00229 // No, then the matrix has no unique solution 00230 ERROR("Can't resolve pump matrix"); 00231 return; 00232 } 00233 } 00234 } 00235 00236 // Elimination 00237 for (int sourceRow = 0; sourceRow + 1 < PUMP_MATRIX_NUM_ROWS; sourceRow++) { 00238 for (int destRow = sourceRow + 1; destRow < PUMP_MATRIX_NUM_ROWS; destRow++) { 00239 float df = matrix[sourceRow][sourceRow]; 00240 float sf = matrix[destRow][sourceRow]; 00241 for (int i = 0; i < PUMP_MATRIX_NUM_ROWS + 1; i++) { 00242 matrix[destRow][i] = matrix[destRow][i] * df - matrix[sourceRow][i] * sf; 00243 } 00244 } 00245 } 00246 00247 // Back-insertion 00248 for (int row = PUMP_MATRIX_NUM_ROWS - 1; row >= 0; row--) { 00249 double f = matrix[row][row]; 00250 if (f == 0) { 00251 ERROR("Can't resolve pump matrix"); 00252 return; 00253 } 00254 00255 for (int ix = 0; ix < PUMP_MATRIX_NUM_ROWS + 1; ix++) { 00256 matrix[row][ix] /= f; 00257 } 00258 00259 for (int destRow = 0; destRow < row; destRow++) { 00260 matrix[destRow][PUMP_MATRIX_NUM_ROWS] -= matrix[destRow][row] * matrix[row][PUMP_MATRIX_NUM_ROWS]; 00261 matrix[destRow][row] = 0; 00262 } 00263 } 00264 00265 *a = matrix[0][PUMP_MATRIX_NUM_ROWS]; 00266 *b = matrix[1][PUMP_MATRIX_NUM_ROWS]; 00267 *c = matrix[2][PUMP_MATRIX_NUM_ROWS]; 00268 00269 INFO("Pump calibration coefficients: a=%f, b=%f, c=%f", *a, *b, *c); 00270 }
Generated on Fri Sep 23 2022 19:29:17 by
1.7.2