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