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.
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 Tue Sep 27 2022 18:47:00 by
1.7.2