Heater for threaded program
Dependents: LEX_Threaded_Programming_V3
Heater.cpp
- Committer:
- justinbuckland
- Date:
- 2019-12-17
- Revision:
- 48:cd2a9b799e89
- Parent:
- 47:06a9691d0a7b
- Child:
- 49:35fd40559960
File content as of revision 48:cd2a9b799e89:
/*------------------------------------------------------------------------------ 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; // use single reading R values 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 if (abs(error) > thermal.pid_wind_up_limit_ohm) error = error * thermal.pid_wind_up_limit_ohm / abs(error); 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; else if (duty_cycle < 0) duty_cycle = 0; 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; }