LEX_Threaded_Programming

Dependencies:   Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC

Committer:
intrinseca
Date:
Wed Aug 28 15:38:19 2019 +0000
Revision:
4:63d7f2a0dec6
Parent:
2:b27d8f9a6e49
Child:
5:702b32ead94e
Review comments

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
omatthews 0:54bedd3964e2 13 Heater * heater;
intrinseca 4:63d7f2a0dec6 14 float r_gradient; //setpoint setting
intrinseca 4:63d7f2a0dec6 15 int curr_time; //FIXME: make local
omatthews 0:54bedd3964e2 16
omatthews 0:54bedd3964e2 17 MODSERIAL pc(PA_9, PA_10, 512); //mcu TX, RX, 512 byte TX and RX buffers
omatthews 0:54bedd3964e2 18 ADS8568_ADC adc(PB_15, PB_14, PB_13, PB_12, PC_15, PC_0, PC_1, PC_2, PC_3);
omatthews 0:54bedd3964e2 19 I2C i2c(PB_7, PB_8); //SDA, SCL
omatthews 0:54bedd3964e2 20 Timer timer;
omatthews 0:54bedd3964e2 21 DigitalIn adc_busy(PA_8); //Busy interrupt sig#
intrinseca 4:63d7f2a0dec6 22 int i; //FIXME: separate i for every time it's used
omatthews 0:54bedd3964e2 23
omatthews 0:54bedd3964e2 24 //Heater Control
omatthews 0:54bedd3964e2 25 FastPWM drive_1(PC_9);
omatthews 0:54bedd3964e2 26 FastPWM drive_2(PC_8);
omatthews 0:54bedd3964e2 27 FastPWM guard_1(PC_7);
omatthews 0:54bedd3964e2 28 FastPWM guard_2(PC_6);
omatthews 0:54bedd3964e2 29
intrinseca 4:63d7f2a0dec6 30 Heater* main_heater;
intrinseca 4:63d7f2a0dec6 31 Heater* lysis_heater;
intrinseca 4:63d7f2a0dec6 32 Heater* heater;
omatthews 0:54bedd3964e2 33
omatthews 0:54bedd3964e2 34
omatthews 0:54bedd3964e2 35 //indicator LEDs
omatthews 0:54bedd3964e2 36 DigitalOut hb_led(PC_13); //Green
omatthews 0:54bedd3964e2 37 DigitalOut led_0(PC_4); //Red
omatthews 0:54bedd3964e2 38 DigitalOut led_1(PC_5); //Green
omatthews 0:54bedd3964e2 39
omatthews 0:54bedd3964e2 40 //User buttons
omatthews 0:54bedd3964e2 41 DigitalIn user_0(PB_0);
omatthews 0:54bedd3964e2 42 DigitalIn user_1(PB_1);
omatthews 0:54bedd3964e2 43
omatthews 0:54bedd3964e2 44 BusOut converts(PC_0, PC_1, PC_2, PC_3);
omatthews 0:54bedd3964e2 45
omatthews 0:54bedd3964e2 46
omatthews 0:54bedd3964e2 47 //Threads
omatthews 0:54bedd3964e2 48 Thread heater_control;
omatthews 2:b27d8f9a6e49 49 Thread logging_thread;
omatthews 0:54bedd3964e2 50
omatthews 0:54bedd3964e2 51 //Tickers
omatthews 0:54bedd3964e2 52 Ticker heat_tick;
omatthews 0:54bedd3964e2 53 Ticker pressure_tick;
omatthews 0:54bedd3964e2 54 Ticker log_tick;
omatthews 0:54bedd3964e2 55
omatthews 0:54bedd3964e2 56
omatthews 0:54bedd3964e2 57 //Flags
omatthews 0:54bedd3964e2 58 bool start_flag = false;
omatthews 0:54bedd3964e2 59 bool config_flag = false;
omatthews 0:54bedd3964e2 60 volatile bool heater_flag = false;
omatthews 2:b27d8f9a6e49 61 volatile bool log_flag = false;
omatthews 0:54bedd3964e2 62 bool triggered_flag = false;
omatthews 0:54bedd3964e2 63 bool untriggered_flag = false;
omatthews 0:54bedd3964e2 64 bool status = true;
omatthews 0:54bedd3964e2 65
omatthews 0:54bedd3964e2 66 //Configuration data
omatthews 0:54bedd3964e2 67 memspcr_ExperimentConfiguration exp_config = memspcr_ExperimentConfiguration_init_zero;
omatthews 0:54bedd3964e2 68 int buffer_length;
omatthews 0:54bedd3964e2 69 std::vector<memspcr_ThermalStep> profile;
intrinseca 4:63d7f2a0dec6 70 unsigned int c = 0; //FIXME: not global
omatthews 0:54bedd3964e2 71 size_t message_length;
intrinseca 4:63d7f2a0dec6 72 uint8_t buffer[256]; //FIXME: Needs to be longer
omatthews 0:54bedd3964e2 73
omatthews 0:54bedd3964e2 74
omatthews 0:54bedd3964e2 75
omatthews 0:54bedd3964e2 76
omatthews 0:54bedd3964e2 77 //Functions for reading and decoding the message__________________________________________________
omatthews 0:54bedd3964e2 78
omatthews 0:54bedd3964e2 79 void read_message()
omatthews 0:54bedd3964e2 80 {
intrinseca 4:63d7f2a0dec6 81 //FIXME: This should work with binary data
omatthews 0:54bedd3964e2 82 if (pc.scanf("%d",&message_length) < 0){pc.printf("Error reading message length");}
omatthews 0:54bedd3964e2 83 pc.printf("Message is %d chars long, buffer length is %d\n",message_length,buffer_length);
intrinseca 4:63d7f2a0dec6 84 //assert message fits in buffer
omatthews 0:54bedd3964e2 85 for (i = 0; i < message_length; i++)
omatthews 0:54bedd3964e2 86 {
omatthews 0:54bedd3964e2 87 i = i % buffer_length;
omatthews 0:54bedd3964e2 88 pc.scanf("%02X",&c);
omatthews 0:54bedd3964e2 89 buffer[i] = (char) c;
omatthews 0:54bedd3964e2 90 }
omatthews 0:54bedd3964e2 91 }
omatthews 0:54bedd3964e2 92
omatthews 0:54bedd3964e2 93 void decode_message()
omatthews 0:54bedd3964e2 94 {
omatthews 0:54bedd3964e2 95 // Create a stream that reads from the buffer.
omatthews 0:54bedd3964e2 96
omatthews 0:54bedd3964e2 97 pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
omatthews 0:54bedd3964e2 98
omatthews 0:54bedd3964e2 99 //Now we are ready to decode the message.
omatthews 0:54bedd3964e2 100 status = pb_decode(&istream, memspcr_ExperimentConfiguration_fields, &exp_config);
omatthews 0:54bedd3964e2 101
omatthews 0:54bedd3964e2 102 // Check for errors...
omatthews 0:54bedd3964e2 103 if (!status)
omatthews 0:54bedd3964e2 104 {
omatthews 0:54bedd3964e2 105 pc.printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
omatthews 0:54bedd3964e2 106 }
omatthews 0:54bedd3964e2 107 }
omatthews 0:54bedd3964e2 108
omatthews 0:54bedd3964e2 109 bool decode_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
omatthews 0:54bedd3964e2 110 {
omatthews 0:54bedd3964e2 111 vector <memspcr_ThermalStep> * dest = (vector <memspcr_ThermalStep> *)(*arg);
omatthews 0:54bedd3964e2 112 memspcr_ThermalStep result = memspcr_ThermalStep_init_zero;
omatthews 0:54bedd3964e2 113 status = pb_decode(stream, memspcr_ThermalStep_fields, & result);
omatthews 0:54bedd3964e2 114
omatthews 0:54bedd3964e2 115 if (!status)
omatthews 0:54bedd3964e2 116 {
omatthews 0:54bedd3964e2 117 pc.printf("Decode callback failed\n");
omatthews 0:54bedd3964e2 118 }
omatthews 0:54bedd3964e2 119
intrinseca 4:63d7f2a0dec6 120 dest->push_back(result); //CHECK: Does result get copied into the vector?
omatthews 0:54bedd3964e2 121 return true;
omatthews 0:54bedd3964e2 122 }
omatthews 0:54bedd3964e2 123
omatthews 0:54bedd3964e2 124
omatthews 0:54bedd3964e2 125 //Ticking functions_________________________________________________________________
omatthews 0:54bedd3964e2 126
omatthews 0:54bedd3964e2 127 void temp_trigger()
omatthews 0:54bedd3964e2 128 {
omatthews 0:54bedd3964e2 129 //This function triggers a temperature update.
omatthews 0:54bedd3964e2 130 //N.B. update cannot be called directly from a ticker as tickers and
omatthews 0:54bedd3964e2 131 //reading the ADC both rely on interrupts.
omatthews 0:54bedd3964e2 132 heater_flag = true;
omatthews 0:54bedd3964e2 133 }
omatthews 0:54bedd3964e2 134
omatthews 2:b27d8f9a6e49 135 void log_trigger()
omatthews 2:b27d8f9a6e49 136 {
omatthews 2:b27d8f9a6e49 137 log_flag = true;
omatthews 2:b27d8f9a6e49 138 }
omatthews 0:54bedd3964e2 139 void pressure_control()
omatthews 0:54bedd3964e2 140 {
omatthews 0:54bedd3964e2 141 //Input pressure control function here
omatthews 0:54bedd3964e2 142 //i.e.
omatthews 0:54bedd3964e2 143 //read_pressure();
omatthews 0:54bedd3964e2 144 //if (pressure < lower_bound) {
omatthews 0:54bedd3964e2 145 //pump_turn_on();
omatthews 0:54bedd3964e2 146 //}
omatthews 0:54bedd3964e2 147 //else if (pressure > upper_bound) {
omatthews 0:54bedd3964e2 148 //pump_turn_off();
omatthews 0:54bedd3964e2 149 //}
omatthews 0:54bedd3964e2 150 led_1 = !led_1;
omatthews 0:54bedd3964e2 151 }
omatthews 0:54bedd3964e2 152
omatthews 2:b27d8f9a6e49 153
omatthews 0:54bedd3964e2 154
omatthews 0:54bedd3964e2 155
omatthews 0:54bedd3964e2 156 //Other functions__________________________________________________________________
omatthews 0:54bedd3964e2 157
omatthews 0:54bedd3964e2 158
omatthews 0:54bedd3964e2 159 void temp_control() {
omatthews 0:54bedd3964e2 160 while(1){
omatthews 0:54bedd3964e2 161 while(!heater_flag);
omatthews 0:54bedd3964e2 162 heater->read();
omatthews 0:54bedd3964e2 163 heater->update();
omatthews 0:54bedd3964e2 164 heater_flag = false;
omatthews 0:54bedd3964e2 165 }
omatthews 0:54bedd3964e2 166 }
omatthews 2:b27d8f9a6e49 167
omatthews 2:b27d8f9a6e49 168 void log_state()
omatthews 2:b27d8f9a6e49 169 {
omatthews 2:b27d8f9a6e49 170 while(1){
omatthews 2:b27d8f9a6e49 171 while(!log_flag);
omatthews 2:b27d8f9a6e49 172 heater->log();
omatthews 2:b27d8f9a6e49 173 log_flag = false;
omatthews 2:b27d8f9a6e49 174 }
omatthews 2:b27d8f9a6e49 175 }
omatthews 0:54bedd3964e2 176
omatthews 0:54bedd3964e2 177 void set_point_routine() {
omatthews 0:54bedd3964e2 178 memspcr_ThermalStep step;
omatthews 0:54bedd3964e2 179 step.resistance = 0.0;
omatthews 0:54bedd3964e2 180 step.elapsed_time_ms = 0;
omatthews 0:54bedd3964e2 181 step.camera_offset_ms = 0;
omatthews 0:54bedd3964e2 182 vector <memspcr_ThermalStep>::iterator it = profile.begin();
omatthews 0:54bedd3964e2 183 vector <memspcr_ThermalStep>::iterator it_prev;
intrinseca 4:63d7f2a0dec6 184 profile.insert(it,step); //not needed - should be checked by PC
intrinseca 4:63d7f2a0dec6 185 //just assert that profile[0] time is 0
omatthews 2:b27d8f9a6e49 186 it++;
omatthews 0:54bedd3964e2 187
omatthews 0:54bedd3964e2 188 for (it_prev = profile.begin(); it < profile.end(); it ++, it_prev++){
omatthews 0:54bedd3964e2 189 triggered_flag = false;
omatthews 0:54bedd3964e2 190 untriggered_flag = false;
omatthews 0:54bedd3964e2 191 r_gradient = (it->resistance - it_prev->resistance)/(it->elapsed_time_ms - it_prev->elapsed_time_ms);
omatthews 0:54bedd3964e2 192 while ((curr_time = timer.read_ms()) <= it->elapsed_time_ms){
omatthews 0:54bedd3964e2 193 heater->Set_ref(it_prev->resistance + r_gradient * (curr_time - it_prev->elapsed_time_ms));
omatthews 0:54bedd3964e2 194
omatthews 0:54bedd3964e2 195 if (!untriggered_flag && triggered_flag)
omatthews 0:54bedd3964e2 196 {
omatthews 0:54bedd3964e2 197 //Untrigger on the next cycle
omatthews 0:54bedd3964e2 198 //trigger_out = 0;
omatthews 0:54bedd3964e2 199 untriggered_flag = true;
omatthews 0:54bedd3964e2 200 }
omatthews 0:54bedd3964e2 201
omatthews 0:54bedd3964e2 202 if (!triggered_flag && curr_time > it_prev->elapsed_time_ms + it->camera_offset_ms)
omatthews 0:54bedd3964e2 203 {
omatthews 0:54bedd3964e2 204 //Start camera trigger
omatthews 0:54bedd3964e2 205 //trigger_out = 1;
omatthews 0:54bedd3964e2 206 triggered_flag = true;
omatthews 0:54bedd3964e2 207 }
intrinseca 4:63d7f2a0dec6 208 else if(triggered_flag) {
intrinseca 4:63d7f2a0dec6 209 trigger_out = false;
intrinseca 4:63d7f2a0dec6 210 }
omatthews 0:54bedd3964e2 211
intrinseca 4:63d7f2a0dec6 212 wait_us(200);
omatthews 0:54bedd3964e2 213 }
omatthews 0:54bedd3964e2 214
omatthews 0:54bedd3964e2 215 }
omatthews 0:54bedd3964e2 216 }
omatthews 0:54bedd3964e2 217
omatthews 0:54bedd3964e2 218
omatthews 0:54bedd3964e2 219
omatthews 0:54bedd3964e2 220
omatthews 0:54bedd3964e2 221
omatthews 0:54bedd3964e2 222
omatthews 0:54bedd3964e2 223 int main() {
omatthews 0:54bedd3964e2 224 pc.baud(115200);
omatthews 0:54bedd3964e2 225 adc.init();
omatthews 2:b27d8f9a6e49 226
omatthews 0:54bedd3964e2 227 buffer_length = sizeof(buffer)/sizeof(uint8_t);
omatthews 0:54bedd3964e2 228 pc.printf("Input configuration file\n");
omatthews 0:54bedd3964e2 229
intrinseca 4:63d7f2a0dec6 230 //set up nanopb
omatthews 0:54bedd3964e2 231 exp_config.thermal.profile.arg = &profile;
omatthews 0:54bedd3964e2 232 exp_config.thermal.profile.funcs.decode = decode_callback;
intrinseca 4:63d7f2a0dec6 233
intrinseca 4:63d7f2a0dec6 234 //read and decode configuration
intrinseca 4:63d7f2a0dec6 235 read_message();
intrinseca 4:63d7f2a0dec6 236 pc.printf("\nMessage read\n");
omatthews 0:54bedd3964e2 237 decode_message();
omatthews 0:54bedd3964e2 238 printf("\nMessage decoded\n");
intrinseca 4:63d7f2a0dec6 239
intrinseca 4:63d7f2a0dec6 240
intrinseca 4:63d7f2a0dec6 241 //Heater heater_(exp_config.thermal);
intrinseca 4:63d7f2a0dec6 242 heater = new Heater(exp_config.thermal);
omatthews 0:54bedd3964e2 243
omatthews 0:54bedd3964e2 244 pc.printf("\nStarting pressure control\n");
omatthews 0:54bedd3964e2 245 pressure_tick.attach(& pressure_control, 1);
omatthews 2:b27d8f9a6e49 246 pc.printf("\nWaiting for start signal to begin temperature control (type in an s or press button 0)\n");
omatthews 0:54bedd3964e2 247
omatthews 2:b27d8f9a6e49 248 while (pc.getcNb()!='s' && !user_0);
omatthews 0:54bedd3964e2 249
omatthews 0:54bedd3964e2 250 pc.printf("Start signal received");
omatthews 0:54bedd3964e2 251 heater_control.start(& temp_control);
omatthews 2:b27d8f9a6e49 252 heat_tick.attach_us(& temp_trigger,exp_config.thermal.control_loop_interval * 1000);
omatthews 0:54bedd3964e2 253
omatthews 2:b27d8f9a6e49 254 logging_thread.start(& log_state);
omatthews 2:b27d8f9a6e49 255 log_tick.attach_us(& log_trigger,exp_config.logging_interval_ms * 1000);
omatthews 0:54bedd3964e2 256
omatthews 0:54bedd3964e2 257
omatthews 0:54bedd3964e2 258 pc.printf("\nStarting routine\n");
omatthews 2:b27d8f9a6e49 259 timer.start();
omatthews 0:54bedd3964e2 260 set_point_routine();
omatthews 2:b27d8f9a6e49 261 heater->turn_off();
omatthews 0:54bedd3964e2 262 pc.printf("Finished");
omatthews 0:54bedd3964e2 263
omatthews 0:54bedd3964e2 264
omatthews 0:54bedd3964e2 265 }