Implemented Constant Current mode

This commit is contained in:
Thomas Kolb 2016-08-06 22:22:21 +02:00
parent 3ef6872e03
commit 97db9c24db
1 changed files with 96 additions and 48 deletions

View File

@ -21,6 +21,7 @@
enum OperState {
Bootstrap,
ConvConstVoltage,
ConvConstCurrent,
Idle,
};
@ -203,21 +204,32 @@ int main(void)
char number[FXP_STR_MAXLEN];
uint8_t sentSomething = 0;
int32_t pwm;
enum OperState operState = Bootstrap;
enum OperState nextState = ConvConstVoltage;
enum OperState lastState = operState;
fxp_t vin, vout, current;
fxp_t vin_avg = 0, vout_avg = 0, current_avg = 0;
fxp_t pErr, iErr = 0;
fxp_t controlAction;
fxp_t PGAIN = fxp_from_float( 20.000f);
fxp_t IGAIN = fxp_from_float( 1.000f);
fxp_t IERR_LIMIT = fxp_from_int(10000);
fxp_t PGAIN_CV = fxp_from_float( 50.000f);
fxp_t IGAIN_CV = fxp_from_float( 0.300f);
fxp_t IERR_LIMIT = fxp_from_int(4000);
fxp_t PGAIN_CC = fxp_from_float( 50.000f);
fxp_t IGAIN_CC = fxp_from_float( 0.300f);
fxp_t CURRENT_THRESHOLD = fxp_from_float(0.05f);
fxp_t maxVoltage = fxp_from_float(11.000f);
fxp_t AVG_FACT = fxp_from_float(0.10f);
fxp_t AVG_FACT_INV = fxp_sub(fxp_from_int(1), AVG_FACT);
fxp_t maxVoltage = fxp_from_float(12.000f);
fxp_t maxCurrent = fxp_from_float( 5.000f);
// Calculated values
//fxp_t VIN_SCALE = fxp_from_float(3.3f * (100 + 12.4f) / 12.4f / 4095.0f);
@ -229,6 +241,8 @@ int main(void)
fxp_t VOUT_SCALE = fxp_from_float(12.6f / 1620.0f);
fxp_t CURRENT_SCALE = fxp_from_float(9.01f / 4095.0f);
fxp_t CURRENT_OFFSET = fxp_from_float(0.049);
init_clock();
init_gpio();
init_adc();
@ -246,37 +260,6 @@ int main(void)
// let the ADC+DMA do its work
adc_start_conversion_regular(ADC1);
/*
// Ramp up target voltage
if((targetVoltage < TARGET_VOLTAGE) && (voltRampUpCountdown-- == 0)) {
targetVoltage += 2.0f;
voltRampUpCountdown = VOLTAGE_UP_INTERVAL;
if(targetVoltage > TARGET_VOLTAGE) {
targetVoltage = TARGET_VOLTAGE;
}
}
// read ADC value
while(!adc_eoc(ADC1));
adcval = adc_read_regular(ADC1);
// scale current measurement
curVoltage = VOLTAGE_MEAS_MAX * adcval / 4096.0f;
// calculate resulting PWM value
if(controlAction > MAX_DUTY_CYCLE) {
pwm_value = (int)(PWM_PERIOD * MAX_DUTY_CYCLE);
} else if(controlAction > 0) {
pwm_value = (int)(controlAction * PWM_PERIOD);
} else {
pwm_value = 0;
}
*/
// *** Do some calculations while ADC converts ***
if(lcd_setup()) {
@ -287,13 +270,13 @@ int main(void)
lcd_set_cursor_pos(1, 0);
fxp_format(vin, number, 1);
fxp_format(vin_avg, number, 1);
fxp_right_align(number, msg, 4, ' ');
lcd_send_string("I:");
lcd_send_string(msg);
lcd_send_string("V ");
fxp_format(vout, number, 1);
fxp_format(vout_avg, number, 1);
fxp_right_align(number, msg, 4, ' ');
lcd_send_string("O:");
lcd_send_string(msg);
@ -301,7 +284,7 @@ int main(void)
lcd_set_cursor_pos(0, 10);
scaled_val = fxp_mult(current, fxp_from_int(1000)); // A -> mA
scaled_val = fxp_mult(current_avg, fxp_from_int(1000)); // A -> mA
fxp_format(scaled_val, number, 0);
fxp_right_align(number, msg, 4, ' ');
lcd_send_string(msg);
@ -330,6 +313,11 @@ int main(void)
vin = fxp_mult(fxp_from_int(adc_values[0]), VIN_SCALE);
vout = fxp_mult(fxp_from_int(adc_values[1]), VOUT_SCALE);
current = fxp_mult(fxp_from_int(adc_values[2]), CURRENT_SCALE);
current = fxp_sub(current, CURRENT_OFFSET);
vin_avg = fxp_add(fxp_mult(vin, AVG_FACT), fxp_mult(vin_avg, AVG_FACT_INV));
vout_avg = fxp_add(fxp_mult(vout, AVG_FACT), fxp_mult(vout_avg, AVG_FACT_INV));
current_avg = fxp_add(fxp_mult(current, AVG_FACT), fxp_mult(current_avg, AVG_FACT_INV));
// Main FSM
if(timebase_ms >= 1000) {
@ -342,7 +330,7 @@ int main(void)
if(time_in_state >= 5) { // bootstrap duration in ms
iErr = fxp_from_int(500);
operState = ConvConstVoltage;
operState = nextState;
}
break;
@ -351,7 +339,7 @@ int main(void)
timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 0);
// calculate error values
pErr = fxp_sub(maxVoltage, vout);
pErr = fxp_sub(maxVoltage, vout_avg);
iErr = fxp_add(iErr, pErr);
// limit integral error range
@ -360,15 +348,10 @@ int main(void)
// calculate the controller output ("action")
controlAction = fxp_add(
fxp_mult(pErr, PGAIN),
fxp_mult(iErr, IGAIN));
fxp_mult(pErr, PGAIN_CV),
fxp_mult(iErr, IGAIN_CV));
int32_t pwm = fxp_to_int(controlAction);
if(pwm > 5000 && current < CURRENT_THRESHOLD) {
operState = Bootstrap;
break;
}
pwm = fxp_to_int(controlAction);
if(pwm >= CONV_PWM_MAX) {
timer_set_oc_value(TIM1, TIM_CH_CONV, CONV_PWM_MAX);
@ -377,6 +360,52 @@ int main(void)
} else {
timer_set_oc_value(TIM1, TIM_CH_CONV, 0);
}
if(time_in_state > 1000 && pwm > CONV_PWM_MAX && current < CURRENT_THRESHOLD) {
operState = Bootstrap;
nextState = ConvConstVoltage;
}
if(current_avg > maxCurrent) {
operState = ConvConstCurrent;
}
break;
case ConvConstCurrent:
// bootstrap off
timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 0);
// calculate error values
pErr = fxp_sub(maxCurrent, current_avg);
iErr = fxp_add(iErr, pErr);
// limit integral error range
if (iErr > IERR_LIMIT) iErr = IERR_LIMIT;
else if(iErr < -IERR_LIMIT) iErr = -IERR_LIMIT;
// calculate the controller output ("action")
controlAction = fxp_add(
fxp_mult(pErr, PGAIN_CC),
fxp_mult(iErr, IGAIN_CC));
pwm = fxp_to_int(controlAction);
if(pwm >= CONV_PWM_MAX) {
timer_set_oc_value(TIM1, TIM_CH_CONV, CONV_PWM_MAX);
} else if(pwm > 0) {
timer_set_oc_value(TIM1, TIM_CH_CONV, pwm);
} else {
timer_set_oc_value(TIM1, TIM_CH_CONV, 0);
}
if(time_in_state > 1000 && pwm > CONV_PWM_MAX && current < CURRENT_THRESHOLD) {
operState = Bootstrap;
nextState = ConvConstCurrent;
}
if(vout_avg > maxVoltage) {
operState = ConvConstVoltage;
}
break;
case Idle:
@ -396,6 +425,25 @@ int main(void)
if(operState != lastState) {
time_in_state = 0;
lastState = operState;
lcd_set_cursor_pos(0, 7);
switch(operState) {
case Idle:
lcd_send_string("ID");
break;
case Bootstrap:
lcd_send_string("BS");
break;
case ConvConstCurrent:
lcd_send_string("CC");
break;
case ConvConstVoltage:
lcd_send_string("CV");
break;
default:
lcd_send_string("??");
break;
}
} else {
time_in_state++;
}