From 4de016eb309704e7f3832b87227507a2f30efe01 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sun, 15 Jan 2023 22:34:10 +0100 Subject: [PATCH] Implement maximum power-point tracking --- src/main.rs | 5 ++- src/switch_control.rs | 75 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2bce6a5..208d323 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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]); diff --git a/src/switch_control.rs b/src/switch_control.rs index f886881..567ecd0 100644 --- a/src/switch_control.rs +++ b/src/switch_control.rs @@ -1,3 +1,7 @@ +enum ControlMode { + MPPT, + ConstantVoltage +} struct PID { @@ -59,9 +63,71 @@ impl PID } } +struct MPPT +{ + update_delay: u32, + + pwm: i32, + increment: i32, + last_power: i32, + + min_pwm: i32, + max_pwm: i32, +} + +impl MPPT +{ + pub fn new(start_pwm: i32, min_pwm: i32, max_pwm: i32) -> Self + { + MPPT:: { + 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 { + mode: ControlMode, cv_pid: PID<10000, T0>, + mppt: MPPT<20, 50000 /* microwatts */>, pwm_max: i32 } @@ -70,15 +136,20 @@ impl SwitchControl pub fn new(cv_target: i32, pwm_max: i32) -> Self { SwitchControl:: { + 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