forked from M-Labs/thermostat
adc: complete temperature calculation
This commit is contained in:
parent
dda1f2f0b4
commit
7d45d5ad32
|
@ -4,6 +4,10 @@ use stm32f4xx_hal::hal::{
|
||||||
blocking::spi::Transfer,
|
blocking::spi::Transfer,
|
||||||
digital::v2::OutputPin,
|
digital::v2::OutputPin,
|
||||||
};
|
};
|
||||||
|
use uom::si::{
|
||||||
|
f64::ElectricPotential,
|
||||||
|
electric_potential::volt,
|
||||||
|
};
|
||||||
use super::{
|
use super::{
|
||||||
regs::{self, Register, RegisterData},
|
regs::{self, Register, RegisterData},
|
||||||
checksum::{ChecksumMode, Checksum},
|
checksum::{ChecksumMode, Checksum},
|
||||||
|
@ -272,7 +276,7 @@ pub struct ChannelCalibration {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelCalibration {
|
impl ChannelCalibration {
|
||||||
pub fn convert_data(&self, data: u32) -> f64 {
|
pub fn convert_data(&self, data: u32) -> ElectricPotential {
|
||||||
let data = if self.bipolar {
|
let data = if self.bipolar {
|
||||||
(data as i32 - 0x80_0000) as f64
|
(data as i32 - 0x80_0000) as f64
|
||||||
} else {
|
} else {
|
||||||
|
@ -282,7 +286,7 @@ impl ChannelCalibration {
|
||||||
let data = data + (self.offset as i32 - 0x80_0000) as f64;
|
let data = data + (self.offset as i32 - 0x80_0000) as f64;
|
||||||
let data = data / (2 << 23) as f64;
|
let data = data / (2 << 23) as f64;
|
||||||
|
|
||||||
const V_REF: f64 = 3.0;
|
const V_REF: f64 = 3.3;
|
||||||
data * V_REF / 0.75
|
ElectricPotential::new::<volt>(data * V_REF / 0.75)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@ use crate::{
|
||||||
steinhart_hart as sh,
|
steinhart_hart as sh,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const R_INNER: f64 = 2.0 * 5100.0;
|
||||||
|
|
||||||
pub struct ChannelState {
|
pub struct ChannelState {
|
||||||
pub adc_data: Option<u32>,
|
pub adc_data: Option<u32>,
|
||||||
pub adc_calibration: ad7172::ChannelCalibration,
|
pub adc_calibration: ad7172::ChannelCalibration,
|
||||||
pub adc_time: Instant,
|
pub adc_time: Instant,
|
||||||
|
pub vref: ElectricPotential,
|
||||||
pub dac_value: ElectricPotential,
|
pub dac_value: ElectricPotential,
|
||||||
pub pid_engaged: bool,
|
pub pid_engaged: bool,
|
||||||
pub pid: pid::Controller,
|
pub pid: pid::Controller,
|
||||||
|
@ -32,6 +34,8 @@ impl ChannelState {
|
||||||
adc_data: None,
|
adc_data: None,
|
||||||
adc_calibration,
|
adc_calibration,
|
||||||
adc_time: Instant::from_secs(0),
|
adc_time: Instant::from_secs(0),
|
||||||
|
// can be initialized later with Channels.read_vref()
|
||||||
|
vref: ElectricPotential::new::<volt>(3.3 / 2.0),
|
||||||
dac_value: ElectricPotential::new::<volt>(0.0),
|
dac_value: ElectricPotential::new::<volt>(0.0),
|
||||||
pid_engaged: false,
|
pid_engaged: false,
|
||||||
pid: pid::Controller::new(pid::Parameters::default()),
|
pid: pid::Controller::new(pid::Parameters::default()),
|
||||||
|
@ -52,14 +56,19 @@ impl ChannelState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_adc(&self) -> Option<ElectricPotential> {
|
pub fn get_adc(&self) -> Option<ElectricPotential> {
|
||||||
let volts = self.adc_calibration.convert_data(self.adc_data?);
|
Some(self.adc_calibration.convert_data(self.adc_data?))
|
||||||
Some(ElectricPotential::new::<volt>(volts))
|
}
|
||||||
|
|
||||||
|
/// Get `SENS[01]` input resistance
|
||||||
|
pub fn get_sens(&self) -> Option<ElectricalResistance> {
|
||||||
|
let r_inner = ElectricalResistance::new::<ohm>(R_INNER);
|
||||||
|
let adc_input = self.get_adc()?;
|
||||||
|
let r = r_inner * adc_input / (self.vref - adc_input);
|
||||||
|
Some(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_temperature(&self) -> Option<ThermodynamicTemperature> {
|
pub fn get_temperature(&self) -> Option<ThermodynamicTemperature> {
|
||||||
let r = self.get_adc()?.get::<volt>();
|
let r = self.get_sens()?;
|
||||||
// TODO:
|
|
||||||
let r = ElectricalResistance::new::<ohm>(r);
|
|
||||||
let temperature = self.sh.get_temperature(r);
|
let temperature = self.sh.get_temperature(r);
|
||||||
Some(temperature)
|
Some(temperature)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ impl Channels {
|
||||||
let pwm = pins.pwm;
|
let pwm = pins.pwm;
|
||||||
let mut channels = Channels { channel0, channel1, adc, pins_adc, pwm };
|
let mut channels = Channels { channel0, channel1, adc, pins_adc, pwm };
|
||||||
for channel in 0..CHANNELS {
|
for channel in 0..CHANNELS {
|
||||||
|
// FIXME: this reads 1.5 V instead of the expected 1.65 V.
|
||||||
|
// channels.channel_state(channel).vref = channels.read_vref(channel);
|
||||||
channels.calibrate_dac_value(channel);
|
channels.calibrate_dac_value(channel);
|
||||||
}
|
}
|
||||||
channels
|
channels
|
||||||
|
@ -172,7 +174,7 @@ impl Channels {
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
||||||
);
|
);
|
||||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||||
ElectricPotential::new::<volt>(mv as f64 / 1000.0)
|
ElectricPotential::new::<millivolt>(mv as f64)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -180,7 +182,7 @@ impl Channels {
|
||||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
||||||
);
|
);
|
||||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||||
ElectricPotential::new::<volt>(mv as f64 / 1000.0)
|
ElectricPotential::new::<millivolt>(mv as f64)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -168,7 +168,7 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
Command::Show(ShowCommand::Input) => {
|
Command::Show(ShowCommand::Input) => {
|
||||||
for channel in 0..CHANNELS {
|
for channel in 0..CHANNELS {
|
||||||
if let Some(adc_data) = channels.channel_state(channel).adc_data {
|
if let Some(adc_input) = channels.channel_state(channel).get_adc() {
|
||||||
let vref = channels.read_vref(channel);
|
let vref = channels.read_vref(channel);
|
||||||
let dac_feedback = channels.read_dac_feedback(channel);
|
let dac_feedback = channels.read_dac_feedback(channel);
|
||||||
|
|
||||||
|
@ -179,9 +179,10 @@ fn main() -> ! {
|
||||||
|
|
||||||
let state = channels.channel_state(channel);
|
let state = channels.channel_state(channel);
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "channel {}: t={} adc{}={} vref={} dac_feedback={} itec={} tec={} tec_u_meas={} r={:03}",
|
socket, "channel {}: t={} adc{}={} adc_r={} vref={} dac_feedback={} itec={} tec={} tec_u_meas={} r={:03}",
|
||||||
channel,
|
channel, state.adc_time,
|
||||||
state.adc_time, channel, adc_data,
|
channel, adc_input.into_format_args(volt, Abbreviation),
|
||||||
|
state.get_sens().unwrap().into_format_args(ohm, Abbreviation),
|
||||||
vref.into_format_args(volt, Abbreviation), dac_feedback.into_format_args(volt, Abbreviation),
|
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),
|
itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, Abbreviation),
|
||||||
tec_u_meas.into_format_args(volt, Abbreviation),
|
tec_u_meas.into_format_args(volt, Abbreviation),
|
||||||
|
@ -265,11 +266,12 @@ fn main() -> ! {
|
||||||
let _ = writeln!(socket, "- t0={}", state.sh.t0.into_format_args(degree_celsius, Abbreviation));
|
let _ = writeln!(socket, "- t0={}", state.sh.t0.into_format_args(degree_celsius, Abbreviation));
|
||||||
let _ = writeln!(socket, "- b={}", state.sh.b);
|
let _ = writeln!(socket, "- b={}", state.sh.b);
|
||||||
let _ = writeln!(socket, "- r0={}", state.sh.r0.into_format_args(ohm, Abbreviation));
|
let _ = writeln!(socket, "- r0={}", state.sh.r0.into_format_args(ohm, Abbreviation));
|
||||||
match (state.get_adc(), state.get_temperature()) {
|
match (state.get_adc(), state.get_sens(), state.get_temperature()) {
|
||||||
(Some(adc), Some(temp)) => {
|
(Some(adc), Some(sens), Some(temp)) => {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "- adc={} temp={:.3}K",
|
socket, "- adc={} r={} temp={:.3}K",
|
||||||
adc.into_format_args(volt, Abbreviation),
|
adc.into_format_args(volt, Abbreviation),
|
||||||
|
sens.into_format_args(ohm, Abbreviation),
|
||||||
temp.into_format_args(degree_celsius, Abbreviation),
|
temp.into_format_args(degree_celsius, Abbreviation),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue