Implement maximum power-point tracking

This commit is contained in:
Thomas Kolb 2023-01-15 22:34:10 +01:00
parent a8ba1add0e
commit 4de016eb30
2 changed files with 77 additions and 3 deletions

View file

@ -289,8 +289,11 @@ fn main() -> ! {
logger.log(b"mV - Iout: ").unwrap();
data = String::from(iout);
logger.log(data.as_bytes()).unwrap();
logger.log(b"mA - Pout: ").unwrap();
data = String::from(vout * iout / 1000);
logger.log(data.as_bytes()).unwrap();
logger.log(b"mA - raw: [").unwrap();
logger.log(b"mW - raw: [").unwrap();
for i in 0..adc_value.len() {
data = String::from(adc_value[i]);

View file

@ -1,3 +1,7 @@
enum ControlMode {
MPPT,
ConstantVoltage
}
struct PID<const GAINSCALE: i32, const T0: i32>
{
@ -59,9 +63,71 @@ impl<const GAINSCALE: i32, const T0: i32> PID<GAINSCALE, T0>
}
}
struct MPPT<const INTERVAL: u32, const PWR_TOLERANCE: i32>
{
update_delay: u32,
pwm: i32,
increment: i32,
last_power: i32,
min_pwm: i32,
max_pwm: i32,
}
impl<const INTERVAL: u32, const PWR_TOLERANCE: i32> MPPT<INTERVAL, PWR_TOLERANCE>
{
pub fn new(start_pwm: i32, min_pwm: i32, max_pwm: i32) -> Self
{
MPPT::<INTERVAL, PWR_TOLERANCE> {
update_delay: INTERVAL - 1,
pwm: start_pwm,
increment: 1,
last_power: 0,
min_pwm,
max_pwm
}
}
pub fn update(&mut self, vout: i32, iout: i32) -> i32
{
if self.update_delay == 0 {
self.update_delay = INTERVAL - 1;
let cur_power = vout * iout;
let power_change = cur_power - self.last_power;
// invert search direction if measured power is significantly lower than previous measurement
if power_change.abs() > PWR_TOLERANCE && cur_power < self.last_power {
self.increment = -self.increment;
}
// enforce the pwm limits
if self.pwm == self.max_pwm {
self.increment = -1;
} else if self.pwm == self.min_pwm {
self.increment = 1;
}
// update the reference power
self.last_power = cur_power;
// step to the next test PWM value
self.pwm += self.increment;
} else {
self.update_delay -= 1;
}
self.pwm
}
}
pub struct SwitchControl<const T0: i32>
{
mode: ControlMode,
cv_pid: PID<10000, T0>,
mppt: MPPT<20, 50000 /* microwatts */>,
pwm_max: i32
}
@ -70,15 +136,20 @@ impl<const T0: i32> SwitchControl<T0>
pub fn new(cv_target: i32, pwm_max: i32) -> Self
{
SwitchControl::<T0> {
mode: ControlMode::MPPT,
cv_pid: PID::<10000, T0>::new(100, 50, 0, cv_target, 0, 0, pwm_max * 10000),
mppt: MPPT::<20, 50000>::new(pwm_max/2, 0, pwm_max),
pwm_max
}
}
// returns the new PWM value
pub fn update(&mut self, vin: i32, vout: i32, iout: i32) -> i32
pub fn update(&mut self, _vin: i32, vout: i32, iout: i32) -> i32
{
let pwm = self.cv_pid.update(vout);
let pwm = match self.mode {
ControlMode::ConstantVoltage => self.cv_pid.update(vout),
ControlMode::MPPT => self.mppt.update(vout, iout),
};
if pwm > self.pwm_max {
self.pwm_max