diff --git a/README.md b/README.md index f9576ed..154c075 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The scope of this setting is per TCP session. | `pwm <0/1> max_i_pos ` | Set PWM duty cycle for **max_i_pos** to *ampere* | | `pwm <0/1> max_i_neg ` | Set PWM duty cycle for **max_i_neg** to *ampere* | | `pwm <0/1> max_v ` | Set PWM duty cycle for **max_v** to *volt* | -| `pwm <0/1> ` | Disengage PID, set **i_set** DAC to *volts* | +| `pwm <0/1> ` | Disengage PID, set **i_set** DAC to *ampere* | | `pwm <0/1> pid` | Set PWM to be controlled by PID | | `pid` | Show PID configuration | | `pid <0/1> target ` | Set the PID controller target | diff --git a/src/channels.rs b/src/channels.rs index b0a9e2d..c6ee771 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,9 +1,10 @@ use stm32f4xx_hal::hal; use smoltcp::time::Instant; use uom::si::{ - f64::{ElectricCurrent, ElectricPotential}, + f64::{ElectricCurrent, ElectricPotential, ElectricalResistance}, electric_potential::{millivolt, volt}, electric_current::ampere, + electrical_resistance::ohm, ratio::ratio, }; use log::info; @@ -17,6 +18,7 @@ use crate::{ }; pub const CHANNELS: usize = 2; +pub const R_SENSE: f64 = 0.05; // TODO: -pub pub struct Channels { @@ -91,7 +93,28 @@ impl Channels { } /// i_set DAC - pub fn set_dac(&mut self, channel: usize, voltage: ElectricPotential) -> (ElectricPotential, ElectricPotential) { + fn get_dac(&mut self, channel: usize) -> (ElectricPotential, ElectricPotential) { + let dac_factor = match channel.into() { + 0 => self.channel0.dac_factor, + 1 => self.channel1.dac_factor, + _ => unreachable!(), + }; + let voltage = self.channel_state(channel).dac_value; + let max = ElectricPotential::new::(ad5680::MAX_VALUE as f64 / dac_factor); + (voltage, max) + } + + pub fn get_i(&mut self, channel: usize) -> (ElectricCurrent, ElectricCurrent) { + let vref = self.channel_state(channel).vref; + let r_sense = ElectricalResistance::new::(R_SENSE); + let (voltage, max) = self.get_dac(channel); + let i_tec = (voltage - vref) / (10.0 * r_sense); + let max = (max - vref) / (10.0 * r_sense); + (i_tec, max) + } + + /// i_set DAC + fn set_dac(&mut self, channel: usize, voltage: ElectricPotential) -> (ElectricPotential, ElectricPotential) { let dac_factor = match channel.into() { 0 => self.channel0.dac_factor, 1 => self.channel1.dac_factor, @@ -109,6 +132,16 @@ impl Channels { (voltage, max) } + pub fn set_i(&mut self, channel: usize, i_tec: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) { + let vref = self.channel_state(channel).vref; + let r_sense = ElectricalResistance::new::(R_SENSE); + let voltage = i_tec * 10.0 * r_sense + vref; + let (voltage, max) = self.set_dac(channel, voltage); + let i_tec = (voltage - vref) / (10.0 * r_sense); + let max = (max - vref) / (10.0 * r_sense); + (i_tec, max) + } + pub fn read_dac_feedback(&mut self, channel: usize) -> ElectricPotential { match channel { 0 => { diff --git a/src/main.rs b/src/main.rs index 8bb7c7d..0999bbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -229,7 +229,12 @@ fn main() -> ! { channel, if state.pid_engaged { "engaged" } else { "disengaged" } ); - let _ = writeln!(socket, "- i_set={:.3}", state.dac_value.into_format_args(volt, Abbreviation)); + let i_set = channels.get_i(channel); + let _ = writeln!( + socket, "- i_set={:.3} / {:.3}", + i_set.0.into_format_args(ampere, Abbreviation), + i_set.1.into_format_args(ampere, Abbreviation), + ); let max_v = channels.get_max_v(channel); let _ = writeln!( socket, "- max_v={:.3} / {:.3}", @@ -302,13 +307,13 @@ fn main() -> ! { Command::Pwm { channel, pin: PwmPin::ISet, value } => { channels.channel_state(channel).pid_engaged = false; leds.g3.off(); - let voltage = ElectricPotential::new::(value); - let (voltage, max) = channels.set_dac(channel, voltage); + let current = ElectricCurrent::new::(value); + let (current, max) = channels.set_i(channel, current); let _ = writeln!( socket, "channel {}: i_set DAC output set to {:.3} / {:.3}", channel, - voltage.into_format_args(volt, Abbreviation), - max.into_format_args(volt, Abbreviation), + current.into_format_args(ampere, Abbreviation), + max.into_format_args(ampere, Abbreviation), ); } Command::Pwm { channel, pin, value } => {