forked from M-Labs/thermostat
Compare commits
3 Commits
master
...
factor-set
Author | SHA1 | Date | |
---|---|---|---|
a0728e1c5f | |||
78187af7f5 | |||
839ee56f96 |
@ -3,10 +3,16 @@ use super::{
|
||||
regs::{self, Register, RegisterData},
|
||||
DigitalFilterOrder, Input, Mode, PostFilter, RefSource,
|
||||
};
|
||||
use core::fmt;
|
||||
use core::{fmt, marker::PhantomData};
|
||||
use log::{info, warn};
|
||||
use stm32f4xx_hal::hal::{blocking::spi::Transfer, digital::v2::OutputPin};
|
||||
use uom::si::{electric_potential::volt, f64::ElectricPotential};
|
||||
use uom::si::f64::ElectricPotential;
|
||||
|
||||
const V_REF: ElectricPotential = ElectricPotential {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 3.3,
|
||||
};
|
||||
|
||||
/// AD7172-2 implementation
|
||||
///
|
||||
@ -284,8 +290,6 @@ impl ChannelCalibration {
|
||||
let data = data / (self.gain as f64 / (0x40_0000 as f64));
|
||||
let data = data + (self.offset as i32 - 0x80_0000) as f64;
|
||||
let data = data / (2 << 23) as f64;
|
||||
|
||||
const V_REF: f64 = 3.3;
|
||||
ElectricPotential::new::<volt>(data * V_REF / 0.75)
|
||||
data * V_REF / 0.75
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ use crate::{
|
||||
config::OutputLimits,
|
||||
pid,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use num_traits::Zero;
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
use uom::si::{
|
||||
electric_current::ampere,
|
||||
electric_potential::volt,
|
||||
electrical_resistance::ohm,
|
||||
f64::{
|
||||
ElectricCurrent, ElectricPotential, ElectricalResistance, ThermodynamicTemperature, Time,
|
||||
},
|
||||
@ -17,8 +17,16 @@ use uom::si::{
|
||||
time::millisecond,
|
||||
};
|
||||
|
||||
const R_INNER: f64 = 2.0 * 5100.0;
|
||||
const VREF_SENS: f64 = 3.3 / 2.0;
|
||||
const R_INNER: ElectricalResistance = ElectricalResistance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 2.0 * 5100.0,
|
||||
};
|
||||
const VREF_SENS: ElectricPotential = ElectricPotential {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 3.3 / 2.0,
|
||||
};
|
||||
|
||||
pub struct ChannelState {
|
||||
pub adc_data: Option<u32>,
|
||||
@ -91,10 +99,9 @@ impl ChannelState {
|
||||
|
||||
/// Get `SENS[01]` input resistance
|
||||
pub fn get_sens(&self) -> Option<ElectricalResistance> {
|
||||
let r_inner = ElectricalResistance::new::<ohm>(R_INNER);
|
||||
let vref = ElectricPotential::new::<volt>(VREF_SENS);
|
||||
let vref = VREF_SENS;
|
||||
let adc_input = self.get_adc()?;
|
||||
let r = r_inner * adc_input / (vref - adc_input);
|
||||
let r = R_INNER * adc_input / (vref - adc_input);
|
||||
Some(r)
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,11 @@ pub enum PinsAdcReadTarget {
|
||||
}
|
||||
|
||||
pub const CHANNELS: usize = 2;
|
||||
const R_SENSE: f64 = 0.05;
|
||||
const R_SENSE: ElectricalResistance = ElectricalResistance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 0.05,
|
||||
};
|
||||
|
||||
const CPU_ADC_VREF: ElectricPotential = ElectricPotential {
|
||||
dimension: PhantomData,
|
||||
@ -176,11 +180,10 @@ impl Channels {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let center_point = vref_meas;
|
||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||
let voltage = negate * i_set * 10.0 * r_sense + center_point;
|
||||
let voltage = negate * i_set * 10.0 * R_SENSE + center_point;
|
||||
let voltage = self.set_dac(channel, voltage);
|
||||
|
||||
negate * (voltage - center_point) / (10.0 * r_sense)
|
||||
negate * (voltage - center_point) / (10.0 * R_SENSE)
|
||||
}
|
||||
|
||||
/// AN4073: ADC Reading Dispersion can be reduced through Averaging
|
||||
@ -398,14 +401,21 @@ impl Channels {
|
||||
* 4.0
|
||||
}
|
||||
|
||||
fn set_pwm(&mut self, channel: usize, pin: PwmPin, duty: f64) -> f64 {
|
||||
fn set_pwm_pin_voltage(
|
||||
&mut self,
|
||||
channel: usize,
|
||||
pin: PwmPin,
|
||||
voltage: ElectricPotential,
|
||||
) -> ElectricPotential {
|
||||
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);
|
||||
value as f64 / (max as f64)
|
||||
}
|
||||
match (channel, pin) {
|
||||
let duty: f64 = (voltage / CPU_ADC_VREF).into();
|
||||
|
||||
let duty = match (channel, pin) {
|
||||
(_, PwmPin::ISet) => panic!("i_set is no pwm pin"),
|
||||
(0, PwmPin::MaxIPos) => set(&mut self.pwm.max_i_pos0, duty),
|
||||
(0, PwmPin::MaxINeg) => set(&mut self.pwm.max_i_neg0, duty),
|
||||
@ -414,7 +424,8 @@ impl Channels {
|
||||
(1, PwmPin::MaxINeg) => set(&mut self.pwm.max_i_neg1, duty),
|
||||
(1, PwmPin::MaxV) => set(&mut self.pwm.max_v1, duty),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
duty * CPU_ADC_VREF
|
||||
}
|
||||
|
||||
pub fn set_max_v(
|
||||
@ -425,10 +436,8 @@ impl Channels {
|
||||
let max_v = max_v.min(MAX_TEC_V).max(ElectricPotential::zero());
|
||||
self.channel_state(channel).output_limits.max_v = max_v;
|
||||
let v_maxv = max_v / 4.0;
|
||||
let duty = (v_maxv / CPU_ADC_VREF).get::<ratio>();
|
||||
|
||||
let duty = self.set_pwm(channel, PwmPin::MaxV, duty);
|
||||
let v_maxv = duty * CPU_ADC_VREF;
|
||||
let v_maxv = self.set_pwm_pin_voltage(channel, PwmPin::MaxV, v_maxv);
|
||||
let max_v = 4.0 * v_maxv;
|
||||
|
||||
(max_v, MAX_TEC_V)
|
||||
@ -439,22 +448,14 @@ impl Channels {
|
||||
channel: usize,
|
||||
max_i_pos: ElectricCurrent,
|
||||
) -> (ElectricCurrent, ElectricCurrent) {
|
||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||
let pin = match self.channel_state(channel).polarity {
|
||||
Polarity::Normal => PwmPin::MaxIPos,
|
||||
Polarity::Reversed => PwmPin::MaxINeg,
|
||||
};
|
||||
|
||||
let max_i_pos = max_i_pos.min(MAX_TEC_I).max(ElectricCurrent::zero());
|
||||
self.channel_state(channel).output_limits.max_i_pos = max_i_pos;
|
||||
let v_maxip = 10.0 * (max_i_pos * r_sense);
|
||||
let duty = (v_maxip / CPU_ADC_VREF).get::<ratio>();
|
||||
|
||||
let duty = self.set_pwm(channel, pin, duty);
|
||||
let v_maxip = duty * CPU_ADC_VREF;
|
||||
let max_i_pos = v_maxip / 10.0 / r_sense;
|
||||
|
||||
(max_i_pos, MAX_TEC_I)
|
||||
let max_i_pos = self.set_max_i(channel, max_i_pos, pin);
|
||||
self.channel_state(channel).output_limits.max_i_pos = max_i_pos.0;
|
||||
max_i_pos
|
||||
}
|
||||
|
||||
pub fn set_max_i_neg(
|
||||
@ -462,22 +463,29 @@ impl Channels {
|
||||
channel: usize,
|
||||
max_i_neg: ElectricCurrent,
|
||||
) -> (ElectricCurrent, ElectricCurrent) {
|
||||
let r_sense = ElectricalResistance::new::<ohm>(R_SENSE);
|
||||
let pin = match self.channel_state(channel).polarity {
|
||||
Polarity::Normal => PwmPin::MaxINeg,
|
||||
Polarity::Reversed => PwmPin::MaxIPos,
|
||||
};
|
||||
|
||||
let max_i_neg = max_i_neg.min(MAX_TEC_I).max(ElectricCurrent::zero());
|
||||
self.channel_state(channel).output_limits.max_i_neg = max_i_neg;
|
||||
let v_maxin = 10.0 * (max_i_neg * r_sense);
|
||||
let duty = (v_maxin / CPU_ADC_VREF).get::<ratio>();
|
||||
let max_i_neg = self.set_max_i(channel, max_i_neg, pin);
|
||||
self.channel_state(channel).output_limits.max_i_neg = max_i_neg.0;
|
||||
max_i_neg
|
||||
}
|
||||
|
||||
let duty = self.set_pwm(channel, pin, duty);
|
||||
let v_maxin = duty * CPU_ADC_VREF;
|
||||
let max_i_neg = v_maxin / 10.0 / r_sense;
|
||||
fn set_max_i(
|
||||
&mut self,
|
||||
channel: usize,
|
||||
max_i: ElectricCurrent,
|
||||
pin: PwmPin,
|
||||
) -> (ElectricCurrent, ElectricCurrent) {
|
||||
let max_i = max_i.min(MAX_TEC_I).max(ElectricCurrent::zero());
|
||||
let v_maxi_ = 10.0 * (max_i * R_SENSE);
|
||||
|
||||
(max_i_neg, MAX_TEC_I)
|
||||
let v_maxi_ = self.set_pwm_pin_voltage(channel, pin, v_maxi_);
|
||||
let max_i = v_maxi_ / 10.0 / R_SENSE;
|
||||
|
||||
(max_i, MAX_TEC_I)
|
||||
}
|
||||
|
||||
pub fn set_postfilter(&mut self, index: u8, filter: Option<PostFilter>) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user