Initial Commit for AD5680 and MAX1968 Drivers
- GPIO Initializations for AD5680, MAX1968 drivers - CTLI voltage of MAX1968 can be set with AD5680 - All features of MAX1968 can be controlled
This commit is contained in:
parent
764a203dd8
commit
475fe28604
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -290,6 +290,7 @@ dependencies = [
|
||||
"smoltcp",
|
||||
"stm32-eth",
|
||||
"stm32f4xx-hal",
|
||||
"uom",
|
||||
"usb-device",
|
||||
"usbd-serial",
|
||||
]
|
||||
@ -462,6 +463,26 @@ version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp"
|
||||
version = "0.10.0"
|
||||
@ -579,18 +600,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -614,6 +635,12 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ufmt-write"
|
||||
version = "0.1.0"
|
||||
@ -626,6 +653,17 @@ version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "uom"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e76503e636584f1e10b9b3b9498538279561adcef5412927ba00c2b32c4ce5ed"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usb-device"
|
||||
version = "0.2.9"
|
||||
|
@ -25,6 +25,7 @@ cortex-m-log = { version = "0.7.0", features = ["log-integration", "semihosting"
|
||||
stm32f4xx-hal = { version = "0.14.0", features = ["rt", "stm32f407", "usb_fs"] }
|
||||
stm32-eth = { version = "0.5.2", features = ["stm32f407"] }
|
||||
smoltcp = { version = "0.10.0", default-features = false, features = ["proto-ipv4", "socket-tcp", "log", "medium-ethernet"] }
|
||||
uom = { version = "0.30", default-features = false, features = ["autoconvert", "si", "f64", "use_serde"] }
|
||||
num-traits = { version = "0.2.15", default-features = false, features = ["libm"] }
|
||||
usb-device = "0.2.9"
|
||||
usbd-serial = "0.1.1"
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{gpio, sys_timer, usb};
|
||||
use crate::laser_diode::current_sources::*;
|
||||
use crate::{laser_diode::current_sources::*, thermostat::max1968};
|
||||
use fugit::ExtU32;
|
||||
use log::info;
|
||||
use stm32f4xx_hal::{
|
||||
@ -31,13 +31,15 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> Independen
|
||||
|
||||
sys_timer::setup(core_perif.SYST, clocks);
|
||||
|
||||
let (_eth_pins, usb, current_source_phy) = gpio::setup(
|
||||
let (_eth_pins, usb, current_source_phy, max1968_phy) = gpio::setup(
|
||||
clocks,
|
||||
perif.TIM4,
|
||||
perif.GPIOA,
|
||||
perif.GPIOB,
|
||||
perif.GPIOC,
|
||||
perif.GPIOD,
|
||||
perif.GPIOG,
|
||||
perif.SPI1,
|
||||
perif.SPI2,
|
||||
perif.OTG_FS_GLOBAL,
|
||||
perif.OTG_FS_DEVICE,
|
||||
@ -56,6 +58,8 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> Independen
|
||||
laser.setup();
|
||||
laser.set_current(0.1).unwrap();
|
||||
|
||||
let tec_driver = max1968::MAX1968::new(max1968_phy, perif.ADC1);
|
||||
|
||||
let mut wd = IndependentWatchdog::new(perif.IWDG);
|
||||
wd.start(WATCHDOG_PERIOD.millis());
|
||||
wd.feed();
|
||||
|
@ -1,13 +1,19 @@
|
||||
use crate::laser_diode::current_sources::*;
|
||||
use crate::thermostat::ad5680;
|
||||
use crate::thermostat::max1968::{MAX1968PinSet, PWM_FREQ_KHZ};
|
||||
use fugit::RateExtU32;
|
||||
use stm32_eth::EthPins;
|
||||
use stm32f4xx_hal::{
|
||||
gpio::{gpioa::*, gpiob::*, gpioc::*, gpiog::*, GpioExt, Input},
|
||||
otg_fs::USB,
|
||||
pac::{GPIOA, GPIOB, GPIOC, GPIOD, GPIOG, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI2},
|
||||
pac::{
|
||||
GPIOA, GPIOB, GPIOC, GPIOD, GPIOG, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI1, SPI2,
|
||||
TIM4,
|
||||
},
|
||||
rcc::Clocks,
|
||||
spi,
|
||||
spi::{NoMiso, Spi},
|
||||
timer::pwm::PwmExt,
|
||||
};
|
||||
|
||||
pub type EthernetPins =
|
||||
@ -15,11 +21,13 @@ pub type EthernetPins =
|
||||
|
||||
pub fn setup(
|
||||
clocks: Clocks,
|
||||
tim4: TIM4,
|
||||
gpioa: GPIOA,
|
||||
gpiob: GPIOB,
|
||||
gpioc: GPIOC,
|
||||
gpiod: GPIOD,
|
||||
gpiog: GPIOG,
|
||||
spi1: SPI1,
|
||||
spi2: SPI2,
|
||||
otg_fs_global: OTG_FS_GLOBAL,
|
||||
otg_fs_device: OTG_FS_DEVICE,
|
||||
@ -28,6 +36,7 @@ pub fn setup(
|
||||
EthernetPins,
|
||||
USB,
|
||||
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
||||
MAX1968PinSet,
|
||||
// photo_diode_phy,
|
||||
// thermostat_phy
|
||||
) {
|
||||
@ -77,5 +86,36 @@ pub fn setup(
|
||||
current_source_short: gpioa.pa4.into_push_pull_output(),
|
||||
};
|
||||
|
||||
(eth_pins, usb, current_source_phy)
|
||||
let pwm_chs = (
|
||||
gpiob.pb6.into_alternate(),
|
||||
gpiob.pb7.into_alternate(),
|
||||
gpiob.pb8.into_alternate(),
|
||||
);
|
||||
let (max_i_neg0, max_v0, max_i_pos0) =
|
||||
tim4.pwm_hz(pwm_chs, PWM_FREQ_KHZ.kHz(), &clocks).split();
|
||||
|
||||
let max1968_phy = MAX1968PinSet {
|
||||
dac_spi: Spi::new(
|
||||
spi1,
|
||||
(
|
||||
gpiob.pb3.into_alternate(),
|
||||
NoMiso {},
|
||||
gpiob.pb5.into_alternate(),
|
||||
),
|
||||
ad5680::SPI_MODE,
|
||||
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(),
|
||||
vref: gpioa.pa6.into_analog(),
|
||||
vtec: gpiob.pb0.into_analog(),
|
||||
itec: gpiob.pb1.into_analog(),
|
||||
max_v0: max_v0,
|
||||
max_i_pos0: max_i_pos0,
|
||||
max_i_neg0: max_i_neg0,
|
||||
};
|
||||
|
||||
(eth_pins, usb, current_source_phy, max1968_phy)
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ use stm32f4xx_hal::pac::{CorePeripherals, Peripherals};
|
||||
|
||||
mod device;
|
||||
mod laser_diode;
|
||||
mod thermostat;
|
||||
use device::{boot::bootup, log_setup, sys_timer};
|
||||
|
||||
use crate::thermostat::max1968;
|
||||
|
||||
// If RTT is used, print panic info through RTT
|
||||
#[cfg(all(feature = "RTT", not(test)))]
|
||||
use {
|
||||
core::panic::PanicInfo,
|
||||
rtt_target::rprintln,
|
||||
};
|
||||
use {core::panic::PanicInfo, rtt_target::rprintln};
|
||||
#[cfg(all(feature = "RTT", not(test)))]
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
@ -28,7 +28,6 @@ use panic_halt as _;
|
||||
#[cfg(not(test))]
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
|
||||
log_setup::init_log();
|
||||
info!("Kirdy init");
|
||||
|
||||
|
45
src/thermostat/ad5680.rs
Normal file
45
src/thermostat/ad5680.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::device::sys_timer::sleep;
|
||||
use stm32f4xx_hal::{
|
||||
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
|
||||
spi,
|
||||
};
|
||||
|
||||
/// SPI Mode 1
|
||||
pub const SPI_MODE: spi::Mode = spi::Mode {
|
||||
polarity: spi::Polarity::IdleLow,
|
||||
phase: spi::Phase::CaptureOnSecondTransition,
|
||||
};
|
||||
pub const SPI_CLOCK_MHZ: u32 = 30;
|
||||
|
||||
pub const MAX_VALUE: u32 = 0x3FFFF;
|
||||
|
||||
pub struct Dac<SPI: Transfer<u8>, S: OutputPin> {
|
||||
spi: SPI,
|
||||
sync: S,
|
||||
}
|
||||
|
||||
impl<SPI: Transfer<u8>, S: OutputPin> Dac<SPI, S> {
|
||||
pub fn new(spi: SPI, mut sync: S) -> Self {
|
||||
let _ = sync.set_low();
|
||||
|
||||
Dac { spi, sync }
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &mut [u8]) -> Result<(), SPI::Error> {
|
||||
// pulse sync to start a new transfer. leave sync idle low
|
||||
// afterwards to save power as recommended per datasheet.
|
||||
let _ = self.sync.set_high();
|
||||
// must be high for >= 33 ns
|
||||
sleep(1);
|
||||
let _ = self.sync.set_low();
|
||||
self.spi.transfer(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: u32) -> Result<u32, SPI::Error> {
|
||||
let value = value.min(MAX_VALUE);
|
||||
let mut buf = [(value >> 14) as u8, (value >> 6) as u8, (value << 2) as u8];
|
||||
self.write(&mut buf)?;
|
||||
Ok(value)
|
||||
}
|
||||
}
|
284
src/thermostat/max1968.rs
Normal file
284
src/thermostat/max1968.rs
Normal file
@ -0,0 +1,284 @@
|
||||
use core::u16;
|
||||
|
||||
use crate::thermostat::ad5680;
|
||||
|
||||
use fugit::RateExtU32;
|
||||
use stm32f4xx_hal::{
|
||||
adc::{
|
||||
config::{self, AdcConfig},
|
||||
Adc,
|
||||
},
|
||||
gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull},
|
||||
hal,
|
||||
pac::{ADC1, SPI1, TIM4},
|
||||
rcc::Clocks,
|
||||
spi::{NoMiso, Spi, TransferModeNormal},
|
||||
timer::pwm::{PwmChannel, PwmExt},
|
||||
};
|
||||
|
||||
use uom::si::{
|
||||
electric_current::ampere,
|
||||
electric_potential::{millivolt, volt},
|
||||
electrical_resistance::ohm,
|
||||
f64::{ElectricCurrent, ElectricPotential, ElectricalResistance},
|
||||
ratio::ratio,
|
||||
};
|
||||
|
||||
pub const PWM_FREQ_KHZ: u32 = 20;
|
||||
pub const R_SENSE: f64 = 0.05;
|
||||
|
||||
// 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,
|
||||
// which is then passed through a resistor divider to provide 0-3V output range
|
||||
const DAC_OUT_V_MAX: f64 = 3.3;
|
||||
const TEC_VSEC_BIAS_V: f64 = 1.65;
|
||||
const MAX_V_DUTY_MAX: f64 = 1.5 / 3.3;
|
||||
const MAX_I_POS_DUTY_MAX: f64 = 1.5 / 3.3;
|
||||
const MAX_I_NEG_DUTY_MAX: f64 = 1.5 / 3.3;
|
||||
|
||||
pub struct MAX1968PinSet {
|
||||
pub dac_spi: DacSpi,
|
||||
pub dac_sync: DacSync,
|
||||
pub shdn: PA5<Output<PushPull>>,
|
||||
pub dac_vfb: PC0<Analog>,
|
||||
pub vref: PA6<Analog>,
|
||||
pub vtec: PB0<Analog>,
|
||||
pub itec: PB1<Analog>,
|
||||
pub max_v0: PwmChannel<TIM4, 1>,
|
||||
pub max_i_pos0: PwmChannel<TIM4, 2>,
|
||||
pub max_i_neg0: PwmChannel<TIM4, 0>,
|
||||
}
|
||||
|
||||
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
|
||||
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 center_pt: ElectricPotential, // To be moved to a miniconf crate's struct
|
||||
pub adc: Adc<ADC1>,
|
||||
pub dac: ad5680::Dac<DacSpi, DacSync>,
|
||||
pub shdn: PA5<Output<PushPull>>,
|
||||
pub adc_pins: MaxAdcPins,
|
||||
pub pwm_pins: PwmPins,
|
||||
}
|
||||
pub struct PwmPins {
|
||||
pub max_v0: PwmChannel<TIM4, 1>,
|
||||
pub max_i_pos0: PwmChannel<TIM4, 2>,
|
||||
pub max_i_neg0: PwmChannel<TIM4, 0>,
|
||||
}
|
||||
enum PwmPinsEnum {
|
||||
MaxV,
|
||||
MaxPosI,
|
||||
MaxNegI,
|
||||
}
|
||||
|
||||
pub enum AdcReadTarget {
|
||||
VREF,
|
||||
DacVfb,
|
||||
ITec,
|
||||
VTec,
|
||||
}
|
||||
|
||||
impl 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) {
|
||||
pin.set_duty(0);
|
||||
pin.enable();
|
||||
}
|
||||
|
||||
let channels = (
|
||||
max_i_neg0.into_alternate::<2>(),
|
||||
max_v0.into_alternate::<2>(),
|
||||
max_i_pos0.into_alternate::<2>(),
|
||||
);
|
||||
|
||||
let (mut max_i_neg0, mut max_v0, mut max_i_pos0) =
|
||||
tim4.pwm_hz(channels, freq, &clocks).split();
|
||||
|
||||
init_pwm_pin(&mut max_v0);
|
||||
init_pwm_pin(&mut max_i_neg0);
|
||||
init_pwm_pin(&mut max_i_pos0);
|
||||
|
||||
PwmPins {
|
||||
max_v0,
|
||||
max_i_pos0,
|
||||
max_i_neg0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MAX1968 {
|
||||
pub fn new(pins: MAX1968PinSet, adc1: ADC1) -> Self {
|
||||
let dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
|
||||
|
||||
let config = AdcConfig::default()
|
||||
.clock(config::Clock::Pclk2_div_2)
|
||||
.default_sample_time(config::SampleTime::Cycles_480);
|
||||
|
||||
let pins_adc = Adc::adc1(adc1, true, config);
|
||||
|
||||
MAX1968 {
|
||||
center_pt: ElectricPotential::new::<millivolt>(1500.0),
|
||||
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 power_down(&mut self) {
|
||||
let _ = self.shdn.set_high();
|
||||
}
|
||||
|
||||
pub fn power_up(&mut self) {
|
||||
let _ = self.shdn.set_high();
|
||||
}
|
||||
|
||||
pub fn set_center_point(&mut self, value: ElectricPotential) {
|
||||
self.center_pt = value;
|
||||
}
|
||||
|
||||
fn set_dac(&mut self, voltage: ElectricPotential) -> ElectricPotential {
|
||||
let value = ((voltage / ElectricPotential::new::<volt>(DAC_OUT_V_MAX)).get::<ratio>()
|
||||
* (ad5680::MAX_VALUE as f64)) as u32;
|
||||
self.dac.set(value).unwrap();
|
||||
// TODO: Store the set-ed DAC Voltage Value
|
||||
voltage
|
||||
}
|
||||
|
||||
pub fn set_i(&mut self, i_tec: ElectricCurrent) -> ElectricCurrent {
|
||||
let center_point = self.center_pt;
|
||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||
let voltage = i_tec * 10.0 * r_sense + center_point;
|
||||
let voltage = self.set_dac(voltage);
|
||||
let i_tec = (voltage - center_point) / (10.0 * r_sense);
|
||||
i_tec
|
||||
}
|
||||
|
||||
// AN4073: ADC Reading Dispersion can be reduced through Averaging
|
||||
// Upon test, 16 Point Averaging = +-3 LSB Dispersion
|
||||
fn adc_read(&mut self, adc_read_target: AdcReadTarget, avg_pt: u16) -> ElectricPotential {
|
||||
let mut sample: u32 = 0;
|
||||
sample = match adc_read_target {
|
||||
AdcReadTarget::VREF => {
|
||||
for _ in (0..avg_pt).rev() {
|
||||
sample += self.adc.convert(
|
||||
&self.adc_pins.vref,
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||
) as u32;
|
||||
}
|
||||
sample / avg_pt as u32
|
||||
}
|
||||
AdcReadTarget::DacVfb => {
|
||||
for _ in (0..avg_pt).rev() {
|
||||
sample += self.adc.convert(
|
||||
&self.adc_pins.dac_vfb,
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||
) as u32;
|
||||
}
|
||||
sample / avg_pt as u32
|
||||
}
|
||||
AdcReadTarget::ITec => {
|
||||
for _ in (0..avg_pt).rev() {
|
||||
sample += self.adc.convert(
|
||||
&self.adc_pins.itec,
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||
) as u32;
|
||||
}
|
||||
sample / avg_pt as u32
|
||||
}
|
||||
AdcReadTarget::VTec => {
|
||||
for _ in (0..avg_pt).rev() {
|
||||
sample += self.adc.convert(
|
||||
&self.adc_pins.vtec,
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480,
|
||||
) as u32;
|
||||
}
|
||||
sample / avg_pt as u32
|
||||
}
|
||||
};
|
||||
let mv = self.adc.sample_to_millivolts(sample as u16);
|
||||
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 {
|
||||
// Fixme: Rev0_2 does not have this feature
|
||||
unimplemented!()
|
||||
//self.adc_read(AdcReadTarget:: DacVfb, 1)
|
||||
}
|
||||
|
||||
pub fn get_tec_i(&mut self) -> ElectricCurrent {
|
||||
(self.adc_read(AdcReadTarget::ITec, 1) - self.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) - ElectricPotential::new::<volt>(TEC_VSEC_BIAS_V))
|
||||
* 4.0
|
||||
}
|
||||
|
||||
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 {
|
||||
let max = pin.get_max_duty();
|
||||
let value = ((duty * (max as f64)) as u16).min(max);
|
||||
pin.set_duty(value);
|
||||
pin.enable();
|
||||
value as f64 / (max as f64)
|
||||
}
|
||||
|
||||
let duty = duty.min(max_duty);
|
||||
|
||||
match pwm_pin {
|
||||
PwmPinsEnum::MaxV => set(&mut self.pwm_pins.max_v0, duty),
|
||||
PwmPinsEnum::MaxPosI => set(&mut self.pwm_pins.max_i_pos0, duty),
|
||||
PwmPinsEnum::MaxNegI => set(&mut self.pwm_pins.max_i_neg0, duty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_max_v(&mut self, max_v: ElectricPotential) -> (ElectricPotential, ElectricPotential) {
|
||||
let max = ElectricPotential::new::<volt>(6.0);
|
||||
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);
|
||||
(duty * max, max)
|
||||
}
|
||||
|
||||
pub fn set_max_i_pos(&mut self, max_i_pos: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
||||
let max = ElectricCurrent::new::<ampere>(3.0);
|
||||
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);
|
||||
(duty * max * 3.3 / 1.5, max)
|
||||
}
|
||||
|
||||
pub fn set_max_i_neg(&mut self, max_i_neg: ElectricCurrent) -> (ElectricCurrent, ElectricCurrent) {
|
||||
let max = ElectricCurrent::new::<ampere>(3.0);
|
||||
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);
|
||||
(duty * max * 3.3 / 1.5, max)
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
pub mod ad5680;
|
||||
pub mod max1968;
|
0
src/thermostat/thermostat.rs
Normal file
0
src/thermostat/thermostat.rs
Normal file
Loading…
Reference in New Issue
Block a user