Qubit 2020 / presensfirmwareupdate

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers calibration.cpp Source File

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 }