Heater for threaded program

Dependents:   LEX_Threaded_Programming_V3

Committer:
justinbuckland
Date:
Mon Nov 11 08:29:51 2019 +0000
Revision:
43:d34ac9d8648c
Parent:
42:166d9bc7675e
Child:
44:e358867319f6
no change

Who changed what in which revision?

UserRevisionLine numberNew contents of line
omatthews 0:4e33cc8171f4 1 /*------------------------------------------------------------------------------
omatthews 0:4e33cc8171f4 2 Library code file for interface to Heater
omatthews 0:4e33cc8171f4 3 Date: 16/07/2018
omatthews 0:4e33cc8171f4 4
omatthews 0:4e33cc8171f4 5
omatthews 0:4e33cc8171f4 6 ------------------------------------------------------------------------------*/
omatthews 1:4435d407d827 7 #include "mbed.h"
omatthews 1:4435d407d827 8 #include "MODSERIAL.h"
omatthews 0:4e33cc8171f4 9 #include "Heater.h"
omatthews 0:4e33cc8171f4 10 #include "ADS8568_ADC.h"
omatthews 0:4e33cc8171f4 11
justinbuckland 43:d34ac9d8648c 12 #define GUARD_DUTY_CYCLE_REF 0.1 // start to reduce guard drive ratio at this duty cycle for main heater
justinbuckland 43:d34ac9d8648c 13 #define GUARD_DUTY_CYCLE_SLOPE 0.5 // slope for reducing guard drive ratio at increasing duty cycle for main heater
justinbuckland 43:d34ac9d8648c 14
justinbuckland 35:5acf01897ed6 15 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)
justinbuckland 35:5acf01897ed6 16 :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)
omatthews 30:055d856f05b5 17 {
justinbuckland 42:166d9bc7675e 18 //Set up PWM
omatthews 30:055d856f05b5 19 drive->prescaler(1);
omatthews 30:055d856f05b5 20 guard->prescaler(1);
omatthews 30:055d856f05b5 21 drive->period_ticks(1000);
omatthews 30:055d856f05b5 22 guard->period_ticks(1000);
justinbuckland 42:166d9bc7675e 23
justinbuckland 42:166d9bc7675e 24 //Initialise values for averaging resistance
justinbuckland 42:166d9bc7675e 25 n_acc = 0;
justinbuckland 42:166d9bc7675e 26 R_acc = 0;
omatthews 30:055d856f05b5 27 }
omatthews 30:055d856f05b5 28
omatthews 2:7f15386fcc90 29 void Heater::read()
omatthews 0:4e33cc8171f4 30 {
omatthews 1:4435d407d827 31 //Reads R and then resets the drive back to its previous value
omatthews 30:055d856f05b5 32 int i = 0;
justinbuckland 43:d34ac9d8648c 33 int guard_wait_us;
justinbuckland 43:d34ac9d8648c 34 int main_wait_us;
justinbuckland 43:d34ac9d8648c 35
omatthews 17:0bfed0e96927 36 double drive_prev = drive->read(); //Store previous value of drive
justinbuckland 35:5acf01897ed6 37
justinbuckland 43:d34ac9d8648c 38 guard_wait_us = (float)thermal.settling_time_us * thermal.guard_drive_ratio;
justinbuckland 43:d34ac9d8648c 39 main_wait_us = thermal.settling_time_us - guard_wait_us;
justinbuckland 43:d34ac9d8648c 40
justinbuckland 43:d34ac9d8648c 41 *drive = 1.0f; //Turn the main heater on for the measurement
justinbuckland 43:d34ac9d8648c 42
justinbuckland 43:d34ac9d8648c 43 wait_us(main_wait_us); //Wait for ADC to settle
justinbuckland 34:294adcc3e4b2 44 adc->start_conversion(ADC_CONV_ALL_CH);
justinbuckland 34:294adcc3e4b2 45
omatthews 18:f5d26d3d532f 46 //Incremental back off until ADC is free
omatthews 30:055d856f05b5 47 while(adc_busy == 1) {
omatthews 30:055d856f05b5 48 wait_us(1);
omatthews 30:055d856f05b5 49 i++;
omatthews 30:055d856f05b5 50 }
omatthews 25:09a315a59956 51
justinbuckland 43:d34ac9d8648c 52 drive->write(0); //Set duty cycle to zero
omatthews 18:f5d26d3d532f 53
omatthews 18:f5d26d3d532f 54 //Get voltage, current and R values from the ADC conversion
omatthews 31:7c6f05326c4d 55 adc->read_channels();
omatthews 31:7c6f05326c4d 56 curr = adc->read_channel_result(i_port);
omatthews 31:7c6f05326c4d 57 v = adc->read_channel_result(v_port);
omatthews 30:055d856f05b5 58
justinbuckland 35:5acf01897ed6 59 if (curr > 0) { //Avoid dividing by 0
justinbuckland 35:5acf01897ed6 60 R = (float)v/curr;
justinbuckland 35:5acf01897ed6 61 R = cal_a + cal_b*R; //Convert to Ohms
omatthews 30:055d856f05b5 62 }
justinbuckland 42:166d9bc7675e 63
justinbuckland 42:166d9bc7675e 64 // Calcualate accumulated resistance values for R_avg output
justinbuckland 42:166d9bc7675e 65 R_acc = R_acc + R;
justinbuckland 42:166d9bc7675e 66 n_acc ++;
justinbuckland 35:5acf01897ed6 67
omatthews 0:4e33cc8171f4 68 }
omatthews 0:4e33cc8171f4 69
omatthews 25:09a315a59956 70 void Heater::update()
omatthews 7:59ece353eea2 71 {
justinbuckland 41:b1602c68abcd 72 //Get error
justinbuckland 41:b1602c68abcd 73 error = R_ref - R;
justinbuckland 41:b1602c68abcd 74
omatthews 25:09a315a59956 75 //Update PWM from setpoint and resistance
paullj 39:5dffedda7a0d 76 double duty_cycle = thermal.pid_kp_mho * error;
justinbuckland 41:b1602c68abcd 77
justinbuckland 41:b1602c68abcd 78 //Get integrated error
paullj 39:5dffedda7a0d 79 if (thermal.pid_integral_time_ms > 0) // set integral time to zero to have no integral term
justinbuckland 41:b1602c68abcd 80 if (abs(error) > thermal.pid_wind_up_limit_ohm) error = error * thermal.pid_wind_up_limit_ohm / abs(error);
justinbuckland 41:b1602c68abcd 81 error_integrated += error * (float) thermal.thermal_control_loop_interval_ms;
paullj 39:5dffedda7a0d 82 duty_cycle += thermal.pid_kp_mho * error_integrated/thermal.pid_integral_time_ms;
justinbuckland 43:d34ac9d8648c 83
paullj 39:5dffedda7a0d 84 if (duty_cycle > thermal.pid_pwm_limit)
paullj 39:5dffedda7a0d 85 duty_cycle = thermal.pid_pwm_limit;
paullj 39:5dffedda7a0d 86 else if (duty_cycle < 0)
paullj 39:5dffedda7a0d 87 duty_cycle = 0;
justinbuckland 36:a8130bd29349 88
justinbuckland 43:d34ac9d8648c 89 //Reduce guard drive ratio to be lower at higher duty cycles: full value up to GUARD_DUTY_CYCLE_REF, then decreases with gradient GUARD_DUTY_CYCLE_SLOPE
justinbuckland 43:d34ac9d8648c 90
justinbuckland 43:d34ac9d8648c 91 double guard_drive_ratio_factor = 1 + GUARD_DUTY_CYCLE_SLOPE*(1 - duty_cycle/GUARD_DUTY_CYCLE_REF);
justinbuckland 43:d34ac9d8648c 92
justinbuckland 43:d34ac9d8648c 93 if (guard_drive_ratio_factor > 1) guard_drive_ratio_factor = 1;
justinbuckland 43:d34ac9d8648c 94 if (guard_drive_ratio_factor < 0) guard_drive_ratio_factor = 0;
justinbuckland 43:d34ac9d8648c 95
omatthews 31:7c6f05326c4d 96 drive->write(duty_cycle);
justinbuckland 43:d34ac9d8648c 97 guard->write(duty_cycle * thermal.guard_drive_ratio * guard_drive_ratio_factor);
omatthews 7:59ece353eea2 98 }
omatthews 18:f5d26d3d532f 99
omatthews 30:055d856f05b5 100 void Heater::Set_ref(float R)
omatthews 19:fccdd7127f94 101 {
omatthews 19:fccdd7127f94 102 R_ref = R;
omatthews 19:fccdd7127f94 103 }
omatthews 30:055d856f05b5 104 void Heater::Set_D(float D)
omatthews 30:055d856f05b5 105 {
omatthews 25:09a315a59956 106 drive->write(D);
omatthews 26:f6c98b05ee85 107 guard->write(D*thermal.guard_drive_ratio);
omatthews 30:055d856f05b5 108 }
omatthews 0:4e33cc8171f4 109
justinbuckland 42:166d9bc7675e 110 float Heater::Get_D() const
omatthews 31:7c6f05326c4d 111 {
omatthews 31:7c6f05326c4d 112 return drive->read();
omatthews 31:7c6f05326c4d 113 }
omatthews 31:7c6f05326c4d 114
omatthews 30:055d856f05b5 115 int Heater::Get_i() const
omatthews 30:055d856f05b5 116 {
omatthews 30:055d856f05b5 117 return curr;
omatthews 30:055d856f05b5 118 }
omatthews 30:055d856f05b5 119 int Heater::Get_v() const
omatthews 30:055d856f05b5 120 {
omatthews 30:055d856f05b5 121 return v;
omatthews 30:055d856f05b5 122 }
omatthews 2:7f15386fcc90 123
omatthews 30:055d856f05b5 124 float Heater::Get_R() const
omatthews 30:055d856f05b5 125 {
omatthews 30:055d856f05b5 126 return R;
omatthews 30:055d856f05b5 127 }
omatthews 0:4e33cc8171f4 128
justinbuckland 42:166d9bc7675e 129 float Heater::Get_R_avg()
justinbuckland 42:166d9bc7675e 130 {
justinbuckland 42:166d9bc7675e 131 R_avg = R_acc / (float) n_acc;
justinbuckland 42:166d9bc7675e 132 R_acc = 0;
justinbuckland 42:166d9bc7675e 133 n_acc = 0;
justinbuckland 42:166d9bc7675e 134 return R_avg;
justinbuckland 42:166d9bc7675e 135 }
justinbuckland 42:166d9bc7675e 136
omatthews 31:7c6f05326c4d 137 float Heater::Get_R_ref() const
omatthews 31:7c6f05326c4d 138 {
omatthews 31:7c6f05326c4d 139 return R_ref;
omatthews 31:7c6f05326c4d 140 }
omatthews 31:7c6f05326c4d 141
omatthews 31:7c6f05326c4d 142 float Heater::Get_error() const
omatthews 31:7c6f05326c4d 143 {
omatthews 31:7c6f05326c4d 144 return error;
omatthews 31:7c6f05326c4d 145 }
omatthews 31:7c6f05326c4d 146
omatthews 31:7c6f05326c4d 147 float Heater::Get_error_integrated() const
omatthews 31:7c6f05326c4d 148 {
omatthews 31:7c6f05326c4d 149 return error_integrated;
omatthews 31:7c6f05326c4d 150 }
omatthews 31:7c6f05326c4d 151
omatthews 30:055d856f05b5 152 void Heater::turn_on ()
omatthews 19:fccdd7127f94 153 {
omatthews 19:fccdd7127f94 154 *drive = 1;
omatthews 26:f6c98b05ee85 155 *guard = thermal.guard_drive_ratio;
omatthews 19:fccdd7127f94 156 }
omatthews 1:4435d407d827 157
omatthews 30:055d856f05b5 158 void Heater::turn_off ()
omatthews 19:fccdd7127f94 159 {
omatthews 19:fccdd7127f94 160 *drive = 0;
omatthews 19:fccdd7127f94 161 *guard = 0;
omatthews 19:fccdd7127f94 162 }