Heater for threaded program

Dependents:   LEX_Threaded_Programming

Heater.cpp

Committer:
omatthews
Date:
2019-07-28
Revision:
18:f5d26d3d532f
Parent:
17:0bfed0e96927
Child:
19:fccdd7127f94

File content as of revision 18:f5d26d3d532f:

/*------------------------------------------------------------------------------
Library code file for interface to Heater
Date: 16/07/2018


------------------------------------------------------------------------------*/
#include "mbed.h"
#include "MODSERIAL.h"
#include "Heater.h"
#include "ADS8568_ADC.h"

extern ADS8568_ADC adc;
extern Timer timer;
extern DigitalIn adc_busy;
extern MODSERIAL pc;  
extern int log_count;
extern float R_avg;


    
Heater::Heater(const int i_port, const int v_port, FastPWM * drive, const float corr_grad, const float corr_int, float R_ref)
    :R_ref(R_ref),i_port(i_port),v_port(v_port),drive(drive),corr_grad(corr_grad),corr_int(corr_int) {}


// Convert from R to T using the linear relationship - T = R * corr_grad + corr_int
float Heater::R_to_T(const float R) const {return R*corr_grad + corr_int;}
float Heater::T_to_R(const float T) const {return (T - corr_int)/corr_grad;}

void Heater::output()const
{
    //Prints the current state to the terminal
    pc.printf("%d,%f,%f,%f,%f,%f\n",timer.read_ms(),R_ref,R,error,error_integrated,drive->read());
}

void Heater::read()
{
    //Reads R and then resets the drive back to its previous value
    
    int i = 0;
    //float error_prev = error;
    
    double drive_prev = drive->read();     //Store previous value of drive
    drive->period_us(1);         //Set period to 1us for the measurement
    *drive = 1.0f;              //Turn the driver on for the measurement
    wait_us(MEAS_DELAY);        //Wait for ADC to settle
    adc.start_conversion(ALL_CH);
    //Incremental back off until ADC is free
    while(adc_busy == 1)
        {
            wait_us(1);
            i++;
        }        
    drive->write(drive_prev);       //Reset the duty cycle back to what it was
    drive->period_us(PWM_PERIOD);         //Reset the period to what it was


    //Get voltage, current and R values from the ADC conversion
    adc.read_channels();
    curr = adc.read_channel_result(i_port);
    v = adc.read_channel_result(v_port);
    
    if (curr > 0) {R = (float)v/curr;}        //Avoid dividing by 0

    //Get error values
    
    error = R_ref - R;
    //error_diff = (error - error_prev)/WAIT_DELAY;
    
    //Avoid integral windup by limiting integral error past actuation saturation 
    if (error*Kp > WIND_UP_LIMIT) {error_integrated += WIND_UP_LIMIT/Kp;}
    else if (error*Kp < -WIND_UP_LIMIT) {error_integrated -= WIND_UP_LIMIT/Kp;}
    else {error_integrated += error;}
    
    
    //Output the error every LOG_LIM reads
    log_count++;
    if (log_count >= LOG_LIM)
    {
    log_count = 0;
    output();
    }
}




void Heater::hold(const int hold_time)
{
    //Holds the heater at R_ref for the given hold time
    //  in: int hold_time - is the time in ms to hold the reference
    
    int end_time = timer.read_ms() + hold_time;
    while (timer.read_ms() < end_time)
    {
        read();
        drive->write((double) (Kp * (error + error_integrated/Ti)));
        wait_ms(WAIT_DELAY);    //Wait before reading again  
    }
}


void Heater::ramp_R(const int ramp_time, const float R_final, const float R_start)
{
    //Ramps the heater from R_start to R_final for the given hold time
    //  in: int hold_time - is the time in ms to hold the reference
    //      float R_final - is the final R_ref value
    //      float R_start - is the initial R_ref value

    int time = timer.read_ms();
    int start_time = time;
    int end_time = start_time + ramp_time;
    float ramp_rate = (R_final - R_start)/ramp_time;
    
    while (time < end_time)
    {
        Set_R_ref(R_start + ramp_rate * (time - start_time));
        hold(1);
        time = timer.read_ms();
    }
    
}
    
void Heater::ramp_T(const int ramp_time, const float T_final, const float T_start) 
{
    //Ramps the heater from T_start to T_final for the given hold time
    //  in: int hold_time - is the time in ms to hold the reference
    //      float T_final - is the final T_ref value
    //      float T_start - is the initial T_ref value
    ramp_R(ramp_time, T_to_R(T_final), T_to_R(T_start));
}



void Heater::Set_R_ref(float R) {R_ref = R;}
void Heater::Set_T_ref(float T_ref) {R_ref = T_to_R(T_ref);}
void Heater::Set_D(float D) {drive->write(D);}

int Heater::Get_i() const {return curr;}
int Heater::Get_v() const {return v;}

float Heater::Get_R() const {return R;}
float Heater::Get_T() const {return R_to_T(R);}

void Heater::turn_on () {*drive = 1;}

void Heater::turn_off () {*drive = 0;}