forked from M-Labs/kirdy
Rewrite MAX1968 Driver Generically
- Set variable to proper types(Rate, ElectricalPotential, etc) - Declare const MAX_I_POS, MAX_I_NEG, MAX_V conversion
This commit is contained in:
parent
0179e7641a
commit
4cf7b7fdf9
|
@ -1,6 +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::{thermostat::max1968::MAX1968}
|
use crate::thermostat::max1968::MAX1968;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
use log::info;
|
use log::info;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
|
@ -10,17 +10,17 @@ use stm32f4xx_hal::{
|
||||||
watchdog::IndependentWatchdog,
|
watchdog::IndependentWatchdog,
|
||||||
};
|
};
|
||||||
|
|
||||||
use uom::si::{
|
use uom::si::{electric_current::ampere, f64::ElectricCurrent};
|
||||||
electric_current::ampere,
|
|
||||||
f64::ElectricCurrent,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "semihosting"))]
|
#[cfg(not(feature = "semihosting"))]
|
||||||
const WATCHDOG_PERIOD: u32 = 1000;
|
const WATCHDOG_PERIOD: u32 = 1000;
|
||||||
#[cfg(feature = "semihosting")]
|
#[cfg(feature = "semihosting")]
|
||||||
const WATCHDOG_PERIOD: u32 = 30000;
|
const WATCHDOG_PERIOD: u32 = 30000;
|
||||||
|
|
||||||
pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> IndependentWatchdog {
|
pub fn bootup(
|
||||||
|
mut core_perif: CorePeripherals,
|
||||||
|
perif: Peripherals,
|
||||||
|
) -> (IndependentWatchdog, MAX1968) {
|
||||||
core_perif.SCB.enable_icache();
|
core_perif.SCB.enable_icache();
|
||||||
core_perif.SCB.enable_dcache(&mut core_perif.CPUID);
|
core_perif.SCB.enable_dcache(&mut core_perif.CPUID);
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> Independen
|
||||||
laser.set_current(0.1).unwrap();
|
laser.set_current(0.1).unwrap();
|
||||||
|
|
||||||
let mut tec_driver = MAX1968::new(max1968_phy, perif.ADC1);
|
let mut tec_driver = MAX1968::new(max1968_phy, perif.ADC1);
|
||||||
|
|
||||||
tec_driver.setup();
|
tec_driver.setup();
|
||||||
|
|
||||||
tec_driver.set_i(ElectricCurrent::new::<ampere>(1.0));
|
tec_driver.set_i(ElectricCurrent::new::<ampere>(1.0));
|
||||||
|
@ -77,5 +78,5 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> Independen
|
||||||
|
|
||||||
info!("Kirdy setup complete");
|
info!("Kirdy setup complete");
|
||||||
|
|
||||||
wd
|
(wd, tec_driver)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::laser_diode::current_sources::*;
|
use crate::laser_diode::current_sources::*;
|
||||||
use crate::thermostat::ad5680;
|
use crate::thermostat::ad5680;
|
||||||
use crate::thermostat::max1968::{MAX1968PinSet, PWM_FREQ_KHZ};
|
use crate::thermostat::max1968::{Channel0, MAX1968PinSet, MAX1968Phy, PWM_FREQ_KHZ};
|
||||||
use fugit::RateExtU32;
|
use fugit::RateExtU32;
|
||||||
use stm32_eth::EthPins;
|
use stm32_eth::EthPins;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
|
@ -36,7 +36,7 @@ pub fn setup(
|
||||||
EthernetPins,
|
EthernetPins,
|
||||||
USB,
|
USB,
|
||||||
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
||||||
MAX1968PinSet,
|
MAX1968Phy<Channel0>,
|
||||||
// photo_diode_phy,
|
// photo_diode_phy,
|
||||||
// thermostat_phy
|
// thermostat_phy
|
||||||
) {
|
) {
|
||||||
|
@ -92,30 +92,32 @@ pub fn setup(
|
||||||
gpiob.pb8.into_alternate(),
|
gpiob.pb8.into_alternate(),
|
||||||
);
|
);
|
||||||
let (max_i_neg0, max_v0, max_i_pos0) =
|
let (max_i_neg0, max_v0, max_i_pos0) =
|
||||||
tim4.pwm_hz(pwm_chs, PWM_FREQ_KHZ.kHz(), &clocks).split();
|
tim4.pwm_hz(pwm_chs, PWM_FREQ_KHZ.convert(), &clocks).split();
|
||||||
|
|
||||||
let max1968_phy = MAX1968PinSet {
|
let max1968_phy = MAX1968Phy::new(MAX1968PinSet {
|
||||||
dac_spi: Spi::new(
|
dac: ad5680::Dac::new(
|
||||||
spi1,
|
Spi::new(
|
||||||
(
|
spi1,
|
||||||
gpiob.pb3.into_alternate(),
|
(
|
||||||
NoMiso {},
|
gpiob.pb3.into_alternate(),
|
||||||
gpiob.pb5.into_alternate(),
|
NoMiso {},
|
||||||
|
gpiob.pb5.into_alternate(),
|
||||||
|
),
|
||||||
|
ad5680::SPI_MODE,
|
||||||
|
ad5680::SPI_CLOCK_MHZ.convert(),
|
||||||
|
&clocks,
|
||||||
),
|
),
|
||||||
ad5680::SPI_MODE,
|
gpiob.pb4.into_push_pull_output(),
|
||||||
ad5680::SPI_CLOCK_MHZ.MHz(),
|
|
||||||
&clocks,
|
|
||||||
),
|
),
|
||||||
dac_sync: gpiob.pb4.into_push_pull_output(),
|
|
||||||
dac_vfb: gpioc.pc0.into_analog(),
|
|
||||||
shdn: gpioa.pa5.into_push_pull_output(),
|
shdn: gpioa.pa5.into_push_pull_output(),
|
||||||
vref: gpioa.pa6.into_analog(),
|
vref_pin: gpioa.pa6.into_analog(),
|
||||||
vtec: gpiob.pb0.into_analog(),
|
itec_pin: gpiob.pb1.into_analog(),
|
||||||
itec: gpiob.pb1.into_analog(),
|
dac_feedback_pin: gpioc.pc0.into_analog(),
|
||||||
max_v0: max_v0,
|
vtec_pin: gpiob.pb0.into_analog(),
|
||||||
max_i_pos0: max_i_pos0,
|
max_v: max_v0,
|
||||||
max_i_neg0: max_i_neg0,
|
max_i_pos: max_i_pos0,
|
||||||
};
|
max_i_neg: max_i_neg0,
|
||||||
|
});
|
||||||
|
|
||||||
(eth_pins, usb, current_source_phy, max1968_phy)
|
(eth_pins, usb, current_source_phy, max1968_phy)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ fn main() -> ! {
|
||||||
let core_perif = CorePeripherals::take().unwrap();
|
let core_perif = CorePeripherals::take().unwrap();
|
||||||
let perif = Peripherals::take().unwrap();
|
let perif = Peripherals::take().unwrap();
|
||||||
|
|
||||||
let mut wd = bootup(core_perif, perif);
|
let (mut wd, mut tec_driver) = bootup(core_perif, perif);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
wd.feed();
|
wd.feed();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::device::sys_timer::sleep;
|
use crate::device::sys_timer::sleep;
|
||||||
|
use fugit::MegahertzU32;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
|
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
|
||||||
spi,
|
spi,
|
||||||
|
@ -9,7 +10,7 @@ pub const SPI_MODE: spi::Mode = spi::Mode {
|
||||||
polarity: spi::Polarity::IdleLow,
|
polarity: spi::Polarity::IdleLow,
|
||||||
phase: spi::Phase::CaptureOnSecondTransition,
|
phase: spi::Phase::CaptureOnSecondTransition,
|
||||||
};
|
};
|
||||||
pub const SPI_CLOCK_MHZ: u32 = 30;
|
pub const SPI_CLOCK_MHZ: MegahertzU32 = MegahertzU32::from_raw(30);
|
||||||
|
|
||||||
pub const MAX_VALUE: u32 = 0x3FFFF;
|
pub const MAX_VALUE: u32 = 0x3FFFF;
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::u16;
|
use core::u16;
|
||||||
|
|
||||||
use crate::thermostat::ad5680;
|
use crate::thermostat::ad5680;
|
||||||
|
|
||||||
use fugit::RateExtU32;
|
use fugit::KilohertzU32;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
adc::{
|
adc::{
|
||||||
config::{self, AdcConfig},
|
config::{self, AdcConfig},
|
||||||
Adc,
|
Adc,
|
||||||
},
|
},
|
||||||
gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull},
|
gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull},
|
||||||
hal,
|
hal::{self, blocking::spi::Transfer, digital::v2::OutputPin},
|
||||||
pac::{ADC1, SPI1, TIM4},
|
pac::{ADC1, SPI1, TIM4},
|
||||||
rcc::Clocks,
|
rcc::Clocks,
|
||||||
spi::{NoMiso, Spi, TransferModeNormal},
|
spi::{NoMiso, Spi, TransferModeNormal},
|
||||||
|
@ -24,29 +25,108 @@ use uom::si::{
|
||||||
ratio::ratio,
|
ratio::ratio,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PWM_FREQ_KHZ: u32 = 20;
|
pub const PWM_FREQ_KHZ: KilohertzU32 = KilohertzU32::from_raw(20);
|
||||||
pub const R_SENSE: f64 = 0.05;
|
pub const R_SENSE: ElectricalResistance = ElectricalResistance {
|
||||||
|
dimension: PhantomData,
|
||||||
|
units: PhantomData,
|
||||||
|
value: 0.05,
|
||||||
|
};
|
||||||
|
|
||||||
// Rev 0_2: DAC Chip connects 3V3 reference voltage and thus provide 0-3.3V output range
|
// Rev 0_2: DAC Chip connects 3V3 reference voltage and thus provide 0-3.3V output range
|
||||||
// TODO: Rev 0_3: DAC Chip connects 3V3 reference voltage,
|
// TODO: Rev 0_3: DAC Chip connects 3V3 reference voltage,
|
||||||
// which is then passed through a resistor divider to provide 0-3V output range
|
// which is then passed through a resistor divider to provide 0-3V output range
|
||||||
const DAC_OUT_V_MAX: f64 = 3.3;
|
const DAC_OUT_V_MAX: f64 = 3.3;
|
||||||
const TEC_VSEC_BIAS_V: f64 = 1.65;
|
const TEC_VSEC_BIAS_V: ElectricPotential = ElectricPotential {
|
||||||
const MAX_V_DUTY_MAX: f64 = 1.5 / 3.3;
|
dimension: PhantomData,
|
||||||
const MAX_I_POS_DUTY_MAX: f64 = 1.5 / 3.3;
|
units: PhantomData,
|
||||||
const MAX_I_NEG_DUTY_MAX: f64 = 1.5 / 3.3;
|
value: 1.65,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct MAX1968PinSet {
|
// Kirdy Design Specs:
|
||||||
pub dac_spi: DacSpi,
|
// MaxV = 5.0V
|
||||||
pub dac_sync: DacSync,
|
// MAX Current = +- 1.0A
|
||||||
pub shdn: PA5<Output<PushPull>>,
|
const MAX_V_DUTY_TO_CURRENT_RATE: ElectricPotential = ElectricPotential {
|
||||||
pub dac_vfb: PC0<Analog>,
|
dimension: PhantomData,
|
||||||
pub vref: PA6<Analog>,
|
units: PhantomData,
|
||||||
pub vtec: PB0<Analog>,
|
value: 4.0 * 3.3,
|
||||||
pub itec: PB1<Analog>,
|
};
|
||||||
pub max_v0: PwmChannel<TIM4, 1>,
|
pub const MAX_V_MAX: ElectricPotential = ElectricPotential {
|
||||||
pub max_i_pos0: PwmChannel<TIM4, 2>,
|
dimension: PhantomData,
|
||||||
pub max_i_neg0: PwmChannel<TIM4, 0>,
|
units: PhantomData,
|
||||||
|
value: 5.0,
|
||||||
|
};
|
||||||
|
const MAX_V_DUTY_MAX: f64 = MAX_V_MAX.value / MAX_V_DUTY_TO_CURRENT_RATE.value;
|
||||||
|
const MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE: ElectricCurrent = ElectricCurrent {
|
||||||
|
dimension: PhantomData,
|
||||||
|
units: PhantomData,
|
||||||
|
value: 1.0 / (10.0 * R_SENSE.value / 3.3),
|
||||||
|
};
|
||||||
|
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 = MAX_I_POS_CURRENT.value / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
||||||
|
const MAX_I_NEG_DUTY_MAX: f64 = MAX_I_NEG_CURRENT.value / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE.value;
|
||||||
|
|
||||||
|
pub trait ChannelPins {
|
||||||
|
type DacSpi: Transfer<u8>;
|
||||||
|
type DacSync: OutputPin;
|
||||||
|
type ShdnPin: OutputPin;
|
||||||
|
type VRefPin;
|
||||||
|
type ItecPin;
|
||||||
|
type DacFeedbackPin;
|
||||||
|
type VTecPin;
|
||||||
|
type MaxVPin;
|
||||||
|
type MaxIPosPin;
|
||||||
|
type MAXINegPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Channel0;
|
||||||
|
|
||||||
|
impl ChannelPins for Channel0 {
|
||||||
|
type DacSpi = DacSpi;
|
||||||
|
type DacSync = DacSync;
|
||||||
|
type ShdnPin = PA5<Output<PushPull>>;
|
||||||
|
type VRefPin = PA6<Analog>;
|
||||||
|
type ItecPin = PB1<Analog>;
|
||||||
|
type DacFeedbackPin = PC0<Analog>;
|
||||||
|
type VTecPin = PB0<Analog>;
|
||||||
|
type MaxVPin = PwmChannel<TIM4, 1>;
|
||||||
|
type MaxIPosPin = PwmChannel<TIM4, 2>;
|
||||||
|
type MAXINegPin = PwmChannel<TIM4, 0>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MAX1968Phy<C: ChannelPins> {
|
||||||
|
// state
|
||||||
|
pub center_pt: ElectricPotential,
|
||||||
|
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
||||||
|
pub shdn: C::ShdnPin,
|
||||||
|
pub vref_pin: C::VRefPin,
|
||||||
|
pub itec_pin: C::ItecPin,
|
||||||
|
pub dac_feedback_pin: C::DacFeedbackPin,
|
||||||
|
pub vtec_pin: C::VTecPin,
|
||||||
|
pub max_v: C::MaxVPin,
|
||||||
|
pub max_i_pos: C::MaxIPosPin,
|
||||||
|
pub max_i_neg: C::MAXINegPin,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MAX1968PinSet<C: ChannelPins> {
|
||||||
|
pub dac: ad5680::Dac<C::DacSpi, C::DacSync>,
|
||||||
|
pub shdn: C::ShdnPin,
|
||||||
|
pub vref_pin: C::VRefPin,
|
||||||
|
pub itec_pin: C::ItecPin,
|
||||||
|
pub dac_feedback_pin: C::DacFeedbackPin,
|
||||||
|
pub vtec_pin: C::VTecPin,
|
||||||
|
pub max_v: C::MaxVPin,
|
||||||
|
pub max_i_pos: C::MaxIPosPin,
|
||||||
|
pub max_i_neg: C::MAXINegPin,
|
||||||
}
|
}
|
||||||
|
|
||||||
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
|
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
|
||||||
|
@ -59,13 +139,11 @@ pub struct MaxAdcPins {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MAX1968 {
|
pub struct MAX1968 {
|
||||||
pub center_pt: ElectricPotential, // To be moved to a miniconf crate's struct
|
// settings
|
||||||
pub adc: Adc<ADC1>,
|
pub phy: MAX1968Phy<Channel0>,
|
||||||
pub dac: ad5680::Dac<DacSpi, DacSync>,
|
pub pins_adc: Adc<ADC1>,
|
||||||
pub shdn: PA5<Output<PushPull>>,
|
|
||||||
pub adc_pins: MaxAdcPins,
|
|
||||||
pub pwm_pins: PwmPins,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PwmPins {
|
pub struct PwmPins {
|
||||||
pub max_v0: PwmChannel<TIM4, 1>,
|
pub max_v0: PwmChannel<TIM4, 1>,
|
||||||
pub max_i_pos0: PwmChannel<TIM4, 2>,
|
pub max_i_pos0: PwmChannel<TIM4, 2>,
|
||||||
|
@ -86,8 +164,6 @@ pub enum AdcReadTarget {
|
||||||
|
|
||||||
impl PwmPins {
|
impl PwmPins {
|
||||||
fn setup(clocks: Clocks, tim4: TIM4, max_v0: PB7, max_i_pos0: PB8, max_i_neg0: PB6) -> PwmPins {
|
fn setup(clocks: Clocks, tim4: TIM4, max_v0: PB7, max_i_pos0: PB8, max_i_neg0: PB6) -> PwmPins {
|
||||||
let freq = 20.kHz();
|
|
||||||
|
|
||||||
fn init_pwm_pin<P: hal::PwmPin<Duty = u16>>(pin: &mut P) {
|
fn init_pwm_pin<P: hal::PwmPin<Duty = u16>>(pin: &mut P) {
|
||||||
pin.set_duty(0);
|
pin.set_duty(0);
|
||||||
pin.enable();
|
pin.enable();
|
||||||
|
@ -100,7 +176,7 @@ impl PwmPins {
|
||||||
);
|
);
|
||||||
|
|
||||||
let (mut max_i_neg0, mut max_v0, mut max_i_pos0) =
|
let (mut max_i_neg0, mut max_v0, mut max_i_pos0) =
|
||||||
tim4.pwm_hz(channels, freq, &clocks).split();
|
tim4.pwm_hz(channels, PWM_FREQ_KHZ.convert(), &clocks).split();
|
||||||
|
|
||||||
init_pwm_pin(&mut max_v0);
|
init_pwm_pin(&mut max_v0);
|
||||||
init_pwm_pin(&mut max_i_neg0);
|
init_pwm_pin(&mut max_i_neg0);
|
||||||
|
@ -114,10 +190,25 @@ impl PwmPins {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MAX1968 {
|
impl<C: ChannelPins> MAX1968Phy<C> {
|
||||||
pub fn new(pins: MAX1968PinSet, adc1: ADC1) -> Self {
|
pub fn new(pins: MAX1968PinSet<C>) -> Self {
|
||||||
let dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
|
MAX1968Phy {
|
||||||
|
center_pt: ElectricPotential::new::<volt>(1.5),
|
||||||
|
dac: pins.dac,
|
||||||
|
shdn: pins.shdn,
|
||||||
|
vref_pin: pins.vref_pin,
|
||||||
|
itec_pin: pins.itec_pin,
|
||||||
|
dac_feedback_pin: pins.dac_feedback_pin,
|
||||||
|
vtec_pin: pins.vtec_pin,
|
||||||
|
max_v: pins.max_v,
|
||||||
|
max_i_pos: pins.max_i_pos,
|
||||||
|
max_i_neg: pins.max_i_neg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MAX1968 {
|
||||||
|
pub fn new(phy_ch0: MAX1968Phy<Channel0>, adc1: ADC1) -> Self {
|
||||||
let config = AdcConfig::default()
|
let config = AdcConfig::default()
|
||||||
.clock(config::Clock::Pclk2_div_2)
|
.clock(config::Clock::Pclk2_div_2)
|
||||||
.default_sample_time(config::SampleTime::Cycles_480);
|
.default_sample_time(config::SampleTime::Cycles_480);
|
||||||
|
@ -125,25 +216,12 @@ impl MAX1968 {
|
||||||
let pins_adc = Adc::adc1(adc1, true, config);
|
let pins_adc = Adc::adc1(adc1, true, config);
|
||||||
|
|
||||||
MAX1968 {
|
MAX1968 {
|
||||||
center_pt: ElectricPotential::new::<millivolt>(1500.0),
|
phy: phy_ch0,
|
||||||
adc: pins_adc,
|
pins_adc: pins_adc,
|
||||||
dac: dac,
|
|
||||||
shdn: pins.shdn,
|
|
||||||
adc_pins: MaxAdcPins {
|
|
||||||
dac_vfb: pins.dac_vfb,
|
|
||||||
vref: pins.vref,
|
|
||||||
itec: pins.itec,
|
|
||||||
vtec: pins.vtec,
|
|
||||||
},
|
|
||||||
pwm_pins: PwmPins {
|
|
||||||
max_v0: pins.max_v0,
|
|
||||||
max_i_pos0: pins.max_i_pos0,
|
|
||||||
max_i_neg0: pins.max_i_neg0,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(&mut self){
|
pub fn setup(&mut self) {
|
||||||
self.power_down();
|
self.power_down();
|
||||||
|
|
||||||
let vref = self.adc_read(AdcReadTarget::VREF, 2048);
|
let vref = self.adc_read(AdcReadTarget::VREF, 2048);
|
||||||
|
@ -158,28 +236,28 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn power_down(&mut self) {
|
pub fn power_down(&mut self) {
|
||||||
let _ = self.shdn.set_low();
|
let _ = self.phy.shdn.set_low();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn power_up(&mut self) {
|
pub fn power_up(&mut self) {
|
||||||
let _ = self.shdn.set_high();
|
let _ = self.phy.shdn.set_high();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_center_point(&mut self, value: ElectricPotential) {
|
pub fn set_center_point(&mut self, value: ElectricPotential) {
|
||||||
self.center_pt = value;
|
self.phy.center_pt = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dac(&mut self, voltage: ElectricPotential) -> ElectricPotential {
|
fn set_dac(&mut self, voltage: ElectricPotential) -> ElectricPotential {
|
||||||
let value = ((voltage / ElectricPotential::new::<volt>(DAC_OUT_V_MAX)).get::<ratio>()
|
let value = ((voltage / ElectricPotential::new::<volt>(DAC_OUT_V_MAX)).get::<ratio>()
|
||||||
* (ad5680::MAX_VALUE as f64)) as u32;
|
* (ad5680::MAX_VALUE as f64)) as u32;
|
||||||
self.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
|
||||||
voltage
|
voltage
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_i(&mut self, i_tec: ElectricCurrent) -> ElectricCurrent {
|
pub fn set_i(&mut self, i_tec: ElectricCurrent) -> ElectricCurrent {
|
||||||
let center_point = self.center_pt;
|
let center_point = self.phy.center_pt;
|
||||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
let r_sense = R_SENSE;
|
||||||
let voltage = i_tec * 10.0 * r_sense + center_point;
|
let voltage = i_tec * 10.0 * r_sense + center_point;
|
||||||
let voltage = self.set_dac(voltage);
|
let voltage = self.set_dac(voltage);
|
||||||
let i_tec = (voltage - center_point) / (10.0 * r_sense);
|
let i_tec = (voltage - center_point) / (10.0 * r_sense);
|
||||||
|
@ -193,8 +271,8 @@ impl MAX1968 {
|
||||||
sample = match adc_read_target {
|
sample = match adc_read_target {
|
||||||
AdcReadTarget::VREF => {
|
AdcReadTarget::VREF => {
|
||||||
for _ in (0..avg_pt).rev() {
|
for _ in (0..avg_pt).rev() {
|
||||||
sample += self.adc.convert(
|
sample += self.pins_adc.convert(
|
||||||
&self.adc_pins.vref,
|
&self.phy.vref_pin,
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||||
) as u32;
|
) as u32;
|
||||||
}
|
}
|
||||||
|
@ -202,8 +280,8 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
AdcReadTarget::DacVfb => {
|
AdcReadTarget::DacVfb => {
|
||||||
for _ in (0..avg_pt).rev() {
|
for _ in (0..avg_pt).rev() {
|
||||||
sample += self.adc.convert(
|
sample += self.pins_adc.convert(
|
||||||
&self.adc_pins.dac_vfb,
|
&self.phy.dac_feedback_pin,
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||||
) as u32;
|
) as u32;
|
||||||
}
|
}
|
||||||
|
@ -211,8 +289,8 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
AdcReadTarget::ITec => {
|
AdcReadTarget::ITec => {
|
||||||
for _ in (0..avg_pt).rev() {
|
for _ in (0..avg_pt).rev() {
|
||||||
sample += self.adc.convert(
|
sample += self.pins_adc.convert(
|
||||||
&self.adc_pins.itec,
|
&self.phy.itec_pin,
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||||
) as u32;
|
) as u32;
|
||||||
}
|
}
|
||||||
|
@ -220,15 +298,15 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
AdcReadTarget::VTec => {
|
AdcReadTarget::VTec => {
|
||||||
for _ in (0..avg_pt).rev() {
|
for _ in (0..avg_pt).rev() {
|
||||||
sample += self.adc.convert(
|
sample += self.pins_adc.convert(
|
||||||
&self.adc_pins.vtec,
|
&self.phy.vtec_pin,
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||||
) as u32;
|
) as u32;
|
||||||
}
|
}
|
||||||
sample / avg_pt as u32
|
sample / avg_pt as u32
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mv = self.adc.sample_to_millivolts(sample as u16);
|
let mv = self.pins_adc.sample_to_millivolts(sample as u16);
|
||||||
ElectricPotential::new::<millivolt>(mv as f64)
|
ElectricPotential::new::<millivolt>(mv as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,15 +321,14 @@ impl MAX1968 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tec_i(&mut self) -> ElectricCurrent {
|
pub fn get_tec_i(&mut self) -> ElectricCurrent {
|
||||||
(self.adc_read(AdcReadTarget::ITec, 1) - self.center_pt)
|
(self.adc_read(AdcReadTarget::ITec, 1) - self.phy.center_pt)
|
||||||
/ ElectricalResistance::new::<ohm>(0.4)
|
/ ElectricalResistance::new::<ohm>(0.4)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tec_v(&mut self) -> ElectricPotential {
|
pub fn get_tec_v(&mut self) -> ElectricPotential {
|
||||||
// Fixme: Rev0_2 has Analog Input Polarity Reversed
|
// Fixme: Rev0_2 has Analog Input Polarity Reversed
|
||||||
// Remove the -ve sign for Rev0_3
|
// Remove the -ve sign for Rev0_3
|
||||||
-(self.adc_read(AdcReadTarget::VTec, 1) - ElectricPotential::new::<volt>(TEC_VSEC_BIAS_V))
|
-(self.adc_read(AdcReadTarget::VTec, 1) - TEC_VSEC_BIAS_V) * 4.0
|
||||||
* 4.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_pwm(&mut self, pwm_pin: PwmPinsEnum, duty: f64, max_duty: f64) -> f64 {
|
fn set_pwm(&mut self, pwm_pin: PwmPinsEnum, duty: f64, max_duty: f64) -> f64 {
|
||||||
|
@ -266,33 +343,27 @@ impl MAX1968 {
|
||||||
let duty = duty.min(max_duty);
|
let duty = duty.min(max_duty);
|
||||||
|
|
||||||
match pwm_pin {
|
match pwm_pin {
|
||||||
PwmPinsEnum::MaxV => set(&mut self.pwm_pins.max_v0, duty),
|
PwmPinsEnum::MaxV => set(&mut self.phy.max_v, duty),
|
||||||
PwmPinsEnum::MaxPosI => set(&mut self.pwm_pins.max_i_pos0, duty),
|
PwmPinsEnum::MaxPosI => set(&mut self.phy.max_i_pos, duty),
|
||||||
PwmPinsEnum::MaxNegI => set(&mut self.pwm_pins.max_i_neg0, duty),
|
PwmPinsEnum::MaxNegI => set(&mut self.phy.max_i_neg, duty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_v(&mut self, max_v: ElectricPotential) -> (ElectricPotential, ElectricPotential) {
|
pub fn set_max_v(&mut self, max_v: ElectricPotential) -> ElectricPotential {
|
||||||
let max = ElectricPotential::new::<volt>(6.0);
|
let duty = (max_v / MAX_V_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let v = max_v / 4.0;
|
|
||||||
let duty = (v / ElectricPotential::new::<volt>(3.3)).get::<ratio>();
|
|
||||||
let duty = self.set_pwm(PwmPinsEnum::MaxV, duty, MAX_V_DUTY_MAX);
|
let duty = self.set_pwm(PwmPinsEnum::MaxV, duty, MAX_V_DUTY_MAX);
|
||||||
(duty * max, max)
|
duty * MAX_V_DUTY_TO_CURRENT_RATE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_i_pos(&mut self, max_i_pos: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
pub fn set_max_i_pos(&mut self, max_i_pos: ElectricCurrent) -> ElectricCurrent {
|
||||||
let max = ElectricCurrent::new::<ampere>(3.0);
|
let duty = (max_i_pos / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let v = 10.0 * max_i_pos * ElectricalResistance::new::<ohm>(R_SENSE);
|
|
||||||
let duty = (v / ElectricPotential::new::<volt>(3.3)).get::<ratio>();
|
|
||||||
let duty = self.set_pwm(PwmPinsEnum::MaxPosI, duty, MAX_I_POS_DUTY_MAX);
|
let duty = self.set_pwm(PwmPinsEnum::MaxPosI, duty, MAX_I_POS_DUTY_MAX);
|
||||||
(duty * max * 3.3 / 1.5, max)
|
duty * MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_i_neg(&mut self, max_i_neg: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
pub fn set_max_i_neg(&mut self, max_i_neg: ElectricCurrent) -> ElectricCurrent {
|
||||||
let max = ElectricCurrent::new::<ampere>(3.0);
|
let duty = (max_i_neg / MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE).get::<ratio>();
|
||||||
let v = 10.0 * max_i_neg * ElectricalResistance::new::<ohm>(R_SENSE);
|
|
||||||
let duty = (v / ElectricPotential::new::<volt>(3.3)).get::<ratio>();
|
|
||||||
let duty = self.set_pwm(PwmPinsEnum::MaxNegI, duty, MAX_I_NEG_DUTY_MAX);
|
let duty = self.set_pwm(PwmPinsEnum::MaxNegI, duty, MAX_I_NEG_DUTY_MAX);
|
||||||
(duty * max * 3.3 / 1.5, max)
|
duty * MAX_I_POS_NEG_DUTY_TO_CURRENT_RATE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::thermostat::ad5680;
|
||||||
|
use crate::thermostat::MAX1968;
|
||||||
|
|
||||||
|
pub struct Thermostat {
|
||||||
|
max1968: MAX1968,
|
||||||
|
// TADC
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Thermostat{
|
||||||
|
pub fn new (max1968: MAX1968) -> Self {
|
||||||
|
Thermostat{
|
||||||
|
max1968
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn setup(&mut self){
|
||||||
|
self.max1968.setup();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue