Justin Buckland
/
MEMSPCR_CONTROL_CALIBRATION_SJM1
Temperature calibration control program
main.cpp@1:68515313ce3e, 2019-06-25 (annotated)
- Committer:
- justinbuckland
- Date:
- Tue Jun 25 11:45:10 2019 +0000
- Revision:
- 1:68515313ce3e
- Parent:
- 0:147db0900012
5 resistance setpoint steps for calibration
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
justinbuckland | 0:147db0900012 | 1 | #include "mbed.h" |
justinbuckland | 0:147db0900012 | 2 | |
justinbuckland | 1:68515313ce3e | 3 | // select heater |
justinbuckland | 1:68515313ce3e | 4 | #define HEATER 1 // inner heater = 1, outer heater = 2 |
justinbuckland | 0:147db0900012 | 5 | |
justinbuckland | 1:68515313ce3e | 6 | // temperature calibration settings |
justinbuckland | 1:68515313ce3e | 7 | #define N_STEPS 5 // number of temperature calibration points |
justinbuckland | 1:68515313ce3e | 8 | #define R_SET_START 1.900 // heater resistance at lowest temp |
justinbuckland | 1:68515313ce3e | 9 | #define R_SET_STEP 0.100 // heater resistance at highest temp |
justinbuckland | 1:68515313ce3e | 10 | #define T_HOLD 100000 // temperature hold time (ms) |
justinbuckland | 0:147db0900012 | 11 | |
justinbuckland | 0:147db0900012 | 12 | // temperature measurement settings |
justinbuckland | 0:147db0900012 | 13 | #define N_SAMPLES 1 // number of samples to acquire for I and V measurements |
justinbuckland | 0:147db0900012 | 14 | #define N_ROLL_AVG 10 // rolling average for R values |
justinbuckland | 0:147db0900012 | 15 | #define PULSE_WIDTH 5000 // heat or cool pulse width (us) |
justinbuckland | 0:147db0900012 | 16 | #define MEAS_DELAY 50 // measurement delay after turning on FET (us) |
justinbuckland | 0:147db0900012 | 17 | #define CAM_TRIG 20 // camera trigger pulse width (us) |
justinbuckland | 1:68515313ce3e | 18 | #define LOG_INTERVAL 1000 // log file interval (ms) |
justinbuckland | 0:147db0900012 | 19 | |
justinbuckland | 0:147db0900012 | 20 | // ADC channels to read |
justinbuckland | 0:147db0900012 | 21 | #define CH_A 1 // value of convst bus to read channel A only |
justinbuckland | 0:147db0900012 | 22 | #define CH_AC 5 // value of convst bus to read channels A and C |
justinbuckland | 0:147db0900012 | 23 | #define CH_ABCD 15 // value of convst bus to read all chanels simultaneously |
justinbuckland | 0:147db0900012 | 24 | |
justinbuckland | 0:147db0900012 | 25 | Serial pc(USBTX, USBRX); // tx, rx |
justinbuckland | 0:147db0900012 | 26 | |
justinbuckland | 0:147db0900012 | 27 | DigitalOut drive(p21); // drive FET |
justinbuckland | 0:147db0900012 | 28 | DigitalOut yLED(p27); // yellow LED (drive on) |
justinbuckland | 0:147db0900012 | 29 | DigitalOut gLED(p28); // green LED (power on) |
justinbuckland | 0:147db0900012 | 30 | DigitalOut rLED(p26); // red LED (thermocycling in progress) |
justinbuckland | 0:147db0900012 | 31 | DigitalOut mbedIO(p25); // MBED IO |
justinbuckland | 0:147db0900012 | 32 | DigitalOut camTrig(p24); // trigger camera |
justinbuckland | 0:147db0900012 | 33 | |
justinbuckland | 0:147db0900012 | 34 | AnalogIn battVolt(p19); |
justinbuckland | 0:147db0900012 | 35 | AnalogIn auxVolt(p20); |
justinbuckland | 0:147db0900012 | 36 | |
justinbuckland | 0:147db0900012 | 37 | BusOut convt(p11, p12, p13, p14); |
justinbuckland | 0:147db0900012 | 38 | SPI spi(p5, p6, p7); // mosi, miso, sclk |
justinbuckland | 0:147db0900012 | 39 | DigitalOut cs(p8); // chip select |
justinbuckland | 0:147db0900012 | 40 | DigitalIn busy(p9); |
justinbuckland | 0:147db0900012 | 41 | DigitalOut reset(p10); |
justinbuckland | 0:147db0900012 | 42 | DigitalIn userButton(p16); |
justinbuckland | 0:147db0900012 | 43 | Timer timer; |
justinbuckland | 0:147db0900012 | 44 | LocalFileSystem local("local"); |
justinbuckland | 0:147db0900012 | 45 | |
justinbuckland | 0:147db0900012 | 46 | FILE *fp = fopen("/local/TEST_LOG.csv", "w"); // Open "test_log" on the local file system for writing |
justinbuckland | 0:147db0900012 | 47 | |
justinbuckland | 0:147db0900012 | 48 | float r = 0; |
justinbuckland | 0:147db0900012 | 49 | float r1 = 0; |
justinbuckland | 0:147db0900012 | 50 | float r2 = 0; |
justinbuckland | 0:147db0900012 | 51 | float rAvg = 0; |
justinbuckland | 0:147db0900012 | 52 | float rAcc = 0; |
justinbuckland | 0:147db0900012 | 53 | float rSet; |
justinbuckland | 0:147db0900012 | 54 | |
justinbuckland | 0:147db0900012 | 55 | int nAcc = 0; |
justinbuckland | 0:147db0900012 | 56 | int eTime; |
justinbuckland | 0:147db0900012 | 57 | int logTime = 0; |
justinbuckland | 0:147db0900012 | 58 | int iCycle = 0; |
justinbuckland | 0:147db0900012 | 59 | |
justinbuckland | 0:147db0900012 | 60 | char outString[100]; |
justinbuckland | 0:147db0900012 | 61 | |
justinbuckland | 0:147db0900012 | 62 | char buffer16[16]; |
justinbuckland | 0:147db0900012 | 63 | int val_array[8]; |
justinbuckland | 0:147db0900012 | 64 | const char dummy = 0; |
justinbuckland | 0:147db0900012 | 65 | |
justinbuckland | 0:147db0900012 | 66 | void logFile(void) { |
justinbuckland | 0:147db0900012 | 67 | rAcc = rAcc + r; |
justinbuckland | 0:147db0900012 | 68 | nAcc++; |
justinbuckland | 0:147db0900012 | 69 | if (eTime > logTime) { |
justinbuckland | 0:147db0900012 | 70 | // trigger camera |
justinbuckland | 0:147db0900012 | 71 | camTrig = 1; |
justinbuckland | 0:147db0900012 | 72 | mbedIO = 1; |
justinbuckland | 0:147db0900012 | 73 | wait_us(CAM_TRIG); |
justinbuckland | 0:147db0900012 | 74 | camTrig = 0; |
justinbuckland | 0:147db0900012 | 75 | mbedIO = 0; |
justinbuckland | 0:147db0900012 | 76 | |
justinbuckland | 0:147db0900012 | 77 | // write data |
justinbuckland | 0:147db0900012 | 78 | sprintf(outString, "%10d,%10d,%10.6f,%10.6f\n", iCycle, eTime, rAcc/nAcc, rSet); // log data |
justinbuckland | 0:147db0900012 | 79 | pc.printf("%s",outString); |
justinbuckland | 0:147db0900012 | 80 | fprintf(fp, outString); |
justinbuckland | 0:147db0900012 | 81 | logTime = logTime + LOG_INTERVAL; |
justinbuckland | 0:147db0900012 | 82 | rAcc = 0; |
justinbuckland | 0:147db0900012 | 83 | nAcc = 0; |
justinbuckland | 0:147db0900012 | 84 | } |
justinbuckland | 0:147db0900012 | 85 | } |
justinbuckland | 0:147db0900012 | 86 | |
justinbuckland | 0:147db0900012 | 87 | void readChannels (char buffer[16], int values[8]){ |
justinbuckland | 0:147db0900012 | 88 | //simultaneously samples and reads into buffer |
justinbuckland | 0:147db0900012 | 89 | short int val_array[8]; |
justinbuckland | 0:147db0900012 | 90 | double i1, v1, i2, v2; |
justinbuckland | 0:147db0900012 | 91 | |
justinbuckland | 0:147db0900012 | 92 | //send convert signal to channels |
justinbuckland | 0:147db0900012 | 93 | convt = CH_ABCD; |
justinbuckland | 0:147db0900012 | 94 | wait_us(1); |
justinbuckland | 0:147db0900012 | 95 | convt = 0; |
justinbuckland | 0:147db0900012 | 96 | |
justinbuckland | 0:147db0900012 | 97 | //SPI(like) data transfer |
justinbuckland | 0:147db0900012 | 98 | cs = 0; |
justinbuckland | 0:147db0900012 | 99 | spi.write(&dummy, 1, buffer, 16); |
justinbuckland | 0:147db0900012 | 100 | cs=1; |
justinbuckland | 0:147db0900012 | 101 | |
justinbuckland | 0:147db0900012 | 102 | //loop over bytes to add channel voltage values |
justinbuckland | 0:147db0900012 | 103 | for (int i=0; i<8; i++){ |
justinbuckland | 0:147db0900012 | 104 | val_array[i] = buffer[2*i]<<8 | buffer16[(2*i) + 1]; |
justinbuckland | 0:147db0900012 | 105 | values [i] = val_array[i]; |
justinbuckland | 0:147db0900012 | 106 | } |
justinbuckland | 0:147db0900012 | 107 | i1 = (double) (val_array[0]-val_array[1]); |
justinbuckland | 0:147db0900012 | 108 | i2 = (double) (val_array[2]-val_array[1]); |
justinbuckland | 0:147db0900012 | 109 | v1 = (double) (val_array[4]-val_array[5]); |
justinbuckland | 0:147db0900012 | 110 | v2 = (double) (val_array[6]-val_array[7]); |
justinbuckland | 0:147db0900012 | 111 | |
justinbuckland | 0:147db0900012 | 112 | // update values if no division by zero (to avoid NaN if PSU is off) |
justinbuckland | 0:147db0900012 | 113 | if (i1 > 0) r1 = v1/i1; |
justinbuckland | 0:147db0900012 | 114 | if (i2 > 0) r2 = v2/i2; |
justinbuckland | 0:147db0900012 | 115 | |
justinbuckland | 0:147db0900012 | 116 | // select heater (inner or outer) |
justinbuckland | 1:68515313ce3e | 117 | if (HEATER == 1) r = r1; |
justinbuckland | 1:68515313ce3e | 118 | if (HEATER == 2) r = r2; |
justinbuckland | 0:147db0900012 | 119 | } |
justinbuckland | 0:147db0900012 | 120 | |
justinbuckland | 0:147db0900012 | 121 | void tempControl(int endTime){ |
justinbuckland | 0:147db0900012 | 122 | eTime = timer.read_ms(); |
justinbuckland | 0:147db0900012 | 123 | while (eTime < endTime) { |
justinbuckland | 0:147db0900012 | 124 | yLED = 1; |
justinbuckland | 0:147db0900012 | 125 | drive = 1; |
justinbuckland | 0:147db0900012 | 126 | wait_us(MEAS_DELAY); // wait for heater current to stabilise |
justinbuckland | 0:147db0900012 | 127 | readChannels (buffer16, val_array); // read ADC channels and update r |
justinbuckland | 0:147db0900012 | 128 | rAvg = ((N_ROLL_AVG-1)*rAvg + r)/N_ROLL_AVG; // calculate rolling average r |
justinbuckland | 0:147db0900012 | 129 | // printf("hold r: %8.4f\r\n",r); |
justinbuckland | 0:147db0900012 | 130 | if (rAvg > rSet) { |
justinbuckland | 0:147db0900012 | 131 | drive = 0; // turn off heater if setpoint resistance is exceeded |
justinbuckland | 0:147db0900012 | 132 | yLED = 0; |
justinbuckland | 0:147db0900012 | 133 | } |
justinbuckland | 0:147db0900012 | 134 | // printf("set r: %8.4f\r\n",r); |
justinbuckland | 0:147db0900012 | 135 | |
justinbuckland | 0:147db0900012 | 136 | logFile(); |
justinbuckland | 0:147db0900012 | 137 | wait_us(PULSE_WIDTH); //wait until pulse_width (us) has elapsed |
justinbuckland | 0:147db0900012 | 138 | eTime = timer.read_ms(); |
justinbuckland | 0:147db0900012 | 139 | } |
justinbuckland | 0:147db0900012 | 140 | } |
justinbuckland | 0:147db0900012 | 141 | |
justinbuckland | 0:147db0900012 | 142 | void tempControlRamp(float setStartR, float setEndR, int endTime){ |
justinbuckland | 0:147db0900012 | 143 | float setRate; |
justinbuckland | 0:147db0900012 | 144 | int startTime; |
justinbuckland | 0:147db0900012 | 145 | |
justinbuckland | 0:147db0900012 | 146 | |
justinbuckland | 0:147db0900012 | 147 | startTime = timer.read_ms(); |
justinbuckland | 0:147db0900012 | 148 | setRate = (setEndR - setStartR)/(endTime - startTime); |
justinbuckland | 0:147db0900012 | 149 | eTime = startTime; |
justinbuckland | 0:147db0900012 | 150 | while (eTime < endTime) { |
justinbuckland | 0:147db0900012 | 151 | rSet = setStartR + setRate*(eTime - startTime); |
justinbuckland | 0:147db0900012 | 152 | yLED = 1; |
justinbuckland | 0:147db0900012 | 153 | drive = 1; |
justinbuckland | 0:147db0900012 | 154 | wait_us(MEAS_DELAY); // wait for heater current to stabilise |
justinbuckland | 0:147db0900012 | 155 | readChannels (buffer16, val_array); // read ADC channels and update r |
justinbuckland | 0:147db0900012 | 156 | rAvg = ((N_ROLL_AVG-1)*rAvg + r)/N_ROLL_AVG; // measure r |
justinbuckland | 0:147db0900012 | 157 | if (rAvg > rSet) { |
justinbuckland | 0:147db0900012 | 158 | drive = 0; // turn off heater if setpoint resistance is exceeded |
justinbuckland | 0:147db0900012 | 159 | yLED = 0; |
justinbuckland | 0:147db0900012 | 160 | } |
justinbuckland | 0:147db0900012 | 161 | // printf("ramp r: %8.4f\r\n",r); |
justinbuckland | 0:147db0900012 | 162 | |
justinbuckland | 0:147db0900012 | 163 | logFile(); |
justinbuckland | 0:147db0900012 | 164 | wait_us(PULSE_WIDTH); //wait until pulse_width (us) has elapsed |
justinbuckland | 0:147db0900012 | 165 | eTime = timer.read_ms(); |
justinbuckland | 0:147db0900012 | 166 | } |
justinbuckland | 0:147db0900012 | 167 | } |
justinbuckland | 0:147db0900012 | 168 | |
justinbuckland | 0:147db0900012 | 169 | |
justinbuckland | 0:147db0900012 | 170 | int main() { |
justinbuckland | 0:147db0900012 | 171 | int endTime = 0; |
justinbuckland | 1:68515313ce3e | 172 | int iStep = 0; |
justinbuckland | 0:147db0900012 | 173 | |
justinbuckland | 0:147db0900012 | 174 | rLED = 0; |
justinbuckland | 0:147db0900012 | 175 | yLED = 0; |
justinbuckland | 0:147db0900012 | 176 | gLED = 0; |
justinbuckland | 0:147db0900012 | 177 | |
justinbuckland | 0:147db0900012 | 178 | drive = 0; |
justinbuckland | 0:147db0900012 | 179 | |
justinbuckland | 0:147db0900012 | 180 | pc.baud(115200); |
justinbuckland | 0:147db0900012 | 181 | |
justinbuckland | 0:147db0900012 | 182 | sprintf(outString," iCycle, Time(ms), r, rSet\n"); |
justinbuckland | 0:147db0900012 | 183 | pc.printf("%s", outString); |
justinbuckland | 0:147db0900012 | 184 | fprintf(fp, outString); |
justinbuckland | 0:147db0900012 | 185 | |
justinbuckland | 0:147db0900012 | 186 | reset = 1; |
justinbuckland | 0:147db0900012 | 187 | wait_ms(1); |
justinbuckland | 0:147db0900012 | 188 | reset = 0; |
justinbuckland | 0:147db0900012 | 189 | |
justinbuckland | 0:147db0900012 | 190 | //set SPI serial to 2MHz, 16 bit data transfer, mode 2 (clock normally high, data preceeding clock cycle) |
justinbuckland | 0:147db0900012 | 191 | spi.format(8,2); |
justinbuckland | 0:147db0900012 | 192 | spi.frequency(2000000); |
justinbuckland | 0:147db0900012 | 193 | spi.set_default_write_value(0x00); |
justinbuckland | 0:147db0900012 | 194 | cs = 1; |
justinbuckland | 0:147db0900012 | 195 | |
justinbuckland | 0:147db0900012 | 196 | rLED = 1; // thermal cycling in progress |
justinbuckland | 0:147db0900012 | 197 | yLED = 0; // heater off |
justinbuckland | 0:147db0900012 | 198 | gLED = 1; // microprocessor power on |
justinbuckland | 0:147db0900012 | 199 | |
justinbuckland | 0:147db0900012 | 200 | timer.start(); |
justinbuckland | 0:147db0900012 | 201 | |
justinbuckland | 1:68515313ce3e | 202 | while (iStep < N_STEPS) { |
justinbuckland | 1:68515313ce3e | 203 | endTime = endTime + T_HOLD; |
justinbuckland | 1:68515313ce3e | 204 | rSet = R_SET_START + R_SET_STEP*iStep; |
justinbuckland | 1:68515313ce3e | 205 | tempControl(endTime); |
justinbuckland | 1:68515313ce3e | 206 | iStep++; |
justinbuckland | 0:147db0900012 | 207 | } |
justinbuckland | 1:68515313ce3e | 208 | |
justinbuckland | 0:147db0900012 | 209 | // extinguish rLED (thermocycling complete), ensure heater is off and close log file for access |
justinbuckland | 0:147db0900012 | 210 | drive = 0; |
justinbuckland | 0:147db0900012 | 211 | rLED = 0; |
justinbuckland | 0:147db0900012 | 212 | logTime = 0; |
justinbuckland | 0:147db0900012 | 213 | logFile(); |
justinbuckland | 0:147db0900012 | 214 | fclose(fp); |
justinbuckland | 0:147db0900012 | 215 | } |