Heater for threaded program

Dependents:   LEX_Threaded_Programming_V3

Heater.cpp

Committer:
justinbuckland
Date:
2020-03-30
Revision:
50:ad9a1eb063b3
Parent:
49:35fd40559960

File content as of revision 50:ad9a1eb063b3:

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


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

Heater::Heater(const int i_port, const int v_port, const float cal_a, const float cal_b, FastPWM * drive, FastPWM * guard, ADS8568_ADC * adc, DigitalIn adc_busy, const memspcr_ThermalConfiguration & thermal)
    :thermal(thermal), i_port(i_port), v_port(v_port), cal_a(cal_a), cal_b(cal_b), drive(drive), guard(guard), adc(adc), adc_busy(adc_busy)
{
    //Set up PWM 
    drive->prescaler(1);
    guard->prescaler(1);
    drive->period_ticks(1000);
    guard->period_ticks(1000);
    
    //Initialise values for averaging resistance
    n_acc = 0;
    R_acc = 0;
    R_smooth = 0;
    R2_acc = 0;
}

void Heater::read()
{
    //Reads R and then resets the drive back to its previous value
    int i = 0;
    double drive_prev = drive->read();     //Store previous value of drive
        
    *drive = 1.0f;                         //Turn the driver on for the measurement
    wait_us(thermal.settling_time_us);     //Wait for ADC to settle
    adc->start_conversion(ADC_CONV_ALL_CH);     
    
    //Incremental back off until ADC is free
    while(adc_busy == 1) {
        wait_us(1);
        i++;
    }

    drive->write(0);       //Reset the duty cycle back 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) {           //Avoid dividing by 0
        R = (float)v/curr;                
        R = cal_a + cal_b*R;  //Convert to Ohms
    }
    
    // Calculate accumulated resistance values for R_avg and R_var output
    R_smooth = R_SMOOTH_FACTOR*R_smooth + (1-R_SMOOTH_FACTOR)*R;
    R_acc = R_acc + R;
    R2_acc = R2_acc + R*R;
    n_acc ++;
        
}

void Heater::update()
{

    //Get error
    error = R_ref - R_smooth;    // use smoothed R values

    //Update PWM from setpoint and resistance
    double duty_cycle = thermal.pid_kp_mho * error;

    //Integral term (if used)
    if (thermal.pid_integral_time_ms > 0) { // set integral time to zero to have no integral term (== infinite integral time)
        error_integrated += error * (float) thermal.thermal_control_loop_interval_ms;
        duty_cycle += thermal.pid_kp_mho * error_integrated/thermal.pid_integral_time_ms;
    }
    
    if (duty_cycle > thermal.pid_pwm_limit) {
        duty_cycle = thermal.pid_pwm_limit;  
        error_integrated = 0;  // zero error_integrated if system is outside linear control range
        }
    else if (duty_cycle < 0) {
        duty_cycle = 0;
        error_integrated = 0;  // zero error_integrated if system is outside linear control range
        }
        
    drive->write(duty_cycle);
    guard->write(duty_cycle * thermal.guard_drive_ratio);
}

void Heater::Set_ref(float R)
{
    R_ref = R;
}
void Heater::Set_D(float D)
{
    drive->write(D);
    guard->write(D*thermal.guard_drive_ratio);
}

float Heater::Get_D() const
{
    return drive->read();
}

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

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

float Heater::Get_R_avg()
{
    R_avg = R_acc / (float) n_acc;
    return R_avg;
}

float Heater::Get_R_var() // need to call Get_R_avg to calculate R_var before calling this function
{
    R_var = R2_acc / (float) n_acc - R_avg * R_avg;
    R_acc = 0;
    R2_acc = 0;
    n_acc = 0;
    return R_var;
}

float Heater::Get_R_ref() const
{
    return R_ref;
}

float Heater::Get_error() const
{
    return error;
}

float Heater::Get_error_integrated() const
{
    return error_integrated;
}

void Heater::turn_on ()
{
    *drive = 1;
    *guard = thermal.guard_drive_ratio;
}

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