Temperature calibration control program

Dependencies:   mbed

Committer:
justinbuckland
Date:
Mon Jun 24 08:48:22 2019 +0000
Revision:
0:147db0900012
Child:
1:68515313ce3e
Initial version; 3-point calibration

Who changed what in which revision?

UserRevisionLine numberNew contents of line
justinbuckland 0:147db0900012 1 #include "mbed.h"
justinbuckland 0:147db0900012 2
justinbuckland 0:147db0900012 3 // thermal cycling settings
justinbuckland 0:147db0900012 4 #define N_CYCLES 40 // number of thermal cycles (ramp-hold-ramp-hold)
justinbuckland 0:147db0900012 5 #define R_SETPOINT_LOW 2.129 // heater resistance at low temp
justinbuckland 0:147db0900012 6 #define T_LOW_RAMP 0 // low temperature ramp time (ms)
justinbuckland 0:147db0900012 7 #define T_LOW_HOLD 30000 // low temperature hold time (ms)
justinbuckland 0:147db0900012 8 #define R_SETPOINT_MID 2.211 // heater resistance at mid temp
justinbuckland 0:147db0900012 9 #define T_MID_RAMP 0 // mid temperature ramp time (ms)
justinbuckland 0:147db0900012 10 #define T_MID_HOLD 0 // mid temperature hold time (ms)
justinbuckland 0:147db0900012 11 #define R_SETPOINT_HIGH 2.35 // heater resistance at high temp
justinbuckland 0:147db0900012 12 #define T_HIGH_RAMP 0 // high temperaure ramp time (ms)
justinbuckland 0:147db0900012 13 #define T_HIGH_HOLD 10000 // high temperature time (ms)
justinbuckland 0:147db0900012 14 #define T_HIGH_START 60000 // hotstart time(ms)
justinbuckland 0:147db0900012 15 #define R_LYSE 1.99 // lyse temperature setpoint
justinbuckland 0:147db0900012 16 #define T_LYSE 0 // lyse time (ms)
justinbuckland 0:147db0900012 17 #define R_RT 2.3 // RT temperature setpoint
justinbuckland 0:147db0900012 18 #define T_RT 300000 // RT time (ms)
justinbuckland 0:147db0900012 19 #define T_FLUIDICS 0 // nominal time for fluidics post lyse
justinbuckland 0:147db0900012 20 #define T_HOLD 60000
justinbuckland 0:147db0900012 21 #define T_RAMP 15000
justinbuckland 0:147db0900012 22
justinbuckland 0:147db0900012 23 #define T_FORM_DSNA 0 // form dsna post thermocycling
justinbuckland 0:147db0900012 24 #define R_FORM_DSNA 2.8 // temperature to form dsna post thermocycling
justinbuckland 0:147db0900012 25
justinbuckland 0:147db0900012 26 #define T_MELT_CURVE 50000 // melt curve ramp time
justinbuckland 0:147db0900012 27 #define R_MELT_LOW 1.82 // low end melt curve temperature
justinbuckland 0:147db0900012 28 #define R_MELT_HIGH 2.08 // high end melt curve temperature
justinbuckland 0:147db0900012 29
justinbuckland 0:147db0900012 30 // temperature measurement settings
justinbuckland 0:147db0900012 31 #define N_SAMPLES 1 // number of samples to acquire for I and V measurements
justinbuckland 0:147db0900012 32 #define N_ROLL_AVG 10 // rolling average for R values
justinbuckland 0:147db0900012 33 #define PULSE_WIDTH 5000 // heat or cool pulse width (us)
justinbuckland 0:147db0900012 34 #define MEAS_DELAY 50 // measurement delay after turning on FET (us)
justinbuckland 0:147db0900012 35 #define CAM_TRIG 20 // camera trigger pulse width (us)
justinbuckland 0:147db0900012 36 #define LOG_INTERVAL 500 // log file interval (ms)
justinbuckland 0:147db0900012 37
justinbuckland 0:147db0900012 38 // ADC channels to read
justinbuckland 0:147db0900012 39 #define CH_A 1 // value of convst bus to read channel A only
justinbuckland 0:147db0900012 40 #define CH_AC 5 // value of convst bus to read channels A and C
justinbuckland 0:147db0900012 41 #define CH_ABCD 15 // value of convst bus to read all chanels simultaneously
justinbuckland 0:147db0900012 42
justinbuckland 0:147db0900012 43 Serial pc(USBTX, USBRX); // tx, rx
justinbuckland 0:147db0900012 44
justinbuckland 0:147db0900012 45 DigitalOut drive(p21); // drive FET
justinbuckland 0:147db0900012 46 DigitalOut yLED(p27); // yellow LED (drive on)
justinbuckland 0:147db0900012 47 DigitalOut gLED(p28); // green LED (power on)
justinbuckland 0:147db0900012 48 DigitalOut rLED(p26); // red LED (thermocycling in progress)
justinbuckland 0:147db0900012 49 DigitalOut mbedIO(p25); // MBED IO
justinbuckland 0:147db0900012 50 DigitalOut camTrig(p24); // trigger camera
justinbuckland 0:147db0900012 51
justinbuckland 0:147db0900012 52 AnalogIn battVolt(p19);
justinbuckland 0:147db0900012 53 AnalogIn auxVolt(p20);
justinbuckland 0:147db0900012 54
justinbuckland 0:147db0900012 55 BusOut convt(p11, p12, p13, p14);
justinbuckland 0:147db0900012 56 SPI spi(p5, p6, p7); // mosi, miso, sclk
justinbuckland 0:147db0900012 57 DigitalOut cs(p8); // chip select
justinbuckland 0:147db0900012 58 DigitalIn busy(p9);
justinbuckland 0:147db0900012 59 DigitalOut reset(p10);
justinbuckland 0:147db0900012 60 DigitalIn userButton(p16);
justinbuckland 0:147db0900012 61 Timer timer;
justinbuckland 0:147db0900012 62 LocalFileSystem local("local");
justinbuckland 0:147db0900012 63
justinbuckland 0:147db0900012 64 FILE *fp = fopen("/local/TEST_LOG.csv", "w"); // Open "test_log" on the local file system for writing
justinbuckland 0:147db0900012 65
justinbuckland 0:147db0900012 66 float r = 0;
justinbuckland 0:147db0900012 67 float r1 = 0;
justinbuckland 0:147db0900012 68 float r2 = 0;
justinbuckland 0:147db0900012 69 float rAvg = 0;
justinbuckland 0:147db0900012 70 float rAcc = 0;
justinbuckland 0:147db0900012 71 float rSet;
justinbuckland 0:147db0900012 72
justinbuckland 0:147db0900012 73 int nAcc = 0;
justinbuckland 0:147db0900012 74 int eTime;
justinbuckland 0:147db0900012 75 int logTime = 0;
justinbuckland 0:147db0900012 76 int iCycle = 0;
justinbuckland 0:147db0900012 77
justinbuckland 0:147db0900012 78 char outString[100];
justinbuckland 0:147db0900012 79
justinbuckland 0:147db0900012 80 char buffer16[16];
justinbuckland 0:147db0900012 81 int val_array[8];
justinbuckland 0:147db0900012 82 const char dummy = 0;
justinbuckland 0:147db0900012 83
justinbuckland 0:147db0900012 84 void logFile(void) {
justinbuckland 0:147db0900012 85 rAcc = rAcc + r;
justinbuckland 0:147db0900012 86 nAcc++;
justinbuckland 0:147db0900012 87 if (eTime > logTime) {
justinbuckland 0:147db0900012 88 // trigger camera
justinbuckland 0:147db0900012 89 camTrig = 1;
justinbuckland 0:147db0900012 90 mbedIO = 1;
justinbuckland 0:147db0900012 91 wait_us(CAM_TRIG);
justinbuckland 0:147db0900012 92 camTrig = 0;
justinbuckland 0:147db0900012 93 mbedIO = 0;
justinbuckland 0:147db0900012 94
justinbuckland 0:147db0900012 95 // write data
justinbuckland 0:147db0900012 96 sprintf(outString, "%10d,%10d,%10.6f,%10.6f\n", iCycle, eTime, rAcc/nAcc, rSet); // log data
justinbuckland 0:147db0900012 97 pc.printf("%s",outString);
justinbuckland 0:147db0900012 98 fprintf(fp, outString);
justinbuckland 0:147db0900012 99 logTime = logTime + LOG_INTERVAL;
justinbuckland 0:147db0900012 100 rAcc = 0;
justinbuckland 0:147db0900012 101 nAcc = 0;
justinbuckland 0:147db0900012 102 }
justinbuckland 0:147db0900012 103 }
justinbuckland 0:147db0900012 104
justinbuckland 0:147db0900012 105 void readChannels (char buffer[16], int values[8]){
justinbuckland 0:147db0900012 106 //simultaneously samples and reads into buffer
justinbuckland 0:147db0900012 107 short int val_array[8];
justinbuckland 0:147db0900012 108 double i1, v1, i2, v2;
justinbuckland 0:147db0900012 109
justinbuckland 0:147db0900012 110 //send convert signal to channels
justinbuckland 0:147db0900012 111 convt = CH_ABCD;
justinbuckland 0:147db0900012 112 wait_us(1);
justinbuckland 0:147db0900012 113 convt = 0;
justinbuckland 0:147db0900012 114
justinbuckland 0:147db0900012 115 //SPI(like) data transfer
justinbuckland 0:147db0900012 116 cs = 0;
justinbuckland 0:147db0900012 117 spi.write(&dummy, 1, buffer, 16);
justinbuckland 0:147db0900012 118 cs=1;
justinbuckland 0:147db0900012 119
justinbuckland 0:147db0900012 120 //loop over bytes to add channel voltage values
justinbuckland 0:147db0900012 121 for (int i=0; i<8; i++){
justinbuckland 0:147db0900012 122 val_array[i] = buffer[2*i]<<8 | buffer16[(2*i) + 1];
justinbuckland 0:147db0900012 123 values [i] = val_array[i];
justinbuckland 0:147db0900012 124 }
justinbuckland 0:147db0900012 125 i1 = (double) (val_array[0]-val_array[1]);
justinbuckland 0:147db0900012 126 i2 = (double) (val_array[2]-val_array[1]);
justinbuckland 0:147db0900012 127 v1 = (double) (val_array[4]-val_array[5]);
justinbuckland 0:147db0900012 128 v2 = (double) (val_array[6]-val_array[7]);
justinbuckland 0:147db0900012 129
justinbuckland 0:147db0900012 130 // update values if no division by zero (to avoid NaN if PSU is off)
justinbuckland 0:147db0900012 131 if (i1 > 0) r1 = v1/i1;
justinbuckland 0:147db0900012 132 if (i2 > 0) r2 = v2/i2;
justinbuckland 0:147db0900012 133
justinbuckland 0:147db0900012 134 // select heater (inner or outer)
justinbuckland 0:147db0900012 135 r = r1; // r1 is inner, r21 is outer
justinbuckland 0:147db0900012 136 }
justinbuckland 0:147db0900012 137
justinbuckland 0:147db0900012 138 void tempControl(int endTime){
justinbuckland 0:147db0900012 139 eTime = timer.read_ms();
justinbuckland 0:147db0900012 140 while (eTime < endTime) {
justinbuckland 0:147db0900012 141 yLED = 1;
justinbuckland 0:147db0900012 142 drive = 1;
justinbuckland 0:147db0900012 143 wait_us(MEAS_DELAY); // wait for heater current to stabilise
justinbuckland 0:147db0900012 144 readChannels (buffer16, val_array); // read ADC channels and update r
justinbuckland 0:147db0900012 145 rAvg = ((N_ROLL_AVG-1)*rAvg + r)/N_ROLL_AVG; // calculate rolling average r
justinbuckland 0:147db0900012 146 // printf("hold r: %8.4f\r\n",r);
justinbuckland 0:147db0900012 147 if (rAvg > rSet) {
justinbuckland 0:147db0900012 148 drive = 0; // turn off heater if setpoint resistance is exceeded
justinbuckland 0:147db0900012 149 yLED = 0;
justinbuckland 0:147db0900012 150 }
justinbuckland 0:147db0900012 151 // printf("set r: %8.4f\r\n",r);
justinbuckland 0:147db0900012 152
justinbuckland 0:147db0900012 153 logFile();
justinbuckland 0:147db0900012 154 wait_us(PULSE_WIDTH); //wait until pulse_width (us) has elapsed
justinbuckland 0:147db0900012 155 eTime = timer.read_ms();
justinbuckland 0:147db0900012 156 }
justinbuckland 0:147db0900012 157 }
justinbuckland 0:147db0900012 158
justinbuckland 0:147db0900012 159 void tempControlRamp(float setStartR, float setEndR, int endTime){
justinbuckland 0:147db0900012 160 float setRate;
justinbuckland 0:147db0900012 161 int startTime;
justinbuckland 0:147db0900012 162
justinbuckland 0:147db0900012 163
justinbuckland 0:147db0900012 164 startTime = timer.read_ms();
justinbuckland 0:147db0900012 165 setRate = (setEndR - setStartR)/(endTime - startTime);
justinbuckland 0:147db0900012 166 eTime = startTime;
justinbuckland 0:147db0900012 167 while (eTime < endTime) {
justinbuckland 0:147db0900012 168 rSet = setStartR + setRate*(eTime - startTime);
justinbuckland 0:147db0900012 169 yLED = 1;
justinbuckland 0:147db0900012 170 drive = 1;
justinbuckland 0:147db0900012 171 wait_us(MEAS_DELAY); // wait for heater current to stabilise
justinbuckland 0:147db0900012 172 readChannels (buffer16, val_array); // read ADC channels and update r
justinbuckland 0:147db0900012 173 rAvg = ((N_ROLL_AVG-1)*rAvg + r)/N_ROLL_AVG; // measure r
justinbuckland 0:147db0900012 174 if (rAvg > rSet) {
justinbuckland 0:147db0900012 175 drive = 0; // turn off heater if setpoint resistance is exceeded
justinbuckland 0:147db0900012 176 yLED = 0;
justinbuckland 0:147db0900012 177 }
justinbuckland 0:147db0900012 178 // printf("ramp r: %8.4f\r\n",r);
justinbuckland 0:147db0900012 179
justinbuckland 0:147db0900012 180 logFile();
justinbuckland 0:147db0900012 181 wait_us(PULSE_WIDTH); //wait until pulse_width (us) has elapsed
justinbuckland 0:147db0900012 182 eTime = timer.read_ms();
justinbuckland 0:147db0900012 183 }
justinbuckland 0:147db0900012 184 }
justinbuckland 0:147db0900012 185
justinbuckland 0:147db0900012 186
justinbuckland 0:147db0900012 187 int main() {
justinbuckland 0:147db0900012 188 int endTime = 0;
justinbuckland 0:147db0900012 189
justinbuckland 0:147db0900012 190 rLED = 0;
justinbuckland 0:147db0900012 191 yLED = 0;
justinbuckland 0:147db0900012 192 gLED = 0;
justinbuckland 0:147db0900012 193
justinbuckland 0:147db0900012 194 drive = 0;
justinbuckland 0:147db0900012 195
justinbuckland 0:147db0900012 196 pc.baud(115200);
justinbuckland 0:147db0900012 197 //Reset ADC sequence
justinbuckland 0:147db0900012 198
justinbuckland 0:147db0900012 199 sprintf(outString," iCycle, Time(ms), r, rSet\n");
justinbuckland 0:147db0900012 200 pc.printf("%s", outString);
justinbuckland 0:147db0900012 201 fprintf(fp, outString);
justinbuckland 0:147db0900012 202
justinbuckland 0:147db0900012 203 // while(userButton == 0)
justinbuckland 0:147db0900012 204 // {
justinbuckland 0:147db0900012 205 // wait_ms(1);
justinbuckland 0:147db0900012 206 // };
justinbuckland 0:147db0900012 207
justinbuckland 0:147db0900012 208
justinbuckland 0:147db0900012 209 reset = 1;
justinbuckland 0:147db0900012 210 wait_ms(1);
justinbuckland 0:147db0900012 211 reset = 0;
justinbuckland 0:147db0900012 212
justinbuckland 0:147db0900012 213 //set SPI serial to 2MHz, 16 bit data transfer, mode 2 (clock normally high, data preceeding clock cycle)
justinbuckland 0:147db0900012 214 spi.format(8,2);
justinbuckland 0:147db0900012 215 spi.frequency(2000000);
justinbuckland 0:147db0900012 216 spi.set_default_write_value(0x00);
justinbuckland 0:147db0900012 217 cs = 1;
justinbuckland 0:147db0900012 218
justinbuckland 0:147db0900012 219 rLED = 1; // thermal cycling in progress
justinbuckland 0:147db0900012 220 yLED = 0; // heater off
justinbuckland 0:147db0900012 221 gLED = 1; // microprocessor power on
justinbuckland 0:147db0900012 222
justinbuckland 0:147db0900012 223
justinbuckland 0:147db0900012 224 timer.start();
justinbuckland 0:147db0900012 225
justinbuckland 0:147db0900012 226 if (T_HOLD > 0) {
justinbuckland 0:147db0900012 227 endTime = endTime + T_HOLD;
justinbuckland 0:147db0900012 228 rSet = R_SETPOINT_LOW;
justinbuckland 0:147db0900012 229 tempControl(endTime);
justinbuckland 0:147db0900012 230 }
justinbuckland 0:147db0900012 231 if (T_RAMP > 0) {
justinbuckland 0:147db0900012 232 endTime = endTime + T_RAMP;
justinbuckland 0:147db0900012 233 tempControlRamp(R_SETPOINT_LOW, R_SETPOINT_MID, endTime);
justinbuckland 0:147db0900012 234
justinbuckland 0:147db0900012 235 }
justinbuckland 0:147db0900012 236 if (T_HOLD > 0) {
justinbuckland 0:147db0900012 237 endTime = endTime + T_HOLD;
justinbuckland 0:147db0900012 238 rSet = R_SETPOINT_MID;
justinbuckland 0:147db0900012 239 tempControl(endTime);
justinbuckland 0:147db0900012 240 }
justinbuckland 0:147db0900012 241 if (T_RAMP > 0) {
justinbuckland 0:147db0900012 242 endTime = endTime + T_RAMP;
justinbuckland 0:147db0900012 243 tempControlRamp(R_SETPOINT_MID, R_SETPOINT_HIGH, endTime);
justinbuckland 0:147db0900012 244
justinbuckland 0:147db0900012 245 }
justinbuckland 0:147db0900012 246 if (T_HOLD > 0) {
justinbuckland 0:147db0900012 247 endTime = endTime + T_HOLD;
justinbuckland 0:147db0900012 248 rSet = R_SETPOINT_HIGH;
justinbuckland 0:147db0900012 249 tempControl(endTime);
justinbuckland 0:147db0900012 250 }
justinbuckland 0:147db0900012 251
justinbuckland 0:147db0900012 252 // extinguish rLED (thermocycling complete), ensure heater is off and close log file for access
justinbuckland 0:147db0900012 253 drive = 0;
justinbuckland 0:147db0900012 254 rLED = 0;
justinbuckland 0:147db0900012 255 logTime = 0;
justinbuckland 0:147db0900012 256 logFile();
justinbuckland 0:147db0900012 257 fclose(fp);
justinbuckland 0:147db0900012 258 }