From bb26490153aa63fea17df39c94d5a93911df654a Mon Sep 17 00:00:00 2001 From: Astro Date: Sun, 13 Sep 2020 22:52:20 +0200 Subject: [PATCH] unit: replace with uom --- Cargo.lock | 11 ++++++++ Cargo.toml | 1 + src/channel_state.rs | 9 ++++-- src/channels.rs | 51 ++++++++++++++++++---------------- src/main.rs | 28 +++++++++++++------ src/units.rs | 65 -------------------------------------------- 6 files changed, 64 insertions(+), 101 deletions(-) delete mode 100644 src/units.rs diff --git a/Cargo.lock b/Cargo.lock index abcb848..1cb20ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -402,6 +402,7 @@ dependencies = [ "smoltcp", "stm32-eth", "stm32f4xx-hal", + "uom", "usb-device", "usbd-serial", ] @@ -418,6 +419,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "uom" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb593f5252356bfb829112f8fca2d0982d48588d2d6bb5a92553b0dfc4c9aba" +dependencies = [ + "num-traits", + "typenum", +] + [[package]] name = "usb-device" version = "0.2.5" diff --git a/Cargo.toml b/Cargo.toml index 3cf69b8..06861b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ num-traits = { version = "0.2", default-features = false, features = ["libm"] } usb-device = "0.2" usbd-serial = "0.1" nb = "0.1" +uom = { version = "0.29", default-features = false, features = ["autoconvert", "si", "f64"] } [patch.crates-io] stm32f4xx-hal = { git = "https://github.com/stm32-rs/stm32f4xx-hal.git" } diff --git a/src/channel_state.rs b/src/channel_state.rs index 78573e4..195a4e0 100644 --- a/src/channel_state.rs +++ b/src/channel_state.rs @@ -1,16 +1,19 @@ use smoltcp::time::Instant; +use uom::si::{ + f64::ElectricPotential, + electric_potential::volt, +}; use crate::{ ad7172, pid, steinhart_hart as sh, - units::Volts, }; pub struct ChannelState { pub adc_data: Option, pub adc_time: Instant, - pub dac_value: Volts, + pub dac_value: ElectricPotential, pub pid_engaged: bool, pub pid: pid::Controller, pub sh: sh::Parameters, @@ -21,7 +24,7 @@ impl Default for ChannelState { ChannelState { adc_data: None, adc_time: Instant::from_secs(0), - dac_value: Volts(0.0), + dac_value: ElectricPotential::new::(0.0), pid_engaged: false, pid: pid::Controller::new(pid::Parameters::default()), sh: sh::Parameters::default(), diff --git a/src/channels.rs b/src/channels.rs index 8602e00..5900f4c 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,4 +1,8 @@ use smoltcp::time::Instant; +use uom::si::{ + f64::ElectricPotential, + electric_potential::{millivolt, volt}, +}; use log::info; use crate::{ ad5680, @@ -6,7 +10,6 @@ use crate::{ channel::{Channel, Channel0, Channel1}, channel_state::ChannelState, pins, - units::Volts, }; pub const CHANNELS: usize = 2; @@ -69,7 +72,7 @@ impl Channels { }; if let Some(dac_value) = dac_value { // Forward PID output to i_set DAC - self.set_dac(channel.into(), Volts(dac_value)); + self.set_dac(channel.into(), ElectricPotential::new::(dac_value)); } channel @@ -77,13 +80,13 @@ impl Channels { } /// i_set DAC - pub fn set_dac(&mut self, channel: usize, voltage: Volts) { + pub fn set_dac(&mut self, channel: usize, voltage: ElectricPotential) { let dac_factor = match channel.into() { 0 => self.channel0.dac_factor, 1 => self.channel1.dac_factor, _ => unreachable!(), }; - let value = (voltage.0 * dac_factor) as u32; + let value = (voltage.get::() * dac_factor) as u32; match channel { 0 => { self.channel0.dac.set(value).unwrap(); @@ -97,7 +100,7 @@ impl Channels { } } - pub fn read_dac_feedback(&mut self, channel: usize) -> Volts { + pub fn read_dac_feedback(&mut self, channel: usize) -> ElectricPotential { match channel { 0 => { let sample = self.pins_adc.convert( @@ -106,7 +109,7 @@ impl Channels { ); let mv = self.pins_adc.sample_to_millivolts(sample); info!("dac0_fb: {}/{:03X}", mv, sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } 1 => { let sample = self.pins_adc.convert( @@ -115,25 +118,25 @@ impl Channels { ); let mv = self.pins_adc.sample_to_millivolts(sample); info!("dac1_fb: {}/{:03X}", mv, sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } _ => unreachable!(), } } - pub fn read_dac_feedback_until_stable(&mut self, channel: usize, tolerance: f64) -> Volts { + pub fn read_dac_feedback_until_stable(&mut self, channel: usize, tolerance: ElectricPotential) -> ElectricPotential { let mut prev = self.read_dac_feedback(channel); loop { let current = self.read_dac_feedback(channel); use num_traits::float::Float; - if (current - prev).0.abs() < tolerance { + if (current - prev).abs() < tolerance { return current; } prev = current; } } - pub fn read_itec(&mut self, channel: usize) -> Volts { + pub fn read_itec(&mut self, channel: usize) -> ElectricPotential { match channel { 0 => { let sample = self.pins_adc.convert( @@ -141,7 +144,7 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } 1 => { let sample = self.pins_adc.convert( @@ -149,14 +152,14 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } _ => unreachable!(), } } /// should be 1.5V - pub fn read_vref(&mut self, channel: usize) -> Volts { + pub fn read_vref(&mut self, channel: usize) -> ElectricPotential { match channel { 0 => { let sample = self.pins_adc.convert( @@ -164,7 +167,7 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64 / 1000.0) } 1 => { let sample = self.pins_adc.convert( @@ -172,13 +175,13 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64 / 1000.0) } _ => unreachable!(), } } - pub fn read_tec_u_meas(&mut self, channel: usize) -> Volts { + pub fn read_tec_u_meas(&mut self, channel: usize) -> ElectricPotential { match channel { 0 => { let sample = self.pins_adc.convert( @@ -186,7 +189,7 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } 1 => { let sample = self.pins_adc.convert( @@ -194,7 +197,7 @@ impl Channels { stm32f4xx_hal::adc::config::SampleTime::Cycles_480 ); let mv = self.pins_adc.sample_to_millivolts(sample); - Volts(mv as f64 / 1000.0) + ElectricPotential::new::(mv as f64) } _ => unreachable!(), } @@ -205,9 +208,9 @@ impl Channels { /// These loops perform a width-first search for the DAC setting /// that will produce a `target_voltage`. pub fn calibrate_dac_value(&mut self, channel: usize) { - let target_voltage = Volts(2.5); + let target_voltage = ElectricPotential::new::(2.5); let mut start_value = 1; - let mut best_error = Volts(100.0); + let mut best_error = ElectricPotential::new::(100.0); for step in (0..18).rev() { let mut prev_value = start_value; @@ -222,15 +225,15 @@ impl Channels { _ => unreachable!(), } - let dac_feedback = self.read_dac_feedback_until_stable(channel, 0.001); + let dac_feedback = self.read_dac_feedback_until_stable(channel, ElectricPotential::new::(0.001)); let error = target_voltage - dac_feedback; - if error < Volts(0.0) { + if error < ElectricPotential::new::(0.0) { break; } else if error < best_error { best_error = error; start_value = prev_value; - let dac_factor = value as f64 / dac_feedback.0; + let dac_factor = value as f64 / dac_feedback.get::(); match channel { 0 => self.channel0.dac_factor = dac_factor, 1 => self.channel1.dac_factor = dac_factor, @@ -243,6 +246,6 @@ impl Channels { } // Reset - self.set_dac(channel, Volts(0.0)); + self.set_dac(channel, ElectricPotential::new::(0.0)); } } diff --git a/src/main.rs b/src/main.rs index ca7efe4..265147d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,18 @@ use smoltcp::{ time::Instant, wire::EthernetAddress, }; +use uom::{ + fmt::DisplayStyle::Abbreviation, + si::{ + f64::{ + ElectricPotential, + ElectricalResistance, + }, + electric_current::ampere, + electric_potential::volt, + electrical_resistance::ohm, + }, +}; mod init_log; use init_log::init_log; @@ -45,8 +57,6 @@ use session::{Session, SessionOutput}; mod command_parser; use command_parser::{Command, ShowCommand, PwmPin}; mod timer; -mod units; -use units::{Ohms, Volts}; mod pid; mod steinhart_hart; mod channels; @@ -165,7 +175,7 @@ fn main() -> ! { let dac_feedback = channels.read_dac_feedback(channel); let itec = channels.read_itec(channel); - let tec_i = -(itec - Volts(1.5)) / Ohms(0.4); + let tec_i = -(itec - ElectricPotential::new::(1.5)) / ElectricalResistance::new::(0.4); let tec_u_meas = channels.read_tec_u_meas(channel); @@ -175,9 +185,9 @@ fn main() -> ! { channel, state.adc_time, channel, adc_data, channel, adc_calibration[channel].convert_data(adc_data), - vref, dac_feedback, - itec, tec_i, - tec_u_meas, + vref.into_format_args(volt, Abbreviation), dac_feedback.into_format_args(volt, Abbreviation), + itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, Abbreviation), + tec_u_meas.into_format_args(volt, Abbreviation), ); } else { let _ = writeln!(socket, "channel {}: no adc input", channel); @@ -219,7 +229,7 @@ fn main() -> ! { channel, if state.pid_engaged { "engaged" } else { "disengaged" } ); - let _ = writeln!(socket, "- i_set={}", state.dac_value); + let _ = writeln!(socket, "- i_set={}", state.dac_value.into_format_args(volt, Abbreviation)); fn show_pwm_channel(mut socket: S, name: &str, pin: &P) where S: core::fmt::Write, @@ -287,11 +297,11 @@ fn main() -> ! { Command::Pwm { channel, pin: PwmPin::ISet, duty } => { channels.channel_state(channel).pid_engaged = false; leds.g3.off(); - let voltage = Volts(duty); + let voltage = ElectricPotential::new::(duty); channels.set_dac(channel, voltage); let _ = writeln!( socket, "channel {}: PWM duty cycle manually set to {}", - channel, voltage + channel, voltage.into_format_args(volt, Abbreviation), ); } Command::Pwm { channel, pin, duty } => { diff --git a/src/units.rs b/src/units.rs deleted file mode 100644 index a52e07e..0000000 --- a/src/units.rs +++ /dev/null @@ -1,65 +0,0 @@ -use core::{ - fmt, - ops::{Add, Div, Neg, Sub}, -}; - -macro_rules! impl_add_sub { - ($Type: ident) => { - impl Add<$Type> for $Type { - type Output = $Type; - fn add(self, rhs: $Type) -> $Type { - $Type(self.0 + rhs.0) - } - } - - impl Sub<$Type> for $Type { - type Output = $Type; - fn sub(self, rhs: $Type) -> $Type { - $Type(self.0 - rhs.0) - } - } - - impl Neg for $Type { - type Output = $Type; - fn neg(self) -> $Type { - $Type(-self.0) - } - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] -pub struct Volts(pub f64); -impl_add_sub!(Volts); - -impl fmt::Display for Volts { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:.3}V", self.0) - } -} - -impl Div for Volts { - type Output = Amps; - fn div(self, rhs: Ohms) -> Amps { - Amps(self.0 / rhs.0) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] -pub struct Amps(pub f64); -impl_add_sub!(Amps); - -impl fmt::Display for Amps { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:.3}A", self.0) - } -} -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] -pub struct Ohms(pub f64); -impl_add_sub!(Ohms); - -impl fmt::Display for Ohms { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:.3}Ω", self.0) - } -}