Heater for threaded program

Dependents:   LEX_Threaded_Programming

Heater.cpp

Committer:
omatthews
Date:
2019-07-23
Revision:
14:f266bf960b8d
Parent:
12:8a048f111140
Child:
15:e7838491c104

File content as of revision 14:f266bf960b8d:

/*------------------------------------------------------------------------------
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 float scale_factors[8];
extern Timer timer;
extern DigitalIn adc_busy;
extern MODSERIAL pc;  
extern int log_count;
extern float R_avg;


    
Heater::Heater(int i_port, int v_port, PwmOut drive, float corr_grad, 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) {}

float Heater::R_to_T(float R) {return R*corr_grad + corr_int;}
float Heater::T_to_R(float T) {return (T - corr_int)/corr_grad;}

void Heater::output()
{
    pc.printf("%d,%f,%f,%f,%f\n",timer.read_ms(),R_ref,R,R_avg,drive.read());
}

void Heater::read()
{
    //Reads R and then resets the drive back to its previous value
    int i = 0;

    float drive_prev = drive.read();     //Store previous value of drive
    drive = 1;
    wait_us(MEAS_DELAY);        //Wait for ADC to settle
    adc.start_conversion(ALL_CH);
    while(adc_busy == 1)
        {
            wait_us(1);
            i++;
        }
    drive.write(drive_prev);
    adc.read_channels();

            
    //pc.printf("conversion took %d us\n", i );
    //i=0;
    
    curr = adc.read_channel_result(i_port);
    v = adc.read_channel_result(v_port);
    if (v<0) {pc.printf("v is %d",v);}
    //if (curr > 0) {R = (float)v/curr;}        //Avoid dividing by 0
    R = (float)v/curr;
    R_avg = (((N_ROLL_AVG - 1) * R_avg) + R)/N_ROLL_AVG;

    error = R_ref - R_avg;
    
    //Avoid integral windup by limiting error past actuation saturation (actuator does saturate for any negative error, but  to ensure integrated error can decrease, the limit has been set to the negative of the positive limit
    if (error*Kd > 1) {error = 1/Kd;}
    else if (error*Kd < -1) {error = -1/Kd;}
    
    
    error_integrated += error;
    
    log_count++;
    if (log_count > 50)
    {
    log_count = 0;
    output();
    }
}




void Heater::hold(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(Kd * error + Ki * error_integrated);
        wait_ms(WAIT_DELAY);  //Minimum duty cycle of 1%
        //pc.printf("%f,%f,%f\n",error,error_integrated,drive.read());
   
  
    }
}


void Heater::ramp_R(int ramp_time, float R_final, float R_start)
{
    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(int ramp_time, float T_final, float T_start) 
{
    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);}

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

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

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

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