ADC logging with demo drive board for calibration ADC read synchronised with heater on time

Dependencies:   mbed MODSERIAL FastPWM ADS8568_ADC

Committer:
justinbuckland
Date:
Tue Jul 31 17:25:41 2018 +0000
Revision:
4:694f0e328a52
Parent:
3:447b0de4295a
Child:
5:67e4ee9a00dc
Thermocycling V2 electronics

Who changed what in which revision?

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