PID calibration
This commit is contained in:
parent
3a6e6bdcea
commit
9799947842
@ -29,15 +29,9 @@
|
|||||||
|
|
||||||
#define ENCODER_DEBOUNCE 6000
|
#define ENCODER_DEBOUNCE 6000
|
||||||
|
|
||||||
// TODO: these need to be calibrated
|
|
||||||
// Tip mV to deg C conversion factor numerator
|
|
||||||
#define TC_CONV_NOM 151
|
|
||||||
// Tip mV to deg C conversion factor denumerator
|
|
||||||
#define TC_CONV_DEN 1000
|
|
||||||
|
|
||||||
#define MAX_BOARD_TEMP 50
|
#define MAX_BOARD_TEMP 50
|
||||||
#define MAX_TIP_TEMP 500
|
#define MAX_TIP_TEMP 500
|
||||||
#define TURN_OFF_DELAY 2
|
#define TURN_OFF_DELAY 3
|
||||||
#define CYCLES_PER_MEASURE 2
|
#define CYCLES_PER_MEASURE 2
|
||||||
#define BOARD_MAX_VOLTAGE 28000
|
#define BOARD_MAX_VOLTAGE 28000
|
||||||
|
|
||||||
|
|||||||
87
fw/main.c
87
fw/main.c
@ -364,6 +364,40 @@ static inline uint16_t isqrt(uint32_t x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Input: temperature difference
|
||||||
|
// Output: duty-cycle 0-max_duty
|
||||||
|
uint16_t pid(int16_t delta, int16_t max_duty)
|
||||||
|
{
|
||||||
|
static s32 err_p, err_i, err_d, dt, prev_err;
|
||||||
|
static u32 t, prev_t;
|
||||||
|
|
||||||
|
t = funSysTick32();
|
||||||
|
dt = FR_DIV(I2FR((t-prev_t)/DELAY_MS_TIME, R), R, I2FR(1000, R), R);
|
||||||
|
|
||||||
|
s32 err = I2FR(delta, R); // temperature delta as fixed point number
|
||||||
|
|
||||||
|
err_p = err;
|
||||||
|
if (delta > 40 && delta < -40) err_i = FR_CLAMP(FR_FixAddSat(err_i, FR_FixMulSat(err, dt)), I2FR(-1000, R), I2FR(1000, R));
|
||||||
|
else err_i = 0;
|
||||||
|
err_d = FR_DIV(FR_FixAddSat(prev_err, -err), R, dt, R);
|
||||||
|
|
||||||
|
prev_err = err;
|
||||||
|
prev_t = t;
|
||||||
|
|
||||||
|
// PID coefficients
|
||||||
|
const s32 kp = FR_numstr("1.1700", R);
|
||||||
|
const s32 ki = FR_numstr("0.05000", R);
|
||||||
|
const s32 kd = FR_numstr("0.07000", R);
|
||||||
|
s32 e = 0;
|
||||||
|
e = FR_FixAddSat(e, FR_FixMulSat(err_p, kp));
|
||||||
|
e = FR_FixAddSat(e, FR_FixMulSat(err_i, ki));
|
||||||
|
e = FR_FixAddSat(e, FR_FixMulSat(err_d, kd));
|
||||||
|
e = FR_CLAMP(e, I2FR(0, R), I2FR(100, R));
|
||||||
|
|
||||||
|
return FR2I(FR_FixMulSat(FR_DIV(e, R, I2FR(100, R), R), I2FR(max_duty, R)), R);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
__attribute__((noreturn)) int main(void)
|
__attribute__((noreturn)) int main(void)
|
||||||
{
|
{
|
||||||
SystemInit();
|
SystemInit();
|
||||||
@ -492,7 +526,7 @@ __attribute__((noreturn)) int main(void)
|
|||||||
static uint16_t vbus_mv, current_ma;
|
static uint16_t vbus_mv, current_ma;
|
||||||
static volatile int16_t temp_c, tip_temp_c;
|
static volatile int16_t temp_c, tip_temp_c;
|
||||||
static uint16_t power;
|
static uint16_t power;
|
||||||
static s32 e;
|
static uint16_t duty;
|
||||||
vbus_mv = U16_FP_EMA_K4(vbus_mv, ((u32)adc_buffer[0]*VCC_MV*11)/4096);
|
vbus_mv = U16_FP_EMA_K4(vbus_mv, ((u32)adc_buffer[0]*VCC_MV*11)/4096);
|
||||||
current_ma = U16_FP_EMA_K4(current_ma, get_current_ma(adc_buffer[1]));
|
current_ma = U16_FP_EMA_K4(current_ma, get_current_ma(adc_buffer[1]));
|
||||||
temp_c = I16_FP_EMA_K4(temp_c, get_temp_c(adc_buffer[2]));
|
temp_c = I16_FP_EMA_K4(temp_c, get_temp_c(adc_buffer[2]));
|
||||||
@ -503,9 +537,17 @@ __attribute__((noreturn)) int main(void)
|
|||||||
Delay_Ms(TURN_OFF_DELAY);
|
Delay_Ms(TURN_OFF_DELAY);
|
||||||
adc_injection_conversion();
|
adc_injection_conversion();
|
||||||
u32 tip_mv = ((u32)injection_results[0]*VCC_MV)/4096;
|
u32 tip_mv = ((u32)injection_results[0]*VCC_MV)/4096;
|
||||||
tip_temp_c = I16_FP_EMA_K2(tip_temp_c, (tip_mv*TC_CONV_NOM)/TC_CONV_DEN) + temp_c;
|
// Tip calibration factors
|
||||||
|
const s32 tip_k = FR_numstr("0.144728", R);
|
||||||
|
const s32 tip_off = FR_numstr("0", R);
|
||||||
|
int16_t tt_now = FR2I(FR_FixAddSat(FR_FixMulSat(I2FR(tip_mv, R), tip_k), tip_off), R);
|
||||||
|
tip_temp_c = I16_FP_EMA_K4(tip_temp_c, tt_now + temp_c);
|
||||||
|
if (enabled) {
|
||||||
|
duty = pid((int16_t)pd_profile.set_temp - tip_temp_c, pd_profile.max_duty);
|
||||||
|
} else {
|
||||||
|
duty = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int16_t delta = (int16_t)pd_profile.set_temp - tip_temp_c;
|
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_MENU:
|
case STATE_MENU:
|
||||||
@ -529,15 +571,14 @@ __attribute__((noreturn)) int main(void)
|
|||||||
case STATE_HEATING:
|
case STATE_HEATING:
|
||||||
// Display tip temperature
|
// Display tip temperature
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TIP:");
|
u8g2_DrawStr(u8g2, x_off+0, y_off+7, "TIP:");
|
||||||
u8g2_DrawStr(u8g2, x_off+20, y_off+7, u16toa(tip_temp_c));
|
u8g2_DrawStr(u8g2, x_off+20, y_off+7, i16toa(tip_temp_c));
|
||||||
// Display bus voltage
|
// Display bus voltage
|
||||||
u8g2_DrawStr(u8g2, x_off+45, y_off+7, "V:");
|
u8g2_DrawStr(u8g2, x_off+45, y_off+7, "V:");
|
||||||
u8g2_DrawStr(u8g2, x_off+55, y_off+7, u16toa(vbus_mv/1000));
|
u8g2_DrawStr(u8g2, x_off+55, y_off+7, u16toa(vbus_mv/1000));
|
||||||
// Display power
|
// Display power
|
||||||
//u8g2_DrawStr(u8g2, x_off+0, y_off+15, "W:");
|
//u8g2_DrawStr(u8g2, x_off+0, y_off+15, "W:");
|
||||||
//u8g2_DrawStr(u8g2, x_off+10, y_off+15, u8g2_u16toa(power, 3));
|
//u8g2_DrawStr(u8g2, x_off+10, y_off+15, u8g2_u16toa(power, 3));
|
||||||
FR_printNumF(buf_putc, e, R, 0, 3);
|
u8g2_DrawStr(u8g2, x_off+0, y_off+15, u16toa(duty));
|
||||||
u8g2_DrawStr(u8g2, x_off+0, y_off+15, buf_get());
|
|
||||||
// Display current
|
// Display current
|
||||||
// u8g2_DrawStr(u8g2, x_off+45, y_off+15, "A:");
|
// u8g2_DrawStr(u8g2, x_off+45, y_off+15, "A:");
|
||||||
// u8g2_DrawStr(u8g2, x_off+55, y_off+15, u16toa(current_ma));
|
// u8g2_DrawStr(u8g2, x_off+55, y_off+15, u16toa(current_ma));
|
||||||
@ -571,37 +612,8 @@ __attribute__((noreturn)) int main(void)
|
|||||||
|
|
||||||
if (pwm) {
|
if (pwm) {
|
||||||
const uint16_t tim_max = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
const uint16_t tim_max = FUNCONF_SYSTEM_CORE_CLOCK / PWM_FREQ_HZ - 1;
|
||||||
static s32 err_p, err_i, err_d, dt, fpt, prev_fpt;
|
pwm_set(((u32)duty*tim_max)/100);
|
||||||
static u32 t, prev_t;
|
u8g2_DrawBox(u8g2, x_off+92, y_off+12, 4, 4);
|
||||||
uint16_t duty;
|
|
||||||
// absolute temperature error
|
|
||||||
s32 err = I2FR(delta, R);
|
|
||||||
fpt = I2FR(tip_temp_c, R);
|
|
||||||
t = funSysTick32();
|
|
||||||
|
|
||||||
dt = FR_DIV(I2FR((t-prev_t)/DELAY_MS_TIME, R), R, I2FR(1000, R), R);
|
|
||||||
err_p = err;
|
|
||||||
// Conditional integration
|
|
||||||
if (delta > 40 && delta < -40) err_i = FR_CLAMP(FR_FixAddSat(err_i, FR_FixMulSat(err, dt)), I2FR(-1000, R), I2FR(1000, R));
|
|
||||||
err_d = FR_DIV(FR_FixAddSat(prev_fpt, -fpt), R, dt, R);
|
|
||||||
prev_t = t;
|
|
||||||
prev_fpt = fpt;
|
|
||||||
|
|
||||||
const s32 kp = FR_numstr("1.2000", R);
|
|
||||||
const s32 ki = FR_numstr("0.05000", R);
|
|
||||||
const s32 kd = FR_numstr("0.00000", R);
|
|
||||||
e = 0;
|
|
||||||
e = FR_FixAddSat(e, FR_FixMulSat(err_p, kp));
|
|
||||||
e = FR_FixAddSat(e, FR_FixMulSat(err_i, ki));
|
|
||||||
e = FR_FixAddSat(e, FR_FixMulSat(err_d, kd));
|
|
||||||
|
|
||||||
e = FR_CLAMP(e, I2FR(0, R), I2FR(100, R));
|
|
||||||
duty = FR2I(FR_FixMulSat(FR_DIV(e, R, I2FR(100, R), R), I2FR(pd_profile.max_duty, R)), R);
|
|
||||||
|
|
||||||
if (duty <= 100) {
|
|
||||||
pwm_set(((u32)duty*tim_max)/100);
|
|
||||||
u8g2_DrawBox(u8g2, x_off+92, y_off+12, 4, 4);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pwm_set(0);
|
pwm_set(0);
|
||||||
}
|
}
|
||||||
@ -622,7 +634,6 @@ __attribute__((noreturn)) int main(void)
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
pwm_on();
|
pwm_on();
|
||||||
} else {
|
} else {
|
||||||
e = 0;
|
|
||||||
pwm_off();
|
pwm_off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user