Skip to content

Commit

Permalink
support sensor switching
Browse files Browse the repository at this point in the history
  • Loading branch information
jordens committed Sep 25, 2024
1 parent 04efd71 commit bd47b2b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 35 deletions.
60 changes: 39 additions & 21 deletions src/hardware/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use arbitrary_int::u2;
use miniconf::Tree;
use num_traits::float::Float;
use smlang::statemachine;
use strum::IntoEnumIterator;
use strum::{AsRefStr, EnumString, IntoEnumIterator};

use super::ad7172;

Expand Down Expand Up @@ -125,6 +125,15 @@ impl Convert for Linear {
}
}

impl Default for Linear {
fn default() -> Self {
Self {
offset: 0.,
gain: 1.,
}
}
}

/// Beta equation (Steinhart-Hart with c=0)
#[derive(Clone, Copy, Debug, Tree)]
pub struct Ntc {
Expand All @@ -133,6 +142,16 @@ pub struct Ntc {
beta_inv: f32, // inverse beta
}

impl Ntc {
pub fn new(t0: f32, r0: f32, r_ref: f32, beta: f32) -> Self {
Self {
t0_inv: 1.0 / (t0 + ZERO_C),
r_rel: r_ref / r0,
beta_inv: 1.0 / beta,
}
}
}

impl Convert for Ntc {
fn convert(&self, code: AdcCode) -> f64 {
// A f32 output dataformat leads to an output quantization of about 31 uK at T0.
Expand All @@ -146,12 +165,29 @@ impl Convert for Ntc {
}
}

impl Default for Ntc {
fn default() -> Self {
Self {
t0_inv: 1. / (25. + ZERO_C),
#[allow(clippy::eq_op)]
r_rel: 10.0e3 / 10.0e3,
beta_inv: 1. / 3988.,
}
}
}

/// DT-670 Silicon diode
#[derive(Clone, Copy, Debug, Tree)]
pub struct Dt670 {
v_ref: f32, // effective reference voltage (V)
}

impl Default for Dt670 {
fn default() -> Self {
Self { v_ref: 5. }
}
}

impl Convert for Dt670 {
fn convert(&self, code: AdcCode) -> f64 {
let voltage = f32::from(code) * self.v_ref;
Expand All @@ -166,36 +202,18 @@ impl Convert for Dt670 {
}

/// ADC configuration structure.
#[derive(Clone, Copy, Debug, Tree)]
#[derive(Clone, Copy, Debug, Tree, EnumString, AsRefStr)]
pub enum Sensor {
Linear(#[tree(depth = 1)] Linear),
Ntc(#[tree(depth = 1)] Ntc),
Dt670(#[tree(depth = 1)] Dt670),
}

impl Sensor {
pub fn linear(offset: f32, gain: f32) -> Self {
Self::Linear(Linear { offset, gain })
}

pub fn ntc(t0: f32, r0: f32, r_ref: f32, beta: f32) -> Self {
Self::Ntc(Ntc {
t0_inv: 1.0 / (t0 + ZERO_C),
r_rel: r_ref / r0,
beta_inv: 1.0 / beta,
})
}

pub fn dt670(v_ref: f32) -> Self {
Self::Dt670(Dt670 { v_ref })
}
}

const ZERO_C: f32 = 273.15; // 0°C in °K

impl Default for Sensor {
fn default() -> Self {
Self::linear(0.0, 1.0)
Self::Linear(Linear::default())
}
}

Expand Down
52 changes: 38 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use rtic_monotonics::Monotonic;
use rtic_sync::{channel::*, make_channel};

use fugit::ExtU32;
use miniconf::Tree;
use miniconf::{TreeDeserialize, TreeKey, TreeSerialize};
use net::{
data_stream::{FrameGenerator, StreamFormat, StreamTarget},
Alarm, NetworkState, NetworkUsers,
Expand All @@ -39,7 +39,26 @@ use serde::Serialize;
use settings::NetSettings;
use statistics::{Buffer, Statistics};

#[derive(Clone, Debug, Tree)]
#[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey, Default)]
pub struct InputChannel {
#[tree(typ="&str", get=Self::get_typ, validate=Self::validate_typ)]
typ: (),
#[tree(depth = 2)]
sensor: Sensor,
}

impl InputChannel {
fn get_typ(&self) -> Result<&str, &'static str> {
Ok(self.sensor.as_ref())
}

fn validate_typ(&mut self, value: &str) -> Result<(), &'static str> {
self.sensor = Sensor::try_from(value).or(Err("invalid sensor type"))?;
Ok(())
}
}

#[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey)]
pub struct ThermostatEem {
/// Specifies the telemetry output period in seconds.
///
Expand All @@ -51,8 +70,8 @@ pub struct ThermostatEem {
telemetry_period: f32,

/// Input sensor configuration
#[tree(depth = 5)]
input: [[Option<Sensor>; 4]; 4],
#[tree(depth = 6)]
input: [[Option<InputChannel>; 4]; 4],

/// Array of settings for the Thermostat output channels.
///
Expand Down Expand Up @@ -90,9 +109,9 @@ impl Default for ThermostatEem {
}
}

#[derive(Clone, Debug, Tree)]
#[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey)]
pub struct Settings {
#[tree(depth = 6)]
#[tree(depth = 7)]
pub thermostat_eem: ThermostatEem,

#[tree(depth = 1)]
Expand All @@ -112,7 +131,7 @@ impl settings::AppSettings for Settings {
}
}

impl serial_settings::Settings<7> for Settings {
impl serial_settings::Settings<8> for Settings {
fn reset(&mut self) {
*self = Self {
thermostat_eem: ThermostatEem::default(),
Expand Down Expand Up @@ -169,12 +188,14 @@ struct Data {

#[rtic::app(device = hal::stm32, peripherals = true, dispatchers=[DCMI, JPEG, SDMMC])]
mod app {
use hardware::adc::Ntc;

use super::*;

#[shared]
struct Shared {
usb: UsbDevice,
network: NetworkUsers<ThermostatEem, 6>,
network: NetworkUsers<ThermostatEem, 7>,
settings: Settings,
telemetry: Telemetry,
gpio: Gpio,
Expand All @@ -184,7 +205,7 @@ mod app {

#[local]
struct Local {
usb_terminal: SerialTerminal<Settings, 7>,
usb_terminal: SerialTerminal<Settings, 8>,
adc_sm: StateMachine<Adc>,
dac: Dac,
pwm: Pwm,
Expand All @@ -200,9 +221,9 @@ mod app {
let clock = SystemTimer::new(|| Systick::now().ticks());

// setup Thermostat hardware
let mut thermostat = hardware::setup::setup::<Settings, 7>(c.core, c.device, clock);
let mut thermostat = hardware::setup::setup::<Settings, 8>(c.core, c.device, clock);

for (sensor, mux) in thermostat
for (channel, mux) in thermostat
.settings
.thermostat_eem
.input
Expand All @@ -212,7 +233,10 @@ mod app {
{
if let Some(mux) = mux {
let r_ref = if mux.is_single_ended() { 5.0e3 } else { 10.0e3 };
*sensor = Some(Sensor::ntc(25.0, 10.0e3, r_ref, 3988.0));
*channel = Some(InputChannel {
sensor: Sensor::Ntc(Ntc::new(25.0, 10.0e3, r_ref, 3988.0)),
..Default::default()
});
}
}

Expand Down Expand Up @@ -373,10 +397,10 @@ mod app {
async fn process(mut c: process::Context, mut data: Receiver<'static, Data, 4>) {
while let Ok(Data { phy, ch, adc_code }) = data.recv().await {
let temp = c.shared.settings.lock(|settings| {
let sensor = settings.thermostat_eem.input[phy as usize][ch]
let input = settings.thermostat_eem.input[phy as usize][ch]
.as_ref()
.unwrap();
sensor.convert(adc_code)
input.sensor.convert(adc_code)
});
(
&mut c.shared.temperature,
Expand Down

0 comments on commit bd47b2b

Please sign in to comment.