adc: complete temperature calculation

pull/20/head
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, 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)
} }
} }

View File

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

View File

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

View File

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