Implemented constant voltage regulator

This commit is contained in:
Thomas Kolb 2016-08-06 03:13:41 +02:00
parent 7b02652cad
commit 3ef6872e03
2 changed files with 70 additions and 22 deletions

2
fxplib

@ -1 +1 @@
Subproject commit 448c3504f65a37275b29661320ecf4f3ca6a924d Subproject commit 035e7ecda497b408a5791ba20a0906b913dfef45

View file

@ -12,14 +12,15 @@
#include "lcd.h" #include "lcd.h"
#include "debug.h" #include "debug.h"
#define CONV_PWM_MAX 960 #define CONV_PWM_PERIOD 960
#define CONV_PWM_MAX (98*CONV_PWM_PERIOD/100)
#define TIM_CH_CONV TIM_OC1 #define TIM_CH_CONV TIM_OC1
#define TIM_CH_BOOTSTRAP TIM_OC2 #define TIM_CH_BOOTSTRAP TIM_OC2
enum OperState { enum OperState {
Bootstrap, Bootstrap,
Convert, ConvConstVoltage,
Idle, Idle,
}; };
@ -99,13 +100,13 @@ static void init_timer(void)
// wanted: 50 kHz / 20 us period // wanted: 50 kHz / 20 us period
// system clock: 48 MHz // system clock: 48 MHz
// => 960 clock cycles / period = CONV_PWM_MAX // => 960 clock cycles / period = CONV_PWM_PERIOD
// prescaler // prescaler
timer_set_prescaler(TIM1, 0); // Timer runs at system clock timer_set_prescaler(TIM1, 0); // Timer runs at system clock
// auto-reload value // auto-reload value
timer_set_period(TIM1, CONV_PWM_MAX - 1); timer_set_period(TIM1, CONV_PWM_PERIOD - 1);
// only generate interrupt on overflow // only generate interrupt on overflow
timer_update_on_overflow(TIM1); timer_update_on_overflow(TIM1);
@ -207,6 +208,17 @@ int main(void)
fxp_t vin, vout, current; fxp_t vin, vout, current;
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 CURRENT_THRESHOLD = fxp_from_float(0.05f);
fxp_t maxVoltage = fxp_from_float(11.000f);
// Calculated values // Calculated values
//fxp_t VIN_SCALE = fxp_from_float(3.3f * (100 + 12.4f) / 12.4f / 4095.0f); //fxp_t VIN_SCALE = fxp_from_float(3.3f * (100 + 12.4f) / 12.4f / 4095.0f);
//fxp_t VOUT_SCALE = fxp_from_float(3.3f * (100 + 12.0f) / 12.0f / 4095.0f); //fxp_t VOUT_SCALE = fxp_from_float(3.3f * (100 + 12.0f) / 12.0f / 4095.0f);
@ -254,16 +266,6 @@ int main(void)
// scale current measurement // scale current measurement
curVoltage = VOLTAGE_MEAS_MAX * adcval / 4096.0f; curVoltage = VOLTAGE_MEAS_MAX * adcval / 4096.0f;
// calculate error values
pErr = targetVoltage - curVoltage;
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 = pErr * PGAIN + iErr * IGAIN;
// calculate resulting PWM value // calculate resulting PWM value
if(controlAction > MAX_DUTY_CYCLE) { if(controlAction > MAX_DUTY_CYCLE) {
@ -297,7 +299,7 @@ int main(void)
lcd_send_string(msg); lcd_send_string(msg);
lcd_send_string("V "); lcd_send_string("V ");
lcd_set_cursor_pos(0, 8); lcd_set_cursor_pos(0, 10);
scaled_val = fxp_mult(current, fxp_from_int(1000)); // A -> mA scaled_val = fxp_mult(current, fxp_from_int(1000)); // A -> mA
fxp_format(scaled_val, number, 0); fxp_format(scaled_val, number, 0);
@ -313,8 +315,9 @@ int main(void)
fxp_format_int((int32_t)cpuload, number); fxp_format_int((int32_t)cpuload, number);
fxp_right_align(number, msg, 3, '0'); fxp_right_align(number, msg, 3, '0');
lcd_send_string("L:0."); lcd_send_string("L:");
lcd_send_string(msg); lcd_send_string(msg);
lcd_send_string("m");
} }
} }
@ -332,19 +335,48 @@ int main(void)
if(timebase_ms >= 1000) { if(timebase_ms >= 1000) {
switch(operState) { switch(operState) {
case Bootstrap: case Bootstrap:
// enable bootstrap pulse for 10 ns / 10 % duty cycle // enable bootstrap pulse with very low duty cycle
// disable converter // disable converter
timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 48); timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 48);
timer_set_oc_value(TIM1, TIM_CH_CONV, 0); timer_set_oc_value(TIM1, TIM_CH_CONV, 0);
if(time_in_state > 10) { // bootstrap for 10 ms if(time_in_state >= 5) { // bootstrap duration in ms
operState = Convert; iErr = fxp_from_int(500);
operState = ConvConstVoltage;
} }
break; break;
case Convert: case ConvConstVoltage:
timer_set_oc_value(TIM1, TIM_CH_CONV, 800); // bootstrap off
timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 0); timer_set_oc_value(TIM1, TIM_CH_BOOTSTRAP, 0);
// calculate error values
pErr = fxp_sub(maxVoltage, vout);
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),
fxp_mult(iErr, IGAIN));
int32_t pwm = fxp_to_int(controlAction);
if(pwm > 5000 && current < CURRENT_THRESHOLD) {
operState = Bootstrap;
break;
}
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);
}
break; break;
case Idle: case Idle:
@ -387,6 +419,22 @@ int main(void)
sentSomething = 1; sentSomething = 1;
} }
if((timebase_ms % 500) == 100) {
debug_send_string("pErr=");
fxp_format(pErr, msg, 3);
debug_send_string(msg);
debug_send_string("; iErr=");
fxp_format(iErr, msg, 3);
debug_send_string(msg);
debug_send_string("; action=");
fxp_format(controlAction, msg, 1);
debug_send_string(msg);
sentSomething = 1;
}
if(sentSomething) { if(sentSomething) {
debug_send_string("\r\n"); debug_send_string("\r\n");
sentSomething = 0; sentSomething = 0;