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,
|
||||
digital::v2::OutputPin,
|
||||
};
|
||||
use uom::si::{
|
||||
f64::ElectricPotential,
|
||||
electric_potential::volt,
|
||||
};
|
||||
use super::{
|
||||
regs::{self, Register, RegisterData},
|
||||
checksum::{ChecksumMode, Checksum},
|
||||
@ -272,7 +276,7 @@ pub struct ChannelCalibration {
|
||||
}
|
||||
|
||||
impl ChannelCalibration {
|
||||
pub fn convert_data(&self, data: u32) -> f64 {
|
||||
pub fn convert_data(&self, data: u32) -> ElectricPotential {
|
||||
let data = if self.bipolar {
|
||||
(data as i32 - 0x80_0000) as f64
|
||||
} else {
|
||||
@ -282,7 +286,7 @@ impl ChannelCalibration {
|
||||
let data = data + (self.offset as i32 - 0x80_0000) as f64;
|
||||
let data = data / (2 << 23) as f64;
|
||||
|
||||
const V_REF: f64 = 3.0;
|
||||
data * V_REF / 0.75
|
||||
const V_REF: f64 = 3.3;
|
||||
ElectricPotential::new::<volt>(data * V_REF / 0.75)
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,13 @@ use crate::{
|
||||
steinhart_hart as sh,
|
||||
};
|
||||
|
||||
const R_INNER: f64 = 2.0 * 5100.0;
|
||||
|
||||
pub struct ChannelState {
|
||||
pub adc_data: Option<u32>,
|
||||
pub adc_calibration: ad7172::ChannelCalibration,
|
||||
pub adc_time: Instant,
|
||||
pub vref: ElectricPotential,
|
||||
pub dac_value: ElectricPotential,
|
||||
pub pid_engaged: bool,
|
||||
pub pid: pid::Controller,
|
||||
@ -32,6 +34,8 @@ impl ChannelState {
|
||||
adc_data: None,
|
||||
adc_calibration,
|
||||
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),
|
||||
pid_engaged: false,
|
||||
pid: pid::Controller::new(pid::Parameters::default()),
|
||||
@ -52,14 +56,19 @@ impl ChannelState {
|
||||
}
|
||||
|
||||
pub fn get_adc(&self) -> Option<ElectricPotential> {
|
||||
let volts = self.adc_calibration.convert_data(self.adc_data?);
|
||||
Some(ElectricPotential::new::<volt>(volts))
|
||||
Some(self.adc_calibration.convert_data(self.adc_data?))
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
let r = self.get_adc()?.get::<volt>();
|
||||
// TODO:
|
||||
let r = ElectricalResistance::new::<ohm>(r);
|
||||
let r = self.get_sens()?;
|
||||
let temperature = self.sh.get_temperature(r);
|
||||
Some(temperature)
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ impl Channels {
|
||||
let pwm = pins.pwm;
|
||||
let mut channels = Channels { channel0, channel1, adc, pins_adc, pwm };
|
||||
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
|
||||
@ -172,7 +174,7 @@ impl Channels {
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
||||
);
|
||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||
ElectricPotential::new::<volt>(mv as f64 / 1000.0)
|
||||
ElectricPotential::new::<millivolt>(mv as f64)
|
||||
}
|
||||
1 => {
|
||||
let sample = self.pins_adc.convert(
|
||||
@ -180,7 +182,7 @@ impl Channels {
|
||||
stm32f4xx_hal::adc::config::SampleTime::Cycles_480
|
||||
);
|
||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||
ElectricPotential::new::<volt>(mv as f64 / 1000.0)
|
||||
ElectricPotential::new::<millivolt>(mv as f64)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
16
src/main.rs
16
src/main.rs
@ -168,7 +168,7 @@ fn main() -> ! {
|
||||
}
|
||||
Command::Show(ShowCommand::Input) => {
|
||||
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 dac_feedback = channels.read_dac_feedback(channel);
|
||||
|
||||
@ -179,9 +179,10 @@ fn main() -> ! {
|
||||
|
||||
let state = channels.channel_state(channel);
|
||||
let _ = writeln!(
|
||||
socket, "channel {}: t={} adc{}={} vref={} dac_feedback={} itec={} tec={} tec_u_meas={} r={:03}",
|
||||
channel,
|
||||
state.adc_time, channel, adc_data,
|
||||
socket, "channel {}: t={} adc{}={} adc_r={} vref={} dac_feedback={} itec={} tec={} tec_u_meas={} r={:03}",
|
||||
channel, state.adc_time,
|
||||
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),
|
||||
itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, 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, "- b={}", state.sh.b);
|
||||
let _ = writeln!(socket, "- r0={}", state.sh.r0.into_format_args(ohm, Abbreviation));
|
||||
match (state.get_adc(), state.get_temperature()) {
|
||||
(Some(adc), Some(temp)) => {
|
||||
match (state.get_adc(), state.get_sens(), state.get_temperature()) {
|
||||
(Some(adc), Some(sens), Some(temp)) => {
|
||||
let _ = writeln!(
|
||||
socket, "- adc={} temp={:.3}K",
|
||||
socket, "- adc={} r={} temp={:.3}K",
|
||||
adc.into_format_args(volt, Abbreviation),
|
||||
sens.into_format_args(ohm, Abbreviation),
|
||||
temp.into_format_args(degree_celsius, Abbreviation),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user