LEX_Threaded_Programming

Dependencies:   Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC

Committer:
justinbuckland
Date:
Tue Sep 17 15:55:26 2019 +0000
Revision:
10:f8202e71e765
Parent:
9:9474da78cec3
Child:
11:7394f281e845
Added pump drive;

Who changed what in which revision?

UserRevisionLine numberNew 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
justinbuckland 8:58c6d51957df 13 #define BUFFER_SIZE 4096
justinbuckland 9:9474da78cec3 14 #define LED_PULSE_PERIOD 8400 // ticks, 10kHz when CPU clock is 84MHz
justinbuckland 9:9474da78cec3 15 #define LED_PULSE_WIDTH 4200 // ticks, 50% duty cycle
justinbuckland 8:58c6d51957df 16
omatthews 0:54bedd3964e2 17 Heater * heater;
intrinseca 4:63d7f2a0dec6 18 float r_gradient; //setpoint setting
omatthews 5:702b32ead94e 19
omatthews 0:54bedd3964e2 20
justinbuckland 8:58c6d51957df 21 MODSERIAL pc(PA_9, PA_10, BUFFER_SIZE); //mcu TX, RX, BUFFER_SIZE byte TX and RX buffers
omatthews 0:54bedd3964e2 22 ADS8568_ADC adc(PB_15, PB_14, PB_13, PB_12, PC_15, PC_0, PC_1, PC_2, PC_3);
omatthews 0:54bedd3964e2 23 I2C i2c(PB_7, PB_8); //SDA, SCL
omatthews 0:54bedd3964e2 24 Timer timer;
omatthews 0:54bedd3964e2 25 DigitalIn adc_busy(PA_8); //Busy interrupt sig#
omatthews 5:702b32ead94e 26
justinbuckland 10:f8202e71e765 27 //Pressure Control
justinbuckland 10:f8202e71e765 28 DigitalOut pump(PA_0);
justinbuckland 10:f8202e71e765 29 float pres_in = 0.0;
justinbuckland 10:f8202e71e765 30 float pres_out = 0.0;
justinbuckland 10:f8202e71e765 31
justinbuckland 10:f8202e71e765 32 //int pressure_setpoint = 2540;
justinbuckland 10:f8202e71e765 33 //int pressure_hysteresis = 48;
justinbuckland 10:f8202e71e765 34 //int pressure_setpoint_low = pressure_setpoint - pressure_hysteresis/2;
justinbuckland 10:f8202e71e765 35 //int pressure_setpoint_high = pressure_setpoint + pressure_hysteresis/2;
omatthews 0:54bedd3964e2 36
omatthews 0:54bedd3964e2 37 //Heater Control
omatthews 5:702b32ead94e 38 FastPWM drive_main(PC_9);
omatthews 5:702b32ead94e 39 FastPWM drive_lysis(PC_8);
omatthews 5:702b32ead94e 40 FastPWM guard_main(PC_7);
omatthews 5:702b32ead94e 41 FastPWM guard_lysis(PC_6);
justinbuckland 7:a4fc853feb30 42
justinbuckland 7:a4fc853feb30 43 int heater_ID_main = 1;
justinbuckland 7:a4fc853feb30 44 int heater_ID_lysis = 2;
omatthews 5:702b32ead94e 45 int i_port_main = 0;
omatthews 5:702b32ead94e 46 int i_port_lysis = 2;
omatthews 5:702b32ead94e 47 int v_port_main = 1;
omatthews 5:702b32ead94e 48 int v_port_lysis = 3;
omatthews 0:54bedd3964e2 49
justinbuckland 7:a4fc853feb30 50 int heater_ID = 0;
omatthews 0:54bedd3964e2 51
justinbuckland 9:9474da78cec3 52 //Illumination LED Control
justinbuckland 9:9474da78cec3 53
omatthews 0:54bedd3964e2 54
justinbuckland 7:a4fc853feb30 55 //Indicator LEDs
omatthews 0:54bedd3964e2 56 DigitalOut hb_led(PC_13); //Green
omatthews 0:54bedd3964e2 57 DigitalOut led_0(PC_4); //Red
omatthews 0:54bedd3964e2 58 DigitalOut led_1(PC_5); //Green
omatthews 0:54bedd3964e2 59
justinbuckland 7:a4fc853feb30 60 //Camera and LED drive
justinbuckland 7:a4fc853feb30 61 DigitalOut camTrigger(PB_2); //Trigger camera
justinbuckland 9:9474da78cec3 62 FastPWM ledDrive(PB_4); //PWM drive LED for fluorescence detection
justinbuckland 7:a4fc853feb30 63
omatthews 0:54bedd3964e2 64 //User buttons
omatthews 0:54bedd3964e2 65 DigitalIn user_0(PB_0);
omatthews 0:54bedd3964e2 66 DigitalIn user_1(PB_1);
omatthews 0:54bedd3964e2 67
omatthews 0:54bedd3964e2 68 BusOut converts(PC_0, PC_1, PC_2, PC_3);
omatthews 0:54bedd3964e2 69
omatthews 0:54bedd3964e2 70 //Threads
omatthews 6:ef2bcc5fe3af 71 Thread heater_control(osPriorityHigh);
omatthews 6:ef2bcc5fe3af 72 Thread logging_thread(osPriorityAboveNormal);
omatthews 0:54bedd3964e2 73
omatthews 0:54bedd3964e2 74 //Tickers
omatthews 0:54bedd3964e2 75 Ticker heat_tick;
omatthews 0:54bedd3964e2 76 Ticker pressure_tick;
omatthews 0:54bedd3964e2 77 Ticker log_tick;
omatthews 0:54bedd3964e2 78
omatthews 0:54bedd3964e2 79
omatthews 0:54bedd3964e2 80 //Flags
omatthews 5:702b32ead94e 81 EventFlags flags; //Flags:
omatthews 5:702b32ead94e 82 // 0 => update heater
omatthews 5:702b32ead94e 83 // 1 => log state
omatthews 5:702b32ead94e 84 bool triggered_flag;
omatthews 0:54bedd3964e2 85 bool status = true;
omatthews 0:54bedd3964e2 86
omatthews 0:54bedd3964e2 87 //Configuration data
omatthews 0:54bedd3964e2 88 memspcr_ExperimentConfiguration exp_config = memspcr_ExperimentConfiguration_init_zero;
omatthews 0:54bedd3964e2 89 int buffer_length;
omatthews 0:54bedd3964e2 90 size_t message_length;
justinbuckland 8:58c6d51957df 91 uint8_t buffer[BUFFER_SIZE];
omatthews 0:54bedd3964e2 92
omatthews 0:54bedd3964e2 93
omatthews 0:54bedd3964e2 94 //Functions for reading and decoding the message__________________________________________________
omatthews 0:54bedd3964e2 95
omatthews 0:54bedd3964e2 96 void read_message()
omatthews 0:54bedd3964e2 97 {
justinbuckland 7:a4fc853feb30 98 if (pc.scanf("%d",&message_length) < 0){pc.printf("# Error reading message length");}
omatthews 5:702b32ead94e 99 size_t buffer_length = sizeof(buffer);
omatthews 5:702b32ead94e 100 if (message_length > buffer_length)
omatthews 5:702b32ead94e 101 {
justinbuckland 7:a4fc853feb30 102 pc.printf("# Message length exceeds buffer. \n Input configuration file\n");
omatthews 5:702b32ead94e 103 read_message();
omatthews 5:702b32ead94e 104 return;
omatthews 5:702b32ead94e 105 }
justinbuckland 7:a4fc853feb30 106 pc.printf("# Message is %d chars long, buffer length is %d\n",message_length,buffer_length);
omatthews 5:702b32ead94e 107 unsigned int c;
omatthews 5:702b32ead94e 108 for (int i = 0; i < message_length; i++)
omatthews 0:54bedd3964e2 109 {
omatthews 0:54bedd3964e2 110 pc.scanf("%02X",&c);
omatthews 0:54bedd3964e2 111 buffer[i] = (char) c;
omatthews 0:54bedd3964e2 112 }
omatthews 0:54bedd3964e2 113 }
omatthews 0:54bedd3964e2 114
omatthews 0:54bedd3964e2 115 void decode_message()
omatthews 0:54bedd3964e2 116 {
omatthews 5:702b32ead94e 117 // Create a stream that reads from the buffer.
omatthews 5:702b32ead94e 118
omatthews 0:54bedd3964e2 119 pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
omatthews 0:54bedd3964e2 120
omatthews 5:702b32ead94e 121 //Now we are ready to decode the message.
omatthews 0:54bedd3964e2 122 status = pb_decode(&istream, memspcr_ExperimentConfiguration_fields, &exp_config);
omatthews 0:54bedd3964e2 123
omatthews 5:702b32ead94e 124 // Check for errors...
omatthews 5:702b32ead94e 125 if (!status) {
justinbuckland 7:a4fc853feb30 126 pc.printf("# Decoding failed: %s\n", PB_GET_ERROR(&istream));
omatthews 0:54bedd3964e2 127 }
omatthews 0:54bedd3964e2 128 }
omatthews 0:54bedd3964e2 129
omatthews 0:54bedd3964e2 130 bool decode_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
omatthews 0:54bedd3964e2 131 {
omatthews 0:54bedd3964e2 132 vector <memspcr_ThermalStep> * dest = (vector <memspcr_ThermalStep> *)(*arg);
omatthews 0:54bedd3964e2 133 memspcr_ThermalStep result = memspcr_ThermalStep_init_zero;
omatthews 0:54bedd3964e2 134 status = pb_decode(stream, memspcr_ThermalStep_fields, & result);
omatthews 5:702b32ead94e 135
omatthews 5:702b32ead94e 136 if (!status) {
justinbuckland 7:a4fc853feb30 137 pc.printf("# Decode callback failed\n");
omatthews 0:54bedd3964e2 138 }
omatthews 0:54bedd3964e2 139
intrinseca 4:63d7f2a0dec6 140 dest->push_back(result); //CHECK: Does result get copied into the vector?
omatthews 0:54bedd3964e2 141 return true;
omatthews 0:54bedd3964e2 142 }
omatthews 0:54bedd3964e2 143
omatthews 0:54bedd3964e2 144
omatthews 0:54bedd3964e2 145 //Ticking functions_________________________________________________________________
omatthews 0:54bedd3964e2 146
omatthews 6:ef2bcc5fe3af 147
omatthews 5:702b32ead94e 148 void temp_trigger()
omatthews 0:54bedd3964e2 149 {
omatthews 5:702b32ead94e 150 //This function triggers a temperature update.
omatthews 5:702b32ead94e 151 //N.B. update cannot be called directly from a ticker as tickers and
omatthews 0:54bedd3964e2 152 //reading the ADC both rely on interrupts.
omatthews 5:702b32ead94e 153 flags.set(0x1);
omatthews 0:54bedd3964e2 154 }
omatthews 0:54bedd3964e2 155
omatthews 6:ef2bcc5fe3af 156
omatthews 2:b27d8f9a6e49 157 void log_trigger()
omatthews 2:b27d8f9a6e49 158 {
omatthews 5:702b32ead94e 159 flags.set(0x2);
omatthews 2:b27d8f9a6e49 160 }
justinbuckland 7:a4fc853feb30 161
omatthews 5:702b32ead94e 162 void pressure_control()
omatthews 0:54bedd3964e2 163 {
justinbuckland 10:f8202e71e765 164 // if (pressure < pressure_setpoint_low) {
justinbuckland 10:f8202e71e765 165 // pump = 1;
justinbuckland 10:f8202e71e765 166 // valve_pres = 1;
justinbuckland 10:f8202e71e765 167 // }
justinbuckland 10:f8202e71e765 168 // else if (pressure > pressure_setpoint_high) {
justinbuckland 10:f8202e71e765 169 // pump = 0;
justinbuckland 10:f8202e71e765 170 // valve_pres = 0;
justinbuckland 10:f8202e71e765 171 // }
omatthews 0:54bedd3964e2 172 led_1 = !led_1;
justinbuckland 10:f8202e71e765 173 pump = !pump;
omatthews 0:54bedd3964e2 174
justinbuckland 10:f8202e71e765 175 }
omatthews 0:54bedd3964e2 176
omatthews 0:54bedd3964e2 177
omatthews 5:702b32ead94e 178 //Other functions__________________________________________________________________
omatthews 0:54bedd3964e2 179
omatthews 0:54bedd3964e2 180
omatthews 0:54bedd3964e2 181 void temp_control() {
omatthews 0:54bedd3964e2 182 while(1){
omatthews 6:ef2bcc5fe3af 183 flags.wait_any(0x1,osWaitForever,true);
omatthews 0:54bedd3964e2 184 heater->read();
omatthews 0:54bedd3964e2 185 heater->update();
omatthews 0:54bedd3964e2 186 }
omatthews 0:54bedd3964e2 187 }
omatthews 5:702b32ead94e 188
omatthews 2:b27d8f9a6e49 189 void log_state()
omatthews 2:b27d8f9a6e49 190 {
omatthews 2:b27d8f9a6e49 191 while(1){
omatthews 6:ef2bcc5fe3af 192 flags.wait_any(0x2,osWaitForever,true);
omatthews 6:ef2bcc5fe3af 193 //Output time, R_ref, R, error, error_integrated
justinbuckland 10:f8202e71e765 194 pc.printf("%10d,%10d,%10.6f,%10.6f,%10.6f,%10.6f\n", heater_ID, timer.read_ms(), heater->Get_R(), heater->Get_R_ref(), pres_in, pres_out);
omatthews 2:b27d8f9a6e49 195 }
omatthews 2:b27d8f9a6e49 196 }
omatthews 5:702b32ead94e 197
omatthews 5:702b32ead94e 198 void set_point_routine(std::vector<memspcr_ThermalStep> profile) {
omatthews 5:702b32ead94e 199 int curr_time;
omatthews 5:702b32ead94e 200 vector <memspcr_ThermalStep>::iterator it_prev, it = profile.begin();
omatthews 5:702b32ead94e 201 if (it->elapsed_time_ms != 0)
omatthews 5:702b32ead94e 202 {
justinbuckland 7:a4fc853feb30 203 pc.printf("# Error: the first point in the profile should be at time 0.\n");
omatthews 5:702b32ead94e 204 return;
omatthews 5:702b32ead94e 205 }
omatthews 2:b27d8f9a6e49 206 it++;
omatthews 0:54bedd3964e2 207
omatthews 0:54bedd3964e2 208 for (it_prev = profile.begin(); it < profile.end(); it ++, it_prev++){
omatthews 0:54bedd3964e2 209 triggered_flag = false;
omatthews 0:54bedd3964e2 210 r_gradient = (it->resistance - it_prev->resistance)/(it->elapsed_time_ms - it_prev->elapsed_time_ms);
omatthews 0:54bedd3964e2 211 while ((curr_time = timer.read_ms()) <= it->elapsed_time_ms){
omatthews 5:702b32ead94e 212 heater->Set_ref(it_prev->resistance + r_gradient * (curr_time - it_prev->elapsed_time_ms));
justinbuckland 8:58c6d51957df 213
justinbuckland 9:9474da78cec3 214 if (!triggered_flag && (it->camera_offset_ms != 0) && (curr_time > it_prev->elapsed_time_ms + it->camera_offset_ms))
omatthews 0:54bedd3964e2 215 {
justinbuckland 9:9474da78cec3 216 //Start camera exposure and turn on LED if camera_offset_ms is non-zero
justinbuckland 7:a4fc853feb30 217 camTrigger = 0;
justinbuckland 7:a4fc853feb30 218 wait_us(10);
justinbuckland 7:a4fc853feb30 219 camTrigger = 1;
justinbuckland 7:a4fc853feb30 220 led_0 = 1;
justinbuckland 10:f8202e71e765 221 // ledDrive.pulsewidth_ticks(LED_PULSE_WIDTH);
omatthews 0:54bedd3964e2 222 triggered_flag = true;
omatthews 0:54bedd3964e2 223 }
justinbuckland 8:58c6d51957df 224 wait_us(200);
omatthews 0:54bedd3964e2 225 }
justinbuckland 8:58c6d51957df 226 //Stop camera exposure and turn off LED at end of time segment
justinbuckland 8:58c6d51957df 227 camTrigger = 0;
justinbuckland 10:f8202e71e765 228 // ledDrive.pulsewidth_ticks(0);
justinbuckland 8:58c6d51957df 229 led_0 = 0;
omatthews 0:54bedd3964e2 230 }
omatthews 0:54bedd3964e2 231 }
omatthews 0:54bedd3964e2 232
omatthews 0:54bedd3964e2 233
omatthews 5:702b32ead94e 234 int main()
omatthews 5:702b32ead94e 235 {
omatthews 0:54bedd3964e2 236 pc.baud(115200);
omatthews 0:54bedd3964e2 237 adc.init();
omatthews 5:702b32ead94e 238
omatthews 0:54bedd3964e2 239 buffer_length = sizeof(buffer)/sizeof(uint8_t);
justinbuckland 7:a4fc853feb30 240 pc.printf("# Input configuration file\n");
omatthews 5:702b32ead94e 241
justinbuckland 9:9474da78cec3 242 //set up LED PWM drive
justinbuckland 9:9474da78cec3 243 ledDrive.prescaler(1);
justinbuckland 9:9474da78cec3 244 ledDrive.period_ticks(LED_PULSE_PERIOD);
justinbuckland 9:9474da78cec3 245 ledDrive.pulsewidth_ticks(0);
justinbuckland 9:9474da78cec3 246
intrinseca 4:63d7f2a0dec6 247 //set up nanopb
omatthews 5:702b32ead94e 248 std::vector<memspcr_ThermalStep> profile;
omatthews 5:702b32ead94e 249 exp_config.profile.funcs.decode = decode_callback;
omatthews 5:702b32ead94e 250 exp_config.profile.arg = &profile;
omatthews 5:702b32ead94e 251
intrinseca 4:63d7f2a0dec6 252 //read and decode configuration
intrinseca 4:63d7f2a0dec6 253 read_message();
justinbuckland 7:a4fc853feb30 254 pc.printf("# Message read\n");
omatthews 0:54bedd3964e2 255 decode_message();
justinbuckland 7:a4fc853feb30 256 pc.printf("# Message decoded\n");
omatthews 5:702b32ead94e 257
omatthews 6:ef2bcc5fe3af 258 Heater * heater_main = new Heater(i_port_main, v_port_main, & drive_main, & guard_main, & adc, adc_busy, exp_config.thermal);
omatthews 6:ef2bcc5fe3af 259 Heater * heater_lysis = new Heater(i_port_lysis, v_port_lysis, & drive_lysis, & guard_lysis, & adc, adc_busy, exp_config.thermal);
omatthews 5:702b32ead94e 260
omatthews 5:702b32ead94e 261 //Select heater. Put control times in us for ticker functions
omatthews 5:702b32ead94e 262 if (exp_config.selected_heater == memspcr_ExperimentConfiguration_Heater_MAIN) {
omatthews 5:702b32ead94e 263 heater = heater_main;
justinbuckland 7:a4fc853feb30 264 heater_ID = heater_ID_main;
omatthews 5:702b32ead94e 265 } else if (exp_config.selected_heater == memspcr_ExperimentConfiguration_Heater_LYSIS) {
omatthews 5:702b32ead94e 266 heater = heater_lysis;
justinbuckland 7:a4fc853feb30 267 heater_ID = heater_ID_lysis;
omatthews 5:702b32ead94e 268 } else {
justinbuckland 8:58c6d51957df 269 pc.printf("# Error - no heater has been selected\n");
omatthews 5:702b32ead94e 270 return 1;
omatthews 5:702b32ead94e 271 }
omatthews 5:702b32ead94e 272
justinbuckland 7:a4fc853feb30 273 pc.printf("# Starting pressure control\n");
omatthews 0:54bedd3964e2 274 pressure_tick.attach(& pressure_control, 1);
justinbuckland 7:a4fc853feb30 275 pc.printf("# Waiting for start signal to begin temperature control (type in an s or press button 0)\n");
omatthews 6:ef2bcc5fe3af 276 heater->Set_ref(0.0);
omatthews 6:ef2bcc5fe3af 277 heater_control.start(& temp_control);
omatthews 6:ef2bcc5fe3af 278 heat_tick.attach_us(& temp_trigger,exp_config.thermal.control_loop_interval_ms * 1000);
omatthews 6:ef2bcc5fe3af 279
omatthews 2:b27d8f9a6e49 280 while (pc.getcNb()!='s' && !user_0);
omatthews 5:702b32ead94e 281
justinbuckland 8:58c6d51957df 282 pc.printf("# Start signal received\n");
omatthews 0:54bedd3964e2 283
omatthews 2:b27d8f9a6e49 284 logging_thread.start(& log_state);
omatthews 6:ef2bcc5fe3af 285 log_tick.attach_us(& log_trigger,exp_config.logging_interval_ms * 1000);
omatthews 0:54bedd3964e2 286
justinbuckland 10:f8202e71e765 287 pc.printf("# Starting routine...\n");
justinbuckland 10:f8202e71e765 288 pc.printf("# heater, time(ms), r, rSet, pres_in, pres_out\n");
omatthews 2:b27d8f9a6e49 289 timer.start();
omatthews 5:702b32ead94e 290 set_point_routine(profile);
omatthews 6:ef2bcc5fe3af 291
omatthews 6:ef2bcc5fe3af 292 //Turn off
omatthews 5:702b32ead94e 293 heat_tick.detach();
omatthews 5:702b32ead94e 294 log_tick.detach();
omatthews 5:702b32ead94e 295 wait(1);
omatthews 2:b27d8f9a6e49 296 heater->turn_off();
justinbuckland 8:58c6d51957df 297
justinbuckland 8:58c6d51957df 298
justinbuckland 7:a4fc853feb30 299 pc.printf("# Finished\n");
justinbuckland 7:a4fc853feb30 300
omatthews 5:702b32ead94e 301 return 0;
omatthews 5:702b32ead94e 302 }