Heater for threaded program

Dependents:   LEX_Threaded_Programming

Heater.cpp

Committer:
omatthews
Date:
2019-07-25
Revision:
17:0bfed0e96927
Parent:
16:cd837b230b09
Child:
18:f5d26d3d532f

File content as of revision 17:0bfed0e96927:

/*------------------------------------------------------------------------------
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, FastPWM * 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,%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);         //Time_on seems to have a precision of us. Larger period => more precise control
    *drive = 1.0f;
    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);
    drive->period_us(PWM_PERIOD);         //Time_on seems to have a precision of us. Larger period => more precise control

    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_avg = (((N_ROLL_AVG - 1) * R_avg) + R)/N_ROLL_AVG;

    error = R_ref - R;
    error_diff = (error - error_prev)/WAIT_DELAY;
    
    //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*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;}
    
    
    
    log_count++;
    if (log_count > 100)
    {
    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((double) (Kp * (error + error_integrated/Ti)));
        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);}

void Heater::Set_D(float D) {drive->write(D);}

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;}