LEX_Threaded_Programming

Dependencies:   Heater_V2 MODSERIAL Nanopb FastPWM ADS8568_ADC

main.cpp

Committer:
omatthews
Date:
2019-08-27
Revision:
2:b27d8f9a6e49
Parent:
0:54bedd3964e2
Child:
4:63d7f2a0dec6

File content as of revision 2:b27d8f9a6e49:

#include "mbed.h"
#include "pb.h"
#include "pb_decode.h"
#include "pb_encode.h"
#include "MODSERIAL.h"
#include "ADS8568_ADC.h"
#include "Heater.h"
#include "FastPWM.h"
#include "memspcr.pb.h"
#include <vector>
#include <iterator>


#define ALL_CH              15     //value of convst bus to read all chanels simultaneosly
Heater * heater;
float r_gradient;
int curr_time;

MODSERIAL pc(PA_9, PA_10, 512); //mcu TX, RX, 512 byte TX and RX buffers
ADS8568_ADC adc(PB_15, PB_14, PB_13, PB_12, PC_15, PC_0, PC_1, PC_2, PC_3);
I2C i2c(PB_7, PB_8);            //SDA, SCL
Timer timer;
DigitalIn adc_busy(PA_8);                   //Busy interrupt sig#
int i;

//Heater Control
FastPWM drive_1(PC_9);
FastPWM drive_2(PC_8);
FastPWM guard_1(PC_7);
FastPWM guard_2(PC_6);



//indicator LEDs
DigitalOut hb_led(PC_13);       //Green
DigitalOut led_0(PC_4);         //Red
DigitalOut led_1(PC_5);         //Green

//User buttons
DigitalIn user_0(PB_0);
DigitalIn user_1(PB_1);

BusOut converts(PC_0, PC_1, PC_2, PC_3);


//Threads
Thread heater_control;
Thread logging_thread;

//Tickers
Ticker heat_tick;
Ticker pressure_tick;
Ticker log_tick;


//Flags
bool start_flag = false;
bool config_flag = false;
volatile bool heater_flag = false;
volatile bool log_flag = false;
bool triggered_flag = false;
bool untriggered_flag = false;
bool status = true;

//Configuration data
memspcr_ExperimentConfiguration exp_config = memspcr_ExperimentConfiguration_init_zero;
int buffer_length;
std::vector<memspcr_ThermalStep> profile;
unsigned int c = 0;
size_t message_length;
uint8_t buffer[256];




//Functions for reading and decoding the message__________________________________________________

void read_message()
{
    if (pc.scanf("%d",&message_length) < 0){pc.printf("Error reading message length");}
    pc.printf("Message is %d chars long, buffer length is %d\n",message_length,buffer_length);
    for (i = 0; i < message_length; i++) 
    {
        i = i % buffer_length;
        pc.scanf("%02X",&c);
        buffer[i] = (char) c;
    }   
}         

void decode_message()
{
    // Create a stream that reads from the buffer. 
    
    pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);

    //Now we are ready to decode the message. 
    status = pb_decode(&istream, memspcr_ExperimentConfiguration_fields, &exp_config);

    // Check for errors... 
    if (!status)
    {
        pc.printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
    }
}

bool decode_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
    vector <memspcr_ThermalStep> * dest = (vector <memspcr_ThermalStep> *)(*arg);
    memspcr_ThermalStep result = memspcr_ThermalStep_init_zero;
    status = pb_decode(stream, memspcr_ThermalStep_fields, & result);
    
    if (!status)
    {
        pc.printf("Decode callback failed\n");
    }

    dest->push_back(result);
    return true;
}


//Ticking functions_________________________________________________________________

void temp_trigger() 
{
    //This function triggers a temperature update. 
    //N.B. update cannot be called directly from a ticker as tickers and 
    //reading the ADC both rely on interrupts.
    heater_flag = true;
}

void log_trigger()
{
    log_flag = true;
}
void pressure_control() 
{
    //Input pressure control function here
    //i.e.
    //read_pressure();
    //if (pressure < lower_bound) {
            //pump_turn_on();
        //}
    //else if (pressure > upper_bound) {
            //pump_turn_off();
        //}
    led_1 = !led_1;
}




//Other functions__________________________________________________________________    


void temp_control() {
    while(1){
        while(!heater_flag);
        heater->read();
        heater->update();
        heater_flag = false;
        } 
    }
    
void log_state()
{
    while(1){
        while(!log_flag);
        heater->log();
        log_flag = false;
    }
}
    
void set_point_routine() {
    memspcr_ThermalStep step;
    step.resistance = 0.0;
    step.elapsed_time_ms = 0;
    step.camera_offset_ms = 0;
    vector <memspcr_ThermalStep>::iterator it = profile.begin();
    vector <memspcr_ThermalStep>::iterator it_prev;
    profile.insert(it,step);
    it++;

    for (it_prev = profile.begin(); it < profile.end(); it ++, it_prev++){
        triggered_flag = false;
        untriggered_flag = false;
        r_gradient = (it->resistance - it_prev->resistance)/(it->elapsed_time_ms - it_prev->elapsed_time_ms);
        while ((curr_time = timer.read_ms()) <= it->elapsed_time_ms){
            heater->Set_ref(it_prev->resistance + r_gradient * (curr_time - it_prev->elapsed_time_ms));
            
            if (!untriggered_flag && triggered_flag)
            {
                //Untrigger on the next cycle
                //trigger_out = 0;
                untriggered_flag = true;
            }
            
            if (!triggered_flag && curr_time > it_prev->elapsed_time_ms + it->camera_offset_ms)
            {
                //Start camera trigger
                //trigger_out = 1;
                triggered_flag = true;
            }

            wait_ms(1);
        }
        
    }
}   


            

        
        
int main() {
    pc.baud(115200);
    adc.init();
    
    buffer_length = sizeof(buffer)/sizeof(uint8_t);
    pc.printf("Input configuration file\n");
        
    read_message();
    
    pc.printf("\nMessage read\n");  
    
    exp_config.thermal.profile.arg = &profile;
    exp_config.thermal.profile.funcs.decode = decode_callback;


    decode_message();
    printf("\nMessage decoded\n");
    Heater heater_(exp_config.thermal);
    heater = &heater_;
    
    pc.printf("\nStarting pressure control\n");
    pressure_tick.attach(& pressure_control, 1);
    pc.printf("\nWaiting for start signal to begin temperature control (type in an s or press button 0)\n");

    while (pc.getcNb()!='s' && !user_0);
    
    pc.printf("Start signal received");
    heater_control.start(& temp_control);
    heat_tick.attach_us(& temp_trigger,exp_config.thermal.control_loop_interval * 1000);

    logging_thread.start(& log_state);
    log_tick.attach_us(& log_trigger,exp_config.logging_interval_ms * 1000);

    
    pc.printf("\nStarting routine\n");
    timer.start();
    set_point_routine();
    heater->turn_off();
    pc.printf("Finished");


    }