LEX_Threaded_Programming

Dependencies:   Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC

Committer:
paullj
Date:
Thu Sep 19 16:14:45 2019 +0000
Revision:
15:6d22fa5a66ab
Parent:
14:39a5eb99fbdb
Child:
16:32b598af6f86
Removed unnecessary printf

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