Reorganize variables and fns structure
This commit is contained in:
parent
784fc03957
commit
c7d36bc8d5
|
@ -1,5 +1,6 @@
|
||||||
use super::{gpio, sys_timer, usb};
|
use super::{gpio, sys_timer, usb};
|
||||||
use crate::laser_diode::current_sources::*;
|
use crate::laser_diode::current_sources::*;
|
||||||
|
use crate::laser_diode::pd_mon::PdMon;
|
||||||
use crate::thermostat::max1968::{MAX1968};
|
use crate::thermostat::max1968::{MAX1968};
|
||||||
use crate::thermostat::thermostat::Thermostat;
|
use crate::thermostat::thermostat::Thermostat;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
|
@ -38,7 +39,7 @@ pub fn bootup(
|
||||||
|
|
||||||
sys_timer::setup(core_perif.SYST, clocks);
|
sys_timer::setup(core_perif.SYST, clocks);
|
||||||
|
|
||||||
let (_eth_pins, usb, current_source_phy, max1968_phy) = gpio::setup(
|
let (_eth_pins, usb, current_source_phy, pd_mon_phy, max1968_phy) = gpio::setup(
|
||||||
clocks,
|
clocks,
|
||||||
perif.TIM4,
|
perif.TIM4,
|
||||||
perif.GPIOA,
|
perif.GPIOA,
|
||||||
|
@ -65,6 +66,9 @@ pub fn bootup(
|
||||||
laser.setup();
|
laser.setup();
|
||||||
laser.set_current(0.1).unwrap();
|
laser.set_current(0.1).unwrap();
|
||||||
|
|
||||||
|
let mut pd_mon = PdMon::new(pd_mon_phy, perif.ADC2);
|
||||||
|
|
||||||
|
|
||||||
let tec_driver = MAX1968::new(max1968_phy, perif.ADC1);
|
let tec_driver = MAX1968::new(max1968_phy, perif.ADC1);
|
||||||
|
|
||||||
let mut thermostat = Thermostat::new(tec_driver);
|
let mut thermostat = Thermostat::new(tec_driver);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::laser_diode::current_sources::*;
|
use crate::laser_diode::current_sources::*;
|
||||||
|
use crate::laser_diode::pd_mon::PdMonPhy;
|
||||||
use crate::thermostat::ad5680;
|
use crate::thermostat::ad5680;
|
||||||
use crate::thermostat::max1968::{Channel0, MAX1968PinSet, MAX1968Phy, PWM_FREQ_KHZ};
|
use crate::thermostat::max1968::{Channel0, MAX1968PinSet, MAX1968Phy, PWM_FREQ_KHZ};
|
||||||
use fugit::RateExtU32;
|
use fugit::RateExtU32;
|
||||||
|
@ -36,8 +37,8 @@ pub fn setup(
|
||||||
EthernetPins,
|
EthernetPins,
|
||||||
USB,
|
USB,
|
||||||
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
||||||
|
PdMonPhy,
|
||||||
MAX1968Phy<Channel0>,
|
MAX1968Phy<Channel0>,
|
||||||
// photo_diode_phy,
|
|
||||||
// thermostat_phy
|
// thermostat_phy
|
||||||
) {
|
) {
|
||||||
let gpioa = gpioa.split();
|
let gpioa = gpioa.split();
|
||||||
|
@ -86,6 +87,10 @@ pub fn setup(
|
||||||
current_source_short: gpioa.pa4.into_push_pull_output(),
|
current_source_short: gpioa.pa4.into_push_pull_output(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let pd_mon_phy = PdMonPhy {
|
||||||
|
ch0_pin: gpioa.pa3.into_analog()
|
||||||
|
};
|
||||||
|
|
||||||
let pwm_chs = (
|
let pwm_chs = (
|
||||||
gpiob.pb6.into_alternate(),
|
gpiob.pb6.into_alternate(),
|
||||||
gpiob.pb7.into_alternate(),
|
gpiob.pb7.into_alternate(),
|
||||||
|
@ -121,5 +126,5 @@ pub fn setup(
|
||||||
max_i_neg: max_i_neg0,
|
max_i_neg: max_i_neg0,
|
||||||
});
|
});
|
||||||
|
|
||||||
(eth_pins, usb, current_source_phy, max1968_phy)
|
(eth_pins, usb, current_source_phy, pd_mon_phy, max1968_phy)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
gpio::{gpioa::*, gpiob::*, gpiod::*, Alternate, Output, PushPull, PD9},
|
gpio::{gpioa::*, gpiob::*, gpiod::*, Alternate, Output, PushPull, Analog, PD9},
|
||||||
hal::{blocking::spi::Write, digital::v2::OutputPin},
|
hal::{blocking::spi::Write, digital::v2::OutputPin},
|
||||||
pac::SPI2,
|
pac::SPI2,
|
||||||
spi::{NoMiso, Spi, TransferModeNormal},
|
spi::{NoMiso, Spi, TransferModeNormal},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::device::sys_timer::sleep;
|
use crate::device::sys_timer::sleep;
|
||||||
pub trait CurrentSourcePhy {
|
pub trait ChannelPins {
|
||||||
|
type PdMonPin;
|
||||||
type CurrentSourceLdoEn: OutputPin;
|
type CurrentSourceLdoEn: OutputPin;
|
||||||
type CurrentSourceShort: OutputPin;
|
type CurrentSourceShort: OutputPin;
|
||||||
type Max5719Load: OutputPin;
|
type Max5719Load: OutputPin;
|
||||||
|
@ -14,7 +15,7 @@ pub trait CurrentSourcePhy {
|
||||||
type Max5719Spi: Write<u8>;
|
type Max5719Spi: Write<u8>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CurrentSourcePhyConstruct<C: CurrentSourcePhy> {
|
pub struct CurrentSourcePhyConstruct<C: ChannelPins> {
|
||||||
pub max5719_spi: C::Max5719Spi,
|
pub max5719_spi: C::Max5719Spi,
|
||||||
pub max5719_load: C::Max5719Load,
|
pub max5719_load: C::Max5719Load,
|
||||||
pub max5719_cs: C::Max5719Cs,
|
pub max5719_cs: C::Max5719Cs,
|
||||||
|
@ -24,14 +25,15 @@ pub struct CurrentSourcePhyConstruct<C: CurrentSourcePhy> {
|
||||||
pub struct CurrentSourceSettings {
|
pub struct CurrentSourceSettings {
|
||||||
pub output_current: f32,
|
pub output_current: f32,
|
||||||
}
|
}
|
||||||
pub struct CurrentSource<C: CurrentSourcePhy> {
|
pub struct CurrentSource<C: ChannelPins> {
|
||||||
pub phy: CurrentSourcePhyConstruct<C>,
|
pub phy: CurrentSourcePhyConstruct<C>,
|
||||||
pub setting: CurrentSourceSettings,
|
pub setting: CurrentSourceSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CurrentSourcePhyCh0;
|
pub struct Channel0;
|
||||||
|
|
||||||
impl CurrentSourcePhy for CurrentSourcePhyCh0 {
|
impl ChannelPins for Channel0 {
|
||||||
|
type PdMonPin = PA3<Analog>;
|
||||||
type CurrentSourceLdoEn = PD9<Output<PushPull>>;
|
type CurrentSourceLdoEn = PD9<Output<PushPull>>;
|
||||||
type CurrentSourceShort = PA4<Output<PushPull>>;
|
type CurrentSourceShort = PA4<Output<PushPull>>;
|
||||||
type Max5719Load = PB14<Output<PushPull>>;
|
type Max5719Load = PB14<Output<PushPull>>;
|
||||||
|
@ -40,7 +42,7 @@ impl CurrentSourcePhy for CurrentSourcePhyCh0 {
|
||||||
Spi<SPI2, (PB10<Alternate<5>>, NoMiso, PB15<Alternate<5>>), TransferModeNormal>;
|
Spi<SPI2, (PB10<Alternate<5>>, NoMiso, PB15<Alternate<5>>), TransferModeNormal>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: CurrentSourcePhy> CurrentSource<C> {
|
impl<C: ChannelPins> CurrentSource<C> {
|
||||||
pub fn setup(&mut self) {
|
pub fn setup(&mut self) {
|
||||||
let _ = self.phy.max5719_load.set_high();
|
let _ = self.phy.max5719_load.set_high();
|
||||||
let _ = self.phy.max5719_cs.set_high();
|
let _ = self.phy.max5719_cs.set_high();
|
||||||
|
@ -53,7 +55,7 @@ impl<C: CurrentSourcePhy> CurrentSource<C> {
|
||||||
pub fn set_current(
|
pub fn set_current(
|
||||||
&mut self,
|
&mut self,
|
||||||
current: f32,
|
current: f32,
|
||||||
) -> Result<(), <<C as CurrentSourcePhy>::Max5719Spi as Write<u8>>::Error> {
|
) -> Result<(), <<C as ChannelPins>::Max5719Spi as Write<u8>>::Error> {
|
||||||
let _ = self.phy.max5719_load.set_high();
|
let _ = self.phy.max5719_load.set_high();
|
||||||
let _ = self.phy.max5719_cs.set_low();
|
let _ = self.phy.max5719_cs.set_low();
|
||||||
self.setting.output_current = current * 10.0 / 0.75;
|
self.setting.output_current = current * 10.0 / 0.75;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
pub mod current_sources;
|
pub mod current_sources;
|
|
@ -2,7 +2,7 @@ use core::marker::PhantomData;
|
||||||
use core::u16;
|
use core::u16;
|
||||||
|
|
||||||
use crate::thermostat::ad5680;
|
use crate::thermostat::ad5680;
|
||||||
use crate::thermostat::thermostat::{DAC_OUT_V_MAX, TEC_VSEC_BIAS_V};
|
use crate::thermostat::thermostat::Settings;
|
||||||
|
|
||||||
use fugit::KilohertzU32;
|
use fugit::KilohertzU32;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
|
@ -59,8 +59,6 @@ impl ChannelPins for Channel0 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MAX1968Phy<C: ChannelPins> {
|
pub struct MAX1968Phy<C: ChannelPins> {
|
||||||
// state
|
|
||||||
pub center_pt: ElectricPotential,
|
|
||||||
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
||||||
pub shdn: C::ShdnPin,
|
pub shdn: C::ShdnPin,
|
||||||
pub vref_pin: C::VRefPin,
|
pub vref_pin: C::VRefPin,
|
||||||
|
@ -86,12 +84,6 @@ pub struct MAX1968PinSet<C: ChannelPins> {
|
||||||
|
|
||||||
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
|
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
|
||||||
type DacSync = PB4<Output<PushPull>>;
|
type DacSync = PB4<Output<PushPull>>;
|
||||||
pub struct MaxAdcPins {
|
|
||||||
pub dac_vfb: PC0<Analog>,
|
|
||||||
pub vref: PA6<Analog>,
|
|
||||||
pub itec: PB1<Analog>,
|
|
||||||
pub vtec: PB0<Analog>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MAX1968 {
|
pub struct MAX1968 {
|
||||||
// settings
|
// settings
|
||||||
|
@ -115,7 +107,6 @@ pub enum AdcReadTarget {
|
||||||
impl<C: ChannelPins> MAX1968Phy<C> {
|
impl<C: ChannelPins> MAX1968Phy<C> {
|
||||||
pub fn new(pins: MAX1968PinSet<C>) -> Self {
|
pub fn new(pins: MAX1968PinSet<C>) -> Self {
|
||||||
MAX1968Phy {
|
MAX1968Phy {
|
||||||
center_pt: ElectricPotential::new::<volt>(1.5),
|
|
||||||
dac: pins.dac,
|
dac: pins.dac,
|
||||||
shdn: pins.shdn,
|
shdn: pins.shdn,
|
||||||
vref_pin: pins.vref_pin,
|
vref_pin: pins.vref_pin,
|
||||||
|
@ -143,27 +134,17 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn setup(&mut self) {
|
|
||||||
// self.power_down();
|
|
||||||
|
|
||||||
// let vref = self.adc_read(AdcReadTarget::VREF, 2048);
|
|
||||||
// self.set_center_point(vref);
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn power_down(&mut self) {
|
pub fn power_down(&mut self) {
|
||||||
let _ = self.phy.shdn.set_low();
|
self.phy.shdn.set_low();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn power_up(&mut self) {
|
pub fn power_up(&mut self) {
|
||||||
let _ = self.phy.shdn.set_high();
|
self.phy.shdn.set_high();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_center_point(&mut self, value: ElectricPotential) {
|
|
||||||
self.phy.center_pt = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_dac(&mut self, voltage: ElectricPotential) -> ElectricPotential {
|
pub fn set_dac(&mut self, voltage: ElectricPotential, dac_out_v_max: ElectricPotential) -> ElectricPotential {
|
||||||
let value = ((voltage / ElectricPotential::new::<volt>(DAC_OUT_V_MAX)).get::<ratio>()
|
let value = ((voltage / dac_out_v_max).get::<ratio>()
|
||||||
* (ad5680::MAX_VALUE as f64)) as u32;
|
* (ad5680::MAX_VALUE as f64)) as u32;
|
||||||
self.phy.dac.set(value).unwrap();
|
self.phy.dac.set(value).unwrap();
|
||||||
// TODO: Store the set-ed DAC Voltage Value
|
// TODO: Store the set-ed DAC Voltage Value
|
||||||
|
@ -216,25 +197,6 @@ impl MAX1968 {
|
||||||
ElectricPotential::new::<millivolt>(mv as f64)
|
ElectricPotential::new::<millivolt>(mv as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_vref(&mut self) -> ElectricPotential {
|
|
||||||
self.adc_read(AdcReadTarget::VREF, 16)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_dac_vfb(&mut self) -> ElectricPotential {
|
|
||||||
self.adc_read(AdcReadTarget:: DacVfb, 16)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_tec_i(&mut self) -> ElectricCurrent {
|
|
||||||
(self.adc_read(AdcReadTarget::ITec, 1) - self.phy.center_pt)
|
|
||||||
/ ElectricalResistance::new::<ohm>(0.4)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_tec_v(&mut self) -> ElectricPotential {
|
|
||||||
// Fixme: Rev0_2 has Analog Input Polarity Reversed
|
|
||||||
// Remove the -ve sign for Rev0_3
|
|
||||||
-(self.adc_read(AdcReadTarget::VTec, 1) - TEC_VSEC_BIAS_V) * 4.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_pwm(&mut self, pwm_pin: PwmPinsEnum, duty: f64, max_duty: f64) -> f64 {
|
pub fn set_pwm(&mut self, pwm_pin: PwmPinsEnum, duty: f64, max_duty: f64) -> f64 {
|
||||||
fn set<P: hal::PwmPin<Duty = u16>>(pin: &mut P, duty: f64) -> f64 {
|
fn set<P: hal::PwmPin<Duty = u16>>(pin: &mut P, duty: f64) -> f64 {
|
||||||
let max = pin.get_max_duty();
|
let max = pin.get_max_duty();
|
||||||
|
|
|
@ -3,13 +3,15 @@ use crate::sys_timer;
|
||||||
use crate::thermostat::ad5680;
|
use crate::thermostat::ad5680;
|
||||||
use crate::thermostat::max1968::{MAX1968, AdcReadTarget, PwmPinsEnum};
|
use crate::thermostat::max1968::{MAX1968, AdcReadTarget, PwmPinsEnum};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use miniconf::serde::de::value;
|
||||||
use uom::si::{
|
use uom::si::{
|
||||||
electric_current::ampere,
|
electric_current::ampere,
|
||||||
electric_potential::{millivolt, volt},
|
electric_potential::volt,
|
||||||
electrical_resistance::ohm,
|
electrical_resistance::ohm,
|
||||||
f64::{ElectricCurrent, ElectricPotential, ElectricalResistance},
|
f64::{ElectricCurrent, ElectricPotential, ElectricalResistance},
|
||||||
ratio::ratio,
|
ratio::ratio,
|
||||||
};
|
};
|
||||||
|
use miniconf::Miniconf;
|
||||||
|
|
||||||
pub const R_SENSE: ElectricalResistance = ElectricalResistance {
|
pub const R_SENSE: ElectricalResistance = ElectricalResistance {
|
||||||
dimension: PhantomData,
|
dimension: PhantomData,
|
||||||
|
@ -17,72 +19,99 @@ pub const R_SENSE: ElectricalResistance = ElectricalResistance {
|
||||||
value: 0.05,
|
value: 0.05,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rev 0_2: DAC Chip connects 3V3 reference voltage and thus provide 0-3.3V output range
|
#[derive(Clone, Debug, Miniconf)]
|
||||||
// TODO: Rev 0_3: DAC Chip connects 3V3 reference voltage,
|
pub struct Settings {
|
||||||
// which is then passed through a resistor divider to provide 0-3V output range
|
pub center_pt: ElectricPotential,
|
||||||
pub const DAC_OUT_V_MAX: f64 = 3.3;
|
pub max_v_set: ElectricPotential,
|
||||||
pub const TEC_VSEC_BIAS_V: ElectricPotential = ElectricPotential {
|
pub max_i_pos_set: ElectricCurrent,
|
||||||
dimension: PhantomData,
|
pub max_i_neg_set: ElectricCurrent,
|
||||||
units: PhantomData,
|
pub i_set: ElectricCurrent,
|
||||||
value: 1.65,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Kirdy Design Specs:
|
impl Settings{
|
||||||
// MaxV = 5.0V
|
// FixMe: Rev0_2 is 3.3V max while Rev0_3 is 3.0V max
|
||||||
// MAX Current = +- 1.0A
|
pub const DAC_OUT_V_MAX: ElectricPotential = ElectricPotential {
|
||||||
const MAX_V_DUTY_TO_CURRENT_RATE: ElectricPotential = ElectricPotential {
|
dimension: PhantomData,
|
||||||
dimension: PhantomData,
|
units: PhantomData,
|
||||||
units: PhantomData,
|
value: 3.3,
|
||||||
value: 4.0 * 3.3,
|
};
|
||||||
};
|
pub const TEC_VSEC_BIAS_V: ElectricPotential = ElectricPotential {
|
||||||
pub const MAX_V_MAX: ElectricPotential = ElectricPotential {
|
dimension: PhantomData,
|
||||||
dimension: PhantomData,
|
units: PhantomData,
|
||||||
units: PhantomData,
|
value: 1.65,
|
||||||
value: 5.0,
|
};
|
||||||
};
|
|
||||||
const MAX_V_DUTY_MAX: f64 = MAX_V_MAX.value / MAX_V_DUTY_TO_CURRENT_RATE.value;
|
// Kirdy Design Specs:
|
||||||
const MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE: ElectricCurrent = ElectricCurrent {
|
// MaxV = 5.0V
|
||||||
dimension: PhantomData,
|
// MAX Current = +- 1.0A
|
||||||
units: PhantomData,
|
const MAX_V_DUTY_TO_CURRENT_RATE: ElectricPotential = ElectricPotential {
|
||||||
value: 1.0 / (10.0 * R_SENSE.value / 3.3),
|
dimension: PhantomData,
|
||||||
};
|
units: PhantomData,
|
||||||
pub const MAX_I_POS_CURRENT: ElectricCurrent = ElectricCurrent {
|
value: 4.0 * 3.3,
|
||||||
dimension: PhantomData,
|
};
|
||||||
units: PhantomData,
|
pub const MAX_V_MAX: ElectricPotential = ElectricPotential {
|
||||||
value: 1.0,
|
dimension: PhantomData,
|
||||||
};
|
units: PhantomData,
|
||||||
pub const MAX_I_NEG_CURRENT: ElectricCurrent = ElectricCurrent {
|
value: 5.0,
|
||||||
dimension: PhantomData,
|
};
|
||||||
units: PhantomData,
|
const MAX_V_DUTY_MAX: f64 = Settings::MAX_V_MAX.value / Settings::MAX_V_DUTY_TO_CURRENT_RATE.value;
|
||||||
value: 1.0,
|
const MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE: ElectricCurrent = ElectricCurrent {
|
||||||
};
|
dimension: PhantomData,
|
||||||
// .get::<ratio>() is not implemented for const
|
units: PhantomData,
|
||||||
const MAX_I_POS_DUTY_MAX: f64 = MAX_I_POS_CURRENT.value / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
value: 1.0 / (10.0 * R_SENSE.value / 3.3),
|
||||||
const MAX_I_NEG_DUTY_MAX: f64 = MAX_I_NEG_CURRENT.value / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
};
|
||||||
|
pub const MAX_I_POS_CURRENT: ElectricCurrent = ElectricCurrent {
|
||||||
|
dimension: PhantomData,
|
||||||
|
units: PhantomData,
|
||||||
|
value: 1.0,
|
||||||
|
};
|
||||||
|
pub const MAX_I_NEG_CURRENT: ElectricCurrent = ElectricCurrent {
|
||||||
|
dimension: PhantomData,
|
||||||
|
units: PhantomData,
|
||||||
|
value: 1.0,
|
||||||
|
};
|
||||||
|
// .get::<ratio>() is not implemented for const
|
||||||
|
const MAX_I_POS_DUTY_MAX: f64 = Settings::MAX_I_POS_CURRENT.value / Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
||||||
|
const MAX_I_NEG_DUTY_MAX: f64 = Settings::MAX_I_NEG_CURRENT.value / Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
center_pt: ElectricPotential::new::<volt>(1.5),
|
||||||
|
max_v_set: ElectricPotential::new::<volt>(5.0),
|
||||||
|
max_i_pos_set: ElectricCurrent::new::<ampere>(1.0),
|
||||||
|
max_i_neg_set: ElectricCurrent::new::<ampere>(1.0),
|
||||||
|
i_set: ElectricCurrent::new::<ampere>(0.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Thermostat {
|
pub struct Thermostat {
|
||||||
max1968: MAX1968,
|
max1968: MAX1968,
|
||||||
|
pub tec_setting: Settings,
|
||||||
// TADC
|
// TADC
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Thermostat{
|
impl Thermostat{
|
||||||
pub fn new (max1968: MAX1968) -> Self {
|
pub fn new (max1968: MAX1968) -> Self {
|
||||||
Thermostat{
|
Thermostat{
|
||||||
max1968
|
max1968: max1968,
|
||||||
|
tec_setting: Settings::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn setup(&mut self) {
|
pub fn setup(&mut self) {
|
||||||
self.power_down();
|
self.power_up();
|
||||||
|
|
||||||
|
self.tec_setting = Settings::default();
|
||||||
|
|
||||||
self.calibrate_dac_value();
|
self.calibrate_dac_value();
|
||||||
|
|
||||||
self.set_i(ElectricCurrent::new::<ampere>(0.0));
|
self.set_i(self.tec_setting.i_set);
|
||||||
|
|
||||||
self.set_max_v(ElectricPotential::new::<volt>(5.0));
|
self.set_max_v(self.tec_setting.max_v_set);
|
||||||
self.set_max_i_pos(ElectricCurrent::new::<ampere>(1.0));
|
self.set_max_i_pos(self.tec_setting.max_i_pos_set);
|
||||||
self.set_max_i_neg(ElectricCurrent::new::<ampere>(1.0));
|
self.set_max_i_neg(self.tec_setting.max_i_neg_set);
|
||||||
|
|
||||||
self.max1968.power_up();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn power_up(&mut self){
|
pub fn power_up(&mut self){
|
||||||
|
@ -93,29 +122,56 @@ impl Thermostat{
|
||||||
self.max1968.power_down();
|
self.max1968.power_down();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_center_pt(&mut self, value: ElectricPotential){
|
||||||
|
info!("set center pt: {:?}", value);
|
||||||
|
self.tec_setting.center_pt = value;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_i(&mut self, i_tec: ElectricCurrent) -> ElectricCurrent {
|
pub fn set_i(&mut self, i_tec: ElectricCurrent) -> ElectricCurrent {
|
||||||
let voltage = i_tec * 10.0 * R_SENSE + self.max1968.phy.center_pt;
|
let voltage = i_tec * 10.0 * R_SENSE + self.tec_setting.center_pt;
|
||||||
let voltage = self.max1968.set_dac(voltage);
|
let voltage = self.max1968.set_dac(voltage, Settings::DAC_OUT_V_MAX);
|
||||||
let i_tec = (voltage - self.max1968.phy.center_pt) / (10.0 * R_SENSE);
|
self.tec_setting.i_set = (voltage - self.tec_setting.center_pt) / (10.0 * R_SENSE);
|
||||||
i_tec
|
self.tec_setting.i_set
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_v(&mut self, max_v: ElectricPotential) -> ElectricPotential {
|
pub fn set_max_v(&mut self, max_v: ElectricPotential) -> ElectricPotential {
|
||||||
let duty = (max_v / MAX_V_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
let duty = (max_v / Settings::MAX_V_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxV, duty, MAX_V_DUTY_MAX);
|
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxV, duty, Settings::MAX_V_DUTY_MAX);
|
||||||
duty * MAX_V_DUTY_TO_CURRENT_RATE
|
self.tec_setting.max_v_set = duty * Settings::MAX_V_DUTY_TO_CURRENT_RATE;
|
||||||
|
self.tec_setting.max_v_set
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_i_pos(&mut self, max_i_pos: ElectricCurrent) -> ElectricCurrent {
|
pub fn set_max_i_pos(&mut self, max_i_pos: ElectricCurrent) -> ElectricCurrent {
|
||||||
let duty = (max_i_pos / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
let duty = (max_i_pos / Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxPosI, duty, MAX_I_POS_DUTY_MAX);
|
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxPosI, duty, Settings::MAX_I_POS_DUTY_MAX);
|
||||||
duty * MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE
|
self.tec_setting.max_i_pos_set = duty * Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE;
|
||||||
|
self.tec_setting.max_i_pos_set
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_i_neg(&mut self, max_i_neg: ElectricCurrent) -> ElectricCurrent {
|
pub fn set_max_i_neg(&mut self, max_i_neg: ElectricCurrent) -> ElectricCurrent {
|
||||||
let duty = (max_i_neg / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
let duty = (max_i_neg / Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxNegI, duty, MAX_I_NEG_DUTY_MAX);
|
let duty = self.max1968.set_pwm(PwmPinsEnum::MaxNegI, duty, Settings::MAX_I_NEG_DUTY_MAX);
|
||||||
duty * MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE
|
self.tec_setting.max_i_neg_set = duty * Settings::MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE;
|
||||||
|
self.tec_setting.max_i_neg_set
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_dac_vfb(&mut self) -> ElectricPotential {
|
||||||
|
self.max1968.adc_read(AdcReadTarget::DacVfb, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_vref(&mut self) -> ElectricPotential {
|
||||||
|
self.max1968.adc_read(AdcReadTarget::VREF, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tec_i(&mut self) -> ElectricCurrent {
|
||||||
|
let vref = self.get_vref();
|
||||||
|
(self.max1968.adc_read(AdcReadTarget::ITec, 16) - vref) / ElectricalResistance::new::<ohm>(0.4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tec_v(&mut self) -> ElectricPotential {
|
||||||
|
// Fixme: Rev0_2 has Analog Input Polarity Reversed
|
||||||
|
// Remove the -ve sign for Rev0_3
|
||||||
|
-(self.max1968.adc_read(AdcReadTarget::VTec, 16) - Settings::TEC_VSEC_BIAS_V) * 4.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calibrates the DAC output to match vref of the MAX driver to reduce zero-current offset of the MAX driver output.
|
/// Calibrates the DAC output to match vref of the MAX driver to reduce zero-current offset of the MAX driver output.
|
||||||
|
@ -135,19 +191,14 @@ impl Thermostat{
|
||||||
/// VREF measurement can introduce significant noise at the current output, degrading the stabilily performance of the
|
/// VREF measurement can introduce significant noise at the current output, degrading the stabilily performance of the
|
||||||
/// thermostat.
|
/// thermostat.
|
||||||
pub fn calibrate_dac_value(&mut self) {
|
pub fn calibrate_dac_value(&mut self) {
|
||||||
let samples = 50;
|
let target_voltage = self.max1968.adc_read(AdcReadTarget::VREF, 64);
|
||||||
let mut target_voltage = ElectricPotential::new::<volt>(0.0);
|
|
||||||
for _ in 0..samples {
|
|
||||||
target_voltage = target_voltage + self.max1968.adc_read(AdcReadTarget::VREF, 1);
|
|
||||||
}
|
|
||||||
target_voltage = target_voltage / samples as f64;
|
|
||||||
let mut start_value = 1;
|
let mut start_value = 1;
|
||||||
let mut best_error = ElectricPotential::new::<volt>(100.0);
|
let mut best_error = ElectricPotential::new::<volt>(100.0);
|
||||||
for step in (0..18).rev() {
|
for step in (0..18).rev() {
|
||||||
info!("Step: {} Calibrating", step);
|
info!("Step: {} Calibrating", step);
|
||||||
let mut prev_value = start_value;
|
let mut prev_value = start_value;
|
||||||
for value in (start_value..=ad5680::MAX_VALUE).step_by(1 << step) {
|
for value in (start_value..=ad5680::MAX_VALUE).step_by(1 << step) {
|
||||||
//info!("Calibrating");
|
info!("Calibrating: Value: {:?}", value);
|
||||||
self.max1968.phy.dac.set(value).unwrap();
|
self.max1968.phy.dac.set(value).unwrap();
|
||||||
sys_timer::sleep(5);
|
sys_timer::sleep(5);
|
||||||
|
|
||||||
|
@ -159,12 +210,13 @@ impl Thermostat{
|
||||||
best_error = error;
|
best_error = error;
|
||||||
start_value = prev_value;
|
start_value = prev_value;
|
||||||
|
|
||||||
let vref = (value as f64 / ad5680::MAX_VALUE as f64) * ElectricPotential::new::<volt>(DAC_OUT_V_MAX);
|
let vref = (value as f64 / ad5680::MAX_VALUE as f64) * Settings::DAC_OUT_V_MAX;
|
||||||
self.max1968.set_center_point(vref);
|
self.set_center_pt(vref);
|
||||||
}
|
}
|
||||||
prev_value = value;
|
prev_value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
info!("Best Error: {:?}", best_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue