LEX_Threaded_Programming

Dependencies:   Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC

Committer:
justinbuckland
Date:
Thu Sep 05 08:29:32 2019 +0000
Revision:
8:58c6d51957df
Parent:
7:a4fc853feb30
Child:
9:9474da78cec3
Camera trigger output added and LED output added

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