adc: complete temperature calculation

This commit is contained in:
Astro 2020-09-16 20:49:24 +02:00
parent dda1f2f0b4
commit 7d45d5ad32
4 changed files with 34 additions and 17 deletions

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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!(),
}

View File

@ -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),
);
}