LEX_Threaded_Programming
Dependencies: Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC
main.cpp@29:818c098c9e5a, 2019-11-16 (annotated)
- Committer:
- justinbuckland
- Date:
- Sat Nov 16 06:06:13 2019 +0000
- Revision:
- 29:818c098c9e5a
- Parent:
- 28:b2513f36a50d
- Child:
- 30:b28088f244c2
Added reporting of variance of resistance measurements
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
omatthews | 0:54bedd3964e2 | 1 | #include "mbed.h" |
omatthews | 0:54bedd3964e2 | 2 | #include "pb.h" |
omatthews | 0:54bedd3964e2 | 3 | #include "pb_decode.h" |
omatthews | 0:54bedd3964e2 | 4 | #include "pb_encode.h" |
omatthews | 0:54bedd3964e2 | 5 | #include "MODSERIAL.h" |
omatthews | 0:54bedd3964e2 | 6 | #include "ADS8568_ADC.h" |
omatthews | 0:54bedd3964e2 | 7 | #include "Heater.h" |
omatthews | 0:54bedd3964e2 | 8 | #include "FastPWM.h" |
omatthews | 0:54bedd3964e2 | 9 | #include "memspcr.pb.h" |
omatthews | 0:54bedd3964e2 | 10 | #include <vector> |
omatthews | 0:54bedd3964e2 | 11 | #include <iterator> |
omatthews | 0:54bedd3964e2 | 12 | |
paullj | 14:39a5eb99fbdb | 13 | #define BUFFER_SIZE 8192 |
justinbuckland | 17:d86e749ae9be | 14 | |
justinbuckland | 17:d86e749ae9be | 15 | //UID lookup address and pointer |
justinbuckland | 17:d86e749ae9be | 16 | #define UID_ADDR 0x1FFF7A10 |
justinbuckland | 17:d86e749ae9be | 17 | unsigned long *uid = (unsigned long *) UID_ADDR; |
justinbuckland | 17:d86e749ae9be | 18 | |
justinbuckland | 17:d86e749ae9be | 19 | //UID and drive board calibration table |
justinbuckland | 17:d86e749ae9be | 20 | #define UID_TABLE_LENGTH 4 |
justinbuckland | 17:d86e749ae9be | 21 | |
justinbuckland | 17:d86e749ae9be | 22 | int drive_board_serial_number[UID_TABLE_LENGTH] = |
justinbuckland | 17:d86e749ae9be | 23 | {1, |
justinbuckland | 17:d86e749ae9be | 24 | 2, |
justinbuckland | 17:d86e749ae9be | 25 | 3, |
justinbuckland | 17:d86e749ae9be | 26 | 4}; |
justinbuckland | 17:d86e749ae9be | 27 | |
justinbuckland | 17:d86e749ae9be | 28 | unsigned long drive_board_uid[UID_TABLE_LENGTH][3] = |
justinbuckland | 17:d86e749ae9be | 29 | {{0x005B0060, 0x32375101, 0x32363531}, |
justinbuckland | 28:b2513f36a50d | 30 | {0x00530028, 0x32375116, 0x30333732}, // updated board 2 UID {0x0051003D, 0x32375114, 0x30333732}, |
justinbuckland | 17:d86e749ae9be | 31 | {0x00520060, 0x32375101, 0x32363531}, |
justinbuckland | 17:d86e749ae9be | 32 | {0x00570060, 0x32375101, 0x32363531}}; |
justinbuckland | 17:d86e749ae9be | 33 | |
justinbuckland | 17:d86e749ae9be | 34 | float drive_board_cal[UID_TABLE_LENGTH][2][2] = |
paullj | 24:f59af7a2effb | 35 | {{{0.0908347476278717, 10.1921343711427}, {0.0497613470164513, 10.2109327517567}}, |
paullj | 24:f59af7a2effb | 36 | {{0.0596907336847412, 10.1550084867437}, {0.0320376283698263, 10.2580153464834}}, |
paullj | 24:f59af7a2effb | 37 | {{0.0119648730956925, 10.4065902688349}, {0.0256785142683800, 10.2921134395920}}, |
paullj | 24:f59af7a2effb | 38 | {{0.0482969653247984, 10.0688110602909}, {0.0882102280729402, 10.1322703041679}}}; |
justinbuckland | 17:d86e749ae9be | 39 | |
omatthews | 0:54bedd3964e2 | 40 | Heater * heater; |
intrinseca | 4:63d7f2a0dec6 | 41 | float r_gradient; //setpoint setting |
omatthews | 5:702b32ead94e | 42 | |
justinbuckland | 8:58c6d51957df | 43 | MODSERIAL pc(PA_9, PA_10, BUFFER_SIZE); //mcu TX, RX, BUFFER_SIZE byte TX and RX buffers |
omatthews | 0:54bedd3964e2 | 44 | ADS8568_ADC adc(PB_15, PB_14, PB_13, PB_12, PC_15, PC_0, PC_1, PC_2, PC_3); |
omatthews | 0:54bedd3964e2 | 45 | I2C i2c(PB_7, PB_8); //SDA, SCL |
omatthews | 0:54bedd3964e2 | 46 | Timer timer; |
omatthews | 0:54bedd3964e2 | 47 | DigitalIn adc_busy(PA_8); //Busy interrupt sig# |
omatthews | 5:702b32ead94e | 48 | |
justinbuckland | 17:d86e749ae9be | 49 | //Fluidic Control |
justinbuckland | 13:b2e00297b465 | 50 | DigitalOut pump(PA_2); |
justinbuckland | 13:b2e00297b465 | 51 | AnalogIn pressure_1(PA_5); |
justinbuckland | 13:b2e00297b465 | 52 | |
justinbuckland | 17:d86e749ae9be | 53 | float pressure_in; |
justinbuckland | 17:d86e749ae9be | 54 | float pressure_out; |
omatthews | 0:54bedd3964e2 | 55 | |
omatthews | 0:54bedd3964e2 | 56 | //Heater Control |
justinbuckland | 18:376350fb7ef9 | 57 | FastPWM drive_1(PC_9); |
justinbuckland | 18:376350fb7ef9 | 58 | FastPWM drive_2(PC_8); |
justinbuckland | 18:376350fb7ef9 | 59 | FastPWM guard_1(PC_7); |
justinbuckland | 18:376350fb7ef9 | 60 | FastPWM guard_2(PC_6); |
justinbuckland | 7:a4fc853feb30 | 61 | |
justinbuckland | 18:376350fb7ef9 | 62 | //ADC channels for heater current and voltage measurements |
justinbuckland | 18:376350fb7ef9 | 63 | int i_port_1 = 0; |
justinbuckland | 18:376350fb7ef9 | 64 | int i_port_2 = 2; |
justinbuckland | 18:376350fb7ef9 | 65 | int v_port_1 = 1; |
justinbuckland | 18:376350fb7ef9 | 66 | int v_port_2 = 3; |
omatthews | 0:54bedd3964e2 | 67 | |
justinbuckland | 18:376350fb7ef9 | 68 | //Heater ID: heater 1 is nearer liquid sense location, heater 2 is other location |
justinbuckland | 18:376350fb7ef9 | 69 | int heater_ID; |
omatthews | 0:54bedd3964e2 | 70 | |
justinbuckland | 9:9474da78cec3 | 71 | //Illumination LED Control |
justinbuckland | 9:9474da78cec3 | 72 | |
justinbuckland | 7:a4fc853feb30 | 73 | //Indicator LEDs |
justinbuckland | 13:b2e00297b465 | 74 | DigitalOut hb_led(PC_13); //Red |
justinbuckland | 13:b2e00297b465 | 75 | DigitalOut led_0(PC_4); //Green |
justinbuckland | 13:b2e00297b465 | 76 | DigitalOut led_1(PC_5); //Red |
omatthews | 0:54bedd3964e2 | 77 | |
justinbuckland | 7:a4fc853feb30 | 78 | //Camera and LED drive |
justinbuckland | 7:a4fc853feb30 | 79 | DigitalOut camTrigger(PB_2); //Trigger camera |
justinbuckland | 12:cadcea541fbf | 80 | DigitalOut ledDrive(PB_4); //Drive LED for fluorescence detection |
justinbuckland | 7:a4fc853feb30 | 81 | |
omatthews | 0:54bedd3964e2 | 82 | //User buttons |
omatthews | 0:54bedd3964e2 | 83 | DigitalIn user_0(PB_0); |
omatthews | 0:54bedd3964e2 | 84 | DigitalIn user_1(PB_1); |
omatthews | 0:54bedd3964e2 | 85 | |
omatthews | 0:54bedd3964e2 | 86 | BusOut converts(PC_0, PC_1, PC_2, PC_3); |
omatthews | 0:54bedd3964e2 | 87 | |
omatthews | 0:54bedd3964e2 | 88 | //Threads |
omatthews | 6:ef2bcc5fe3af | 89 | Thread heater_control(osPriorityHigh); |
omatthews | 6:ef2bcc5fe3af | 90 | Thread logging_thread(osPriorityAboveNormal); |
justinbuckland | 19:8154688252fd | 91 | Thread pressure_thread(osPriorityNormal); |
omatthews | 0:54bedd3964e2 | 92 | |
omatthews | 0:54bedd3964e2 | 93 | //Tickers |
omatthews | 0:54bedd3964e2 | 94 | Ticker heat_tick; |
omatthews | 0:54bedd3964e2 | 95 | Ticker pressure_tick; |
omatthews | 0:54bedd3964e2 | 96 | Ticker log_tick; |
omatthews | 0:54bedd3964e2 | 97 | |
omatthews | 0:54bedd3964e2 | 98 | //Flags |
omatthews | 5:702b32ead94e | 99 | EventFlags flags; //Flags: |
omatthews | 5:702b32ead94e | 100 | // 0 => update heater |
omatthews | 5:702b32ead94e | 101 | // 1 => log state |
justinbuckland | 13:b2e00297b465 | 102 | // 2 => read pressure |
omatthews | 5:702b32ead94e | 103 | bool triggered_flag; |
omatthews | 0:54bedd3964e2 | 104 | bool status = true; |
omatthews | 0:54bedd3964e2 | 105 | |
omatthews | 0:54bedd3964e2 | 106 | //Configuration data |
omatthews | 0:54bedd3964e2 | 107 | memspcr_ExperimentConfiguration exp_config = memspcr_ExperimentConfiguration_init_zero; |
omatthews | 0:54bedd3964e2 | 108 | int buffer_length; |
omatthews | 0:54bedd3964e2 | 109 | size_t message_length; |
justinbuckland | 8:58c6d51957df | 110 | uint8_t buffer[BUFFER_SIZE]; |
omatthews | 0:54bedd3964e2 | 111 | |
omatthews | 0:54bedd3964e2 | 112 | |
omatthews | 0:54bedd3964e2 | 113 | //Functions for reading and decoding the message__________________________________________________ |
omatthews | 0:54bedd3964e2 | 114 | |
omatthews | 0:54bedd3964e2 | 115 | void read_message() |
omatthews | 0:54bedd3964e2 | 116 | { |
justinbuckland | 7:a4fc853feb30 | 117 | if (pc.scanf("%d",&message_length) < 0){pc.printf("# Error reading message length");} |
omatthews | 5:702b32ead94e | 118 | size_t buffer_length = sizeof(buffer); |
omatthews | 5:702b32ead94e | 119 | if (message_length > buffer_length) |
omatthews | 5:702b32ead94e | 120 | { |
justinbuckland | 7:a4fc853feb30 | 121 | pc.printf("# Message length exceeds buffer. \n Input configuration file\n"); |
omatthews | 5:702b32ead94e | 122 | read_message(); |
omatthews | 5:702b32ead94e | 123 | return; |
omatthews | 5:702b32ead94e | 124 | } |
justinbuckland | 7:a4fc853feb30 | 125 | pc.printf("# Message is %d chars long, buffer length is %d\n",message_length,buffer_length); |
omatthews | 5:702b32ead94e | 126 | unsigned int c; |
omatthews | 5:702b32ead94e | 127 | for (int i = 0; i < message_length; i++) |
omatthews | 0:54bedd3964e2 | 128 | { |
omatthews | 0:54bedd3964e2 | 129 | pc.scanf("%02X",&c); |
omatthews | 0:54bedd3964e2 | 130 | buffer[i] = (char) c; |
omatthews | 0:54bedd3964e2 | 131 | } |
omatthews | 0:54bedd3964e2 | 132 | } |
omatthews | 0:54bedd3964e2 | 133 | |
omatthews | 0:54bedd3964e2 | 134 | void decode_message() |
omatthews | 0:54bedd3964e2 | 135 | { |
omatthews | 5:702b32ead94e | 136 | // Create a stream that reads from the buffer. |
omatthews | 0:54bedd3964e2 | 137 | pb_istream_t istream = pb_istream_from_buffer(buffer, message_length); |
omatthews | 0:54bedd3964e2 | 138 | |
omatthews | 5:702b32ead94e | 139 | //Now we are ready to decode the message. |
omatthews | 0:54bedd3964e2 | 140 | status = pb_decode(&istream, memspcr_ExperimentConfiguration_fields, &exp_config); |
omatthews | 0:54bedd3964e2 | 141 | |
omatthews | 5:702b32ead94e | 142 | // Check for errors... |
omatthews | 5:702b32ead94e | 143 | if (!status) { |
justinbuckland | 7:a4fc853feb30 | 144 | pc.printf("# Decoding failed: %s\n", PB_GET_ERROR(&istream)); |
omatthews | 0:54bedd3964e2 | 145 | } |
omatthews | 0:54bedd3964e2 | 146 | } |
omatthews | 0:54bedd3964e2 | 147 | |
omatthews | 0:54bedd3964e2 | 148 | bool decode_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) |
omatthews | 0:54bedd3964e2 | 149 | { |
omatthews | 0:54bedd3964e2 | 150 | vector <memspcr_ThermalStep> * dest = (vector <memspcr_ThermalStep> *)(*arg); |
omatthews | 0:54bedd3964e2 | 151 | memspcr_ThermalStep result = memspcr_ThermalStep_init_zero; |
omatthews | 0:54bedd3964e2 | 152 | status = pb_decode(stream, memspcr_ThermalStep_fields, & result); |
omatthews | 5:702b32ead94e | 153 | |
omatthews | 5:702b32ead94e | 154 | if (!status) { |
justinbuckland | 7:a4fc853feb30 | 155 | pc.printf("# Decode callback failed\n"); |
omatthews | 0:54bedd3964e2 | 156 | } |
omatthews | 0:54bedd3964e2 | 157 | |
intrinseca | 4:63d7f2a0dec6 | 158 | dest->push_back(result); //CHECK: Does result get copied into the vector? |
omatthews | 0:54bedd3964e2 | 159 | return true; |
omatthews | 0:54bedd3964e2 | 160 | } |
omatthews | 0:54bedd3964e2 | 161 | |
omatthews | 0:54bedd3964e2 | 162 | |
omatthews | 0:54bedd3964e2 | 163 | //Ticking functions_________________________________________________________________ |
omatthews | 0:54bedd3964e2 | 164 | |
omatthews | 6:ef2bcc5fe3af | 165 | |
omatthews | 5:702b32ead94e | 166 | void temp_trigger() |
omatthews | 0:54bedd3964e2 | 167 | { |
omatthews | 5:702b32ead94e | 168 | //This function triggers a temperature update. |
omatthews | 5:702b32ead94e | 169 | //N.B. update cannot be called directly from a ticker as tickers and |
omatthews | 0:54bedd3964e2 | 170 | //reading the ADC both rely on interrupts. |
omatthews | 5:702b32ead94e | 171 | flags.set(0x1); |
omatthews | 0:54bedd3964e2 | 172 | } |
omatthews | 0:54bedd3964e2 | 173 | |
omatthews | 6:ef2bcc5fe3af | 174 | |
omatthews | 2:b27d8f9a6e49 | 175 | void log_trigger() |
omatthews | 2:b27d8f9a6e49 | 176 | { |
omatthews | 5:702b32ead94e | 177 | flags.set(0x2); |
omatthews | 2:b27d8f9a6e49 | 178 | } |
justinbuckland | 7:a4fc853feb30 | 179 | |
justinbuckland | 13:b2e00297b465 | 180 | void pressure_trigger() |
omatthews | 0:54bedd3964e2 | 181 | { |
justinbuckland | 19:8154688252fd | 182 | flags.set(0x4); |
justinbuckland | 10:f8202e71e765 | 183 | } |
omatthews | 0:54bedd3964e2 | 184 | |
omatthews | 0:54bedd3964e2 | 185 | |
omatthews | 5:702b32ead94e | 186 | //Other functions__________________________________________________________________ |
omatthews | 0:54bedd3964e2 | 187 | |
omatthews | 0:54bedd3964e2 | 188 | |
omatthews | 0:54bedd3964e2 | 189 | void temp_control() { |
omatthews | 0:54bedd3964e2 | 190 | while(1){ |
omatthews | 6:ef2bcc5fe3af | 191 | flags.wait_any(0x1,osWaitForever,true); |
omatthews | 0:54bedd3964e2 | 192 | heater->read(); |
omatthews | 0:54bedd3964e2 | 193 | heater->update(); |
justinbuckland | 17:d86e749ae9be | 194 | wait_us(200);//Give other threads time to get selected |
omatthews | 0:54bedd3964e2 | 195 | } |
omatthews | 0:54bedd3964e2 | 196 | } |
omatthews | 5:702b32ead94e | 197 | |
omatthews | 2:b27d8f9a6e49 | 198 | void log_state() |
omatthews | 2:b27d8f9a6e49 | 199 | { |
omatthews | 2:b27d8f9a6e49 | 200 | while(1){ |
omatthews | 6:ef2bcc5fe3af | 201 | flags.wait_any(0x2,osWaitForever,true); |
justinbuckland | 29:818c098c9e5a | 202 | //Output time, R_avg, R_ref, R_var, error, error_integrated, duty cycle, input pressure, output pressure |
justinbuckland | 26:e2e834e16367 | 203 | pc.printf("%10d,%10d,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f\n", |
justinbuckland | 29:818c098c9e5a | 204 | heater_ID, timer.read_ms(), heater->Get_R_avg(), heater->Get_R_ref(), heater->Get_R_var(), heater->Get_error(), heater->Get_error_integrated(), heater->Get_D(), pressure_in, pressure_out); |
justinbuckland | 17:d86e749ae9be | 205 | wait_us(200);//Give other threads time to get selected |
justinbuckland | 19:8154688252fd | 206 | } |
omatthews | 2:b27d8f9a6e49 | 207 | } |
omatthews | 5:702b32ead94e | 208 | |
justinbuckland | 13:b2e00297b465 | 209 | void pressure_control() { |
justinbuckland | 13:b2e00297b465 | 210 | while(1){ |
justinbuckland | 19:8154688252fd | 211 | flags.wait_any(0x4,osWaitForever,true); |
justinbuckland | 17:d86e749ae9be | 212 | pressure_in = pressure_1.read(); |
justinbuckland | 20:ccbe2a03893d | 213 | if (pressure_in < exp_config.fluidics.pressure_sensor_setpoint_adc - exp_config.fluidics.pressure_sensor_hysteresis_adc) { |
justinbuckland | 13:b2e00297b465 | 214 | led_1 = 1; |
justinbuckland | 13:b2e00297b465 | 215 | pump = 1; |
justinbuckland | 13:b2e00297b465 | 216 | } |
justinbuckland | 20:ccbe2a03893d | 217 | else if (pressure_in > exp_config.fluidics.pressure_sensor_setpoint_adc) { |
justinbuckland | 13:b2e00297b465 | 218 | led_1 = 0; |
justinbuckland | 13:b2e00297b465 | 219 | pump = 0; |
justinbuckland | 13:b2e00297b465 | 220 | } |
justinbuckland | 13:b2e00297b465 | 221 | } |
justinbuckland | 13:b2e00297b465 | 222 | } |
justinbuckland | 13:b2e00297b465 | 223 | |
justinbuckland | 13:b2e00297b465 | 224 | |
omatthews | 5:702b32ead94e | 225 | void set_point_routine(std::vector<memspcr_ThermalStep> profile) { |
omatthews | 5:702b32ead94e | 226 | int curr_time; |
omatthews | 5:702b32ead94e | 227 | vector <memspcr_ThermalStep>::iterator it_prev, it = profile.begin(); |
omatthews | 5:702b32ead94e | 228 | if (it->elapsed_time_ms != 0) |
omatthews | 5:702b32ead94e | 229 | { |
justinbuckland | 7:a4fc853feb30 | 230 | pc.printf("# Error: the first point in the profile should be at time 0.\n"); |
omatthews | 5:702b32ead94e | 231 | return; |
omatthews | 5:702b32ead94e | 232 | } |
omatthews | 2:b27d8f9a6e49 | 233 | it++; |
omatthews | 0:54bedd3964e2 | 234 | |
omatthews | 0:54bedd3964e2 | 235 | for (it_prev = profile.begin(); it < profile.end(); it ++, it_prev++){ |
omatthews | 0:54bedd3964e2 | 236 | triggered_flag = false; |
paullj | 14:39a5eb99fbdb | 237 | r_gradient = (it->resistance_set_point - it_prev->resistance_set_point)/(it->elapsed_time_ms - it_prev->elapsed_time_ms); |
omatthews | 0:54bedd3964e2 | 238 | while ((curr_time = timer.read_ms()) <= it->elapsed_time_ms){ |
paullj | 14:39a5eb99fbdb | 239 | heater->Set_ref(it_prev->resistance_set_point + r_gradient * (curr_time - it_prev->elapsed_time_ms)); |
justinbuckland | 8:58c6d51957df | 240 | |
justinbuckland | 9:9474da78cec3 | 241 | if (!triggered_flag && (it->camera_offset_ms != 0) && (curr_time > it_prev->elapsed_time_ms + it->camera_offset_ms)) |
omatthews | 0:54bedd3964e2 | 242 | { |
justinbuckland | 9:9474da78cec3 | 243 | //Start camera exposure and turn on LED if camera_offset_ms is non-zero |
justinbuckland | 7:a4fc853feb30 | 244 | camTrigger = 0; |
justinbuckland | 7:a4fc853feb30 | 245 | wait_us(10); |
justinbuckland | 7:a4fc853feb30 | 246 | camTrigger = 1; |
justinbuckland | 7:a4fc853feb30 | 247 | led_0 = 1; |
justinbuckland | 12:cadcea541fbf | 248 | ledDrive = 1; |
omatthews | 0:54bedd3964e2 | 249 | triggered_flag = true; |
omatthews | 0:54bedd3964e2 | 250 | } |
justinbuckland | 8:58c6d51957df | 251 | wait_us(200); |
omatthews | 0:54bedd3964e2 | 252 | } |
justinbuckland | 8:58c6d51957df | 253 | //Stop camera exposure and turn off LED at end of time segment |
justinbuckland | 8:58c6d51957df | 254 | camTrigger = 0; |
justinbuckland | 8:58c6d51957df | 255 | led_0 = 0; |
justinbuckland | 12:cadcea541fbf | 256 | ledDrive = 0; |
omatthews | 0:54bedd3964e2 | 257 | } |
omatthews | 0:54bedd3964e2 | 258 | } |
omatthews | 0:54bedd3964e2 | 259 | |
omatthews | 0:54bedd3964e2 | 260 | |
omatthews | 5:702b32ead94e | 261 | int main() |
omatthews | 5:702b32ead94e | 262 | { |
justinbuckland | 18:376350fb7ef9 | 263 | int i_board = -1; |
justinbuckland | 18:376350fb7ef9 | 264 | int i_heater; |
justinbuckland | 18:376350fb7ef9 | 265 | float drive_cal_a, drive_cal_b; |
justinbuckland | 18:376350fb7ef9 | 266 | |
omatthews | 0:54bedd3964e2 | 267 | pc.baud(115200); |
omatthews | 0:54bedd3964e2 | 268 | adc.init(); |
justinbuckland | 17:d86e749ae9be | 269 | |
justinbuckland | 17:d86e749ae9be | 270 | pc.printf("\r\nUnique ID: %08X %08X %08X \r\n", uid[0], uid[1], uid[2]); |
justinbuckland | 17:d86e749ae9be | 271 | for (int i = 0; i < UID_TABLE_LENGTH; i++) |
justinbuckland | 17:d86e749ae9be | 272 | { |
justinbuckland | 17:d86e749ae9be | 273 | if (uid[0]==drive_board_uid[i][0] && uid[1]==drive_board_uid[i][1] && uid[2]==drive_board_uid[i][2]) |
justinbuckland | 17:d86e749ae9be | 274 | { |
justinbuckland | 17:d86e749ae9be | 275 | i_board = i; |
justinbuckland | 17:d86e749ae9be | 276 | i = UID_TABLE_LENGTH; |
justinbuckland | 17:d86e749ae9be | 277 | } |
justinbuckland | 17:d86e749ae9be | 278 | } |
justinbuckland | 17:d86e749ae9be | 279 | |
omatthews | 0:54bedd3964e2 | 280 | buffer_length = sizeof(buffer)/sizeof(uint8_t); |
paullj | 22:f65353f6e935 | 281 | pc.printf("# Input [CONFIGURATION] file\n"); |
justinbuckland | 9:9474da78cec3 | 282 | |
intrinseca | 4:63d7f2a0dec6 | 283 | //set up nanopb |
omatthews | 5:702b32ead94e | 284 | std::vector<memspcr_ThermalStep> profile; |
omatthews | 5:702b32ead94e | 285 | exp_config.profile.funcs.decode = decode_callback; |
omatthews | 5:702b32ead94e | 286 | exp_config.profile.arg = &profile; |
omatthews | 5:702b32ead94e | 287 | |
intrinseca | 4:63d7f2a0dec6 | 288 | //read and decode configuration |
justinbuckland | 18:376350fb7ef9 | 289 | read_message(); |
justinbuckland | 7:a4fc853feb30 | 290 | pc.printf("# Message read\n"); |
omatthews | 0:54bedd3964e2 | 291 | decode_message(); |
justinbuckland | 7:a4fc853feb30 | 292 | pc.printf("# Message decoded\n"); |
omatthews | 5:702b32ead94e | 293 | |
justinbuckland | 18:376350fb7ef9 | 294 | //Select heater |
justinbuckland | 18:376350fb7ef9 | 295 | if (exp_config.selected_heater == memspcr_ExperimentConfiguration_Heater_HEATER_1) |
justinbuckland | 18:376350fb7ef9 | 296 | i_heater = 0; |
justinbuckland | 18:376350fb7ef9 | 297 | else if (exp_config.selected_heater == memspcr_ExperimentConfiguration_Heater_HEATER_2) |
justinbuckland | 18:376350fb7ef9 | 298 | i_heater = 1; |
justinbuckland | 18:376350fb7ef9 | 299 | else { |
justinbuckland | 8:58c6d51957df | 300 | pc.printf("# Error - no heater has been selected\n"); |
omatthews | 5:702b32ead94e | 301 | return 1; |
omatthews | 5:702b32ead94e | 302 | } |
justinbuckland | 18:376350fb7ef9 | 303 | heater_ID = i_heater + 1; |
justinbuckland | 18:376350fb7ef9 | 304 | |
justinbuckland | 18:376350fb7ef9 | 305 | //Set drive ADC->Resistance calibration coefficients (default: no change if board not found) |
justinbuckland | 18:376350fb7ef9 | 306 | drive_cal_a = drive_board_cal[i_board][i_heater][0]; |
justinbuckland | 18:376350fb7ef9 | 307 | drive_cal_b = drive_board_cal[i_board][i_heater][1]; |
justinbuckland | 18:376350fb7ef9 | 308 | |
justinbuckland | 18:376350fb7ef9 | 309 | pc.printf("# Heater: %d\n", heater_ID); |
justinbuckland | 20:ccbe2a03893d | 310 | pc.printf("# Drive board calibration: %10.6f, %10.6f\n", drive_cal_a, drive_cal_b); |
omatthews | 5:702b32ead94e | 311 | |
justinbuckland | 18:376350fb7ef9 | 312 | //Define heaters |
justinbuckland | 18:376350fb7ef9 | 313 | Heater * heater_1 = new Heater(i_port_1, v_port_1, drive_cal_a, drive_cal_b, & drive_1, & guard_1, & adc, adc_busy, exp_config.thermal); |
justinbuckland | 18:376350fb7ef9 | 314 | Heater * heater_2 = new Heater(i_port_2, v_port_2, drive_cal_a, drive_cal_b, & drive_2, & guard_2, & adc, adc_busy, exp_config.thermal); |
justinbuckland | 18:376350fb7ef9 | 315 | if (i_heater == 0) |
justinbuckland | 18:376350fb7ef9 | 316 | heater = heater_1; |
justinbuckland | 18:376350fb7ef9 | 317 | else |
justinbuckland | 18:376350fb7ef9 | 318 | heater = heater_2; |
justinbuckland | 18:376350fb7ef9 | 319 | |
justinbuckland | 20:ccbe2a03893d | 320 | //Start pressure control |
justinbuckland | 20:ccbe2a03893d | 321 | pc.printf("# Pressure setpoint: %10.6f hystersess: %10.6f\n",exp_config.fluidics.pressure_sensor_setpoint_adc, exp_config.fluidics.pressure_sensor_hysteresis_adc); |
paullj | 22:f65353f6e935 | 322 | pc.printf("# Waiting for signal to begin [PRESSURE] control (type p or press button 0)\n"); |
justinbuckland | 18:376350fb7ef9 | 323 | while (pc.getcNb()!='p' && !user_0); |
justinbuckland | 18:376350fb7ef9 | 324 | pc.printf("# Pressure control start signal received\n"); |
justinbuckland | 13:b2e00297b465 | 325 | pressure_thread.start(& pressure_control); |
justinbuckland | 20:ccbe2a03893d | 326 | pressure_tick.attach_us(& pressure_trigger, exp_config.fluidics.pressure_control_loop_interval_ms * 1000); |
justinbuckland | 13:b2e00297b465 | 327 | |
justinbuckland | 20:ccbe2a03893d | 328 | //Start logging |
omatthews | 2:b27d8f9a6e49 | 329 | logging_thread.start(& log_state); |
omatthews | 6:ef2bcc5fe3af | 330 | log_tick.attach_us(& log_trigger,exp_config.logging_interval_ms * 1000); |
omatthews | 0:54bedd3964e2 | 331 | |
paullj | 22:f65353f6e935 | 332 | //Start temperature control |
paullj | 22:f65353f6e935 | 333 | pc.printf("# Waiting for signal to begin [THERMAL] control (type s or press button 0)\n"); |
paullj | 22:f65353f6e935 | 334 | while (pc.getcNb()!='s' && !user_0); |
paullj | 22:f65353f6e935 | 335 | pc.printf("# Thermal control start signal received\n"); |
paullj | 22:f65353f6e935 | 336 | |
paullj | 22:f65353f6e935 | 337 | heater->Set_ref(0.0); |
paullj | 22:f65353f6e935 | 338 | heater_control.start(& temp_control); |
paullj | 22:f65353f6e935 | 339 | heat_tick.attach_us(& temp_trigger,exp_config.thermal.thermal_control_loop_interval_ms * 1000); |
paullj | 22:f65353f6e935 | 340 | |
justinbuckland | 27:0ee855da5ba9 | 341 | pc.printf("# Starting routine on drive board: %d\n",drive_board_serial_number[i_board]); |
justinbuckland | 26:e2e834e16367 | 342 | pc.printf("heater id, time (ms), R_avg (Ohm), R_set (Ohm), R (Ohm), Err (Ohm), Err_int (Ohm.ms), Duty cycle, P1 (ADC), P2 (ADC)\n"); |
paullj | 23:d00849a9aa23 | 343 | timer.start(); |
omatthews | 5:702b32ead94e | 344 | set_point_routine(profile); |
omatthews | 6:ef2bcc5fe3af | 345 | |
omatthews | 6:ef2bcc5fe3af | 346 | //Turn off |
omatthews | 5:702b32ead94e | 347 | heat_tick.detach(); |
omatthews | 5:702b32ead94e | 348 | log_tick.detach(); |
omatthews | 5:702b32ead94e | 349 | wait(1); |
omatthews | 2:b27d8f9a6e49 | 350 | heater->turn_off(); |
justinbuckland | 18:376350fb7ef9 | 351 | |
justinbuckland | 7:a4fc853feb30 | 352 | pc.printf("# Finished\n"); |
justinbuckland | 7:a4fc853feb30 | 353 | |
omatthews | 5:702b32ead94e | 354 | return 0; |
omatthews | 5:702b32ead94e | 355 | } |