Compare commits
No commits in common. "1849e6f5e7da91b06fbcddfed4e9638ad311dab4" and "4a1ce342a0b8ed12762805b6d2d5839e98213807" have entirely different histories.
1849e6f5e7
...
4a1ce342a0
|
@ -402,7 +402,6 @@ dependencies = [
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
"stm32-eth",
|
"stm32-eth",
|
||||||
"stm32f4xx-hal",
|
"stm32f4xx-hal",
|
||||||
"uom",
|
|
||||||
"usb-device",
|
"usb-device",
|
||||||
"usbd-serial",
|
"usbd-serial",
|
||||||
]
|
]
|
||||||
|
@ -419,16 +418,6 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uom"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8bb593f5252356bfb829112f8fca2d0982d48588d2d6bb5a92553b0dfc4c9aba"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "usb-device"
|
name = "usb-device"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
|
|
@ -32,7 +32,6 @@ num-traits = { version = "0.2", default-features = false, features = ["libm"] }
|
||||||
usb-device = "0.2"
|
usb-device = "0.2"
|
||||||
usbd-serial = "0.1"
|
usbd-serial = "0.1"
|
||||||
nb = "0.1"
|
nb = "0.1"
|
||||||
uom = { version = "0.29", default-features = false, features = ["autoconvert", "si", "f64"] }
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
stm32f4xx-hal = { git = "https://github.com/stm32-rs/stm32f4xx-hal.git" }
|
stm32f4xx-hal = { git = "https://github.com/stm32-rs/stm32f4xx-hal.git" }
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"0wa1xknnmmax278pwvcj134g62y00mr7k54cmvis64y27qlbg64h"
|
"06adm0s65h5qxb1a1gfjcwnl8lny52p90nrk3anj52iwnqlc5qwr"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
use stm32f4xx_hal::hal::digital::v2::OutputPin;
|
||||||
use crate::{
|
use crate::{
|
||||||
ad5680,
|
ad5680,
|
||||||
ad7172,
|
|
||||||
channel_state::ChannelState,
|
channel_state::ChannelState,
|
||||||
pins::{ChannelPins, ChannelPinSet},
|
pins::{ChannelPins, ChannelPinSet},
|
||||||
};
|
};
|
||||||
|
@ -28,8 +27,8 @@ pub struct Channel<C: ChannelPins> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ChannelPins> Channel<C> {
|
impl<C: ChannelPins> Channel<C> {
|
||||||
pub fn new(mut pins: ChannelPinSet<C>, adc_calibration: ad7172::ChannelCalibration) -> Self {
|
pub fn new(mut pins: ChannelPinSet<C>) -> Self {
|
||||||
let state = ChannelState::new(adc_calibration);
|
let state = ChannelState::default();
|
||||||
let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
|
let mut dac = ad5680::Dac::new(pins.dac_spi, pins.dac_sync);
|
||||||
let _ = dac.set(0);
|
let _ = dac.set(0);
|
||||||
// power up TEC
|
// power up TEC
|
||||||
|
|
|
@ -1,57 +1,43 @@
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use uom::si::{
|
|
||||||
f64::ElectricPotential,
|
|
||||||
electric_potential::volt,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ad7172,
|
ad7172,
|
||||||
pid,
|
pid,
|
||||||
steinhart_hart as sh,
|
steinhart_hart as sh,
|
||||||
|
units::Volts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
pub struct ChannelState {
|
pub struct ChannelState {
|
||||||
pub adc_data: Option<u32>,
|
pub adc_data: Option<u32>,
|
||||||
pub adc_calibration: ad7172::ChannelCalibration,
|
|
||||||
pub adc_time: Instant,
|
pub adc_time: Instant,
|
||||||
pub dac_value: ElectricPotential,
|
pub dac_value: Volts,
|
||||||
pub pid_engaged: bool,
|
pub pid_engaged: bool,
|
||||||
pub pid: pid::Controller,
|
pub pid: pid::Controller,
|
||||||
pub sh: sh::Parameters,
|
pub sh: sh::Parameters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelState {
|
impl Default for ChannelState {
|
||||||
pub fn new(adc_calibration: ad7172::ChannelCalibration) -> Self {
|
fn default() -> Self {
|
||||||
ChannelState {
|
ChannelState {
|
||||||
adc_data: None,
|
adc_data: None,
|
||||||
adc_calibration,
|
|
||||||
adc_time: Instant::from_secs(0),
|
adc_time: Instant::from_secs(0),
|
||||||
dac_value: ElectricPotential::new::<volt>(0.0),
|
dac_value: Volts(0.0),
|
||||||
pid_engaged: false,
|
pid_engaged: false,
|
||||||
pid: pid::Controller::new(pid::Parameters::default()),
|
pid: pid::Controller::new(pid::Parameters::default()),
|
||||||
sh: sh::Parameters::default(),
|
sh: sh::Parameters::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, now: Instant, adc_data: u32) {
|
impl ChannelState {
|
||||||
|
/// Update PID state on ADC input, calculate new DAC output
|
||||||
|
pub fn update_pid(&mut self, now: Instant, adc_data: u32) -> f64 {
|
||||||
self.adc_data = Some(adc_data);
|
self.adc_data = Some(adc_data);
|
||||||
self.adc_time = now;
|
self.adc_time = now;
|
||||||
}
|
|
||||||
|
|
||||||
/// Update PID state on ADC input, calculate new DAC output
|
|
||||||
pub fn update_pid(&mut self) -> f64 {
|
|
||||||
// Update PID controller
|
// Update PID controller
|
||||||
self.pid.update(self.get_temperature().unwrap())
|
let input = (adc_data as f64) / (ad7172::MAX_VALUE as f64);
|
||||||
}
|
let temperature = self.sh.get_temperature(input);
|
||||||
|
self.pid.update(temperature)
|
||||||
pub fn get_adc(&self) -> Option<ElectricPotential> {
|
|
||||||
let volts = self.adc_calibration.convert_data(self.adc_data?);
|
|
||||||
Some(ElectricPotential::new::<volt>(volts))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_temperature(&self) -> Option<f64> {
|
|
||||||
let r = self.get_adc()?.get::<volt>();
|
|
||||||
let temperature = self.sh.get_temperature(r);
|
|
||||||
Some(temperature)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use uom::si::{
|
|
||||||
f64::ElectricPotential,
|
|
||||||
electric_potential::{millivolt, volt},
|
|
||||||
};
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use crate::{
|
use crate::{
|
||||||
ad5680,
|
ad5680,
|
||||||
|
@ -10,6 +6,7 @@ use crate::{
|
||||||
channel::{Channel, Channel0, Channel1},
|
channel::{Channel, Channel0, Channel1},
|
||||||
channel_state::ChannelState,
|
channel_state::ChannelState,
|
||||||
pins,
|
pins,
|
||||||
|
units::Volts,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CHANNELS: usize = 2;
|
pub const CHANNELS: usize = 2;
|
||||||
|
@ -26,23 +23,20 @@ pub struct Channels {
|
||||||
|
|
||||||
impl Channels {
|
impl Channels {
|
||||||
pub fn new(pins: pins::Pins) -> Self {
|
pub fn new(pins: pins::Pins) -> Self {
|
||||||
|
let channel0 = Channel::new(pins.channel0);
|
||||||
|
let channel1 = Channel::new(pins.channel1);
|
||||||
|
let pins_adc = pins.pins_adc;
|
||||||
|
let pwm = pins.pwm;
|
||||||
|
|
||||||
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
|
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
|
||||||
// Feature not used
|
// Feature not used
|
||||||
adc.set_sync_enable(false).unwrap();
|
adc.set_sync_enable(false).unwrap();
|
||||||
|
|
||||||
// Setup channels and start ADC
|
// Setup channels and start ADC
|
||||||
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
|
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
|
||||||
let adc_calibration0 = adc.get_calibration(0)
|
|
||||||
.expect("adc_calibration0");
|
|
||||||
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
|
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
|
||||||
let adc_calibration1 = adc.get_calibration(1)
|
|
||||||
.expect("adc_calibration1");
|
|
||||||
adc.start_continuous_conversion().unwrap();
|
adc.start_continuous_conversion().unwrap();
|
||||||
|
|
||||||
let mut channel0 = Channel::new(pins.channel0, adc_calibration0);
|
|
||||||
let mut channel1 = Channel::new(pins.channel1, adc_calibration1);
|
|
||||||
let pins_adc = pins.pins_adc;
|
|
||||||
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 {
|
||||||
channels.calibrate_dac_value(channel);
|
channels.calibrate_dac_value(channel);
|
||||||
|
@ -75,7 +69,7 @@ impl Channels {
|
||||||
};
|
};
|
||||||
if let Some(dac_value) = dac_value {
|
if let Some(dac_value) = dac_value {
|
||||||
// Forward PID output to i_set DAC
|
// Forward PID output to i_set DAC
|
||||||
self.set_dac(channel.into(), ElectricPotential::new::<volt>(dac_value));
|
self.set_dac(channel.into(), Volts(dac_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
channel
|
channel
|
||||||
|
@ -83,13 +77,13 @@ impl Channels {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// i_set DAC
|
/// i_set DAC
|
||||||
pub fn set_dac(&mut self, channel: usize, voltage: ElectricPotential) {
|
pub fn set_dac(&mut self, channel: usize, voltage: Volts) {
|
||||||
let dac_factor = match channel.into() {
|
let dac_factor = match channel.into() {
|
||||||
0 => self.channel0.dac_factor,
|
0 => self.channel0.dac_factor,
|
||||||
1 => self.channel1.dac_factor,
|
1 => self.channel1.dac_factor,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let value = (voltage.get::<volt>() * dac_factor) as u32;
|
let value = (voltage.0 * dac_factor) as u32;
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
self.channel0.dac.set(value).unwrap();
|
self.channel0.dac.set(value).unwrap();
|
||||||
|
@ -103,7 +97,7 @@ impl Channels {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_dac_feedback(&mut self, channel: usize) -> ElectricPotential {
|
pub fn read_dac_feedback(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -112,7 +106,7 @@ impl Channels {
|
||||||
);
|
);
|
||||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||||
info!("dac0_fb: {}/{:03X}", mv, sample);
|
info!("dac0_fb: {}/{:03X}", mv, sample);
|
||||||
ElectricPotential::new::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -121,25 +115,25 @@ impl Channels {
|
||||||
);
|
);
|
||||||
let mv = self.pins_adc.sample_to_millivolts(sample);
|
let mv = self.pins_adc.sample_to_millivolts(sample);
|
||||||
info!("dac1_fb: {}/{:03X}", mv, sample);
|
info!("dac1_fb: {}/{:03X}", mv, sample);
|
||||||
ElectricPotential::new::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_dac_feedback_until_stable(&mut self, channel: usize, tolerance: ElectricPotential) -> ElectricPotential {
|
pub fn read_dac_feedback_until_stable(&mut self, channel: usize, tolerance: f64) -> Volts {
|
||||||
let mut prev = self.read_dac_feedback(channel);
|
let mut prev = self.read_dac_feedback(channel);
|
||||||
loop {
|
loop {
|
||||||
let current = self.read_dac_feedback(channel);
|
let current = self.read_dac_feedback(channel);
|
||||||
use num_traits::float::Float;
|
use num_traits::float::Float;
|
||||||
if (current - prev).abs() < tolerance {
|
if (current - prev).0.abs() < tolerance {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
prev = current;
|
prev = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_itec(&mut self, channel: usize) -> ElectricPotential {
|
pub fn read_itec(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -147,7 +141,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::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -155,14 +149,14 @@ 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::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// should be 1.5V
|
/// should be 1.5V
|
||||||
pub fn read_vref(&mut self, channel: usize) -> ElectricPotential {
|
pub fn read_vref(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -170,7 +164,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)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -178,13 +172,13 @@ 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)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_tec_u_meas(&mut self, channel: usize) -> ElectricPotential {
|
pub fn read_tec_u_meas(&mut self, channel: usize) -> Volts {
|
||||||
match channel {
|
match channel {
|
||||||
0 => {
|
0 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -192,7 +186,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::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let sample = self.pins_adc.convert(
|
let sample = self.pins_adc.convert(
|
||||||
|
@ -200,7 +194,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::<millivolt>(mv as f64)
|
Volts(mv as f64 / 1000.0)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -211,9 +205,9 @@ impl Channels {
|
||||||
/// These loops perform a width-first search for the DAC setting
|
/// These loops perform a width-first search for the DAC setting
|
||||||
/// that will produce a `target_voltage`.
|
/// that will produce a `target_voltage`.
|
||||||
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
pub fn calibrate_dac_value(&mut self, channel: usize) {
|
||||||
let target_voltage = ElectricPotential::new::<volt>(2.5);
|
let target_voltage = Volts(2.5);
|
||||||
let mut start_value = 1;
|
let mut start_value = 1;
|
||||||
let mut best_error = ElectricPotential::new::<volt>(100.0);
|
let mut best_error = Volts(100.0);
|
||||||
|
|
||||||
for step in (0..18).rev() {
|
for step in (0..18).rev() {
|
||||||
let mut prev_value = start_value;
|
let mut prev_value = start_value;
|
||||||
|
@ -228,15 +222,15 @@ impl Channels {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let dac_feedback = self.read_dac_feedback_until_stable(channel, ElectricPotential::new::<volt>(0.001));
|
let dac_feedback = self.read_dac_feedback_until_stable(channel, 0.001);
|
||||||
let error = target_voltage - dac_feedback;
|
let error = target_voltage - dac_feedback;
|
||||||
if error < ElectricPotential::new::<volt>(0.0) {
|
if error < Volts(0.0) {
|
||||||
break;
|
break;
|
||||||
} else if error < best_error {
|
} else if error < best_error {
|
||||||
best_error = error;
|
best_error = error;
|
||||||
start_value = prev_value;
|
start_value = prev_value;
|
||||||
|
|
||||||
let dac_factor = value as f64 / dac_feedback.get::<volt>();
|
let dac_factor = value as f64 / dac_feedback.0;
|
||||||
match channel {
|
match channel {
|
||||||
0 => self.channel0.dac_factor = dac_factor,
|
0 => self.channel0.dac_factor = dac_factor,
|
||||||
1 => self.channel1.dac_factor = dac_factor,
|
1 => self.channel1.dac_factor = dac_factor,
|
||||||
|
@ -249,6 +243,6 @@ impl Channels {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
self.set_dac(channel, ElectricPotential::new::<volt>(0.0));
|
self.set_dac(channel, Volts(0.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
src/main.rs
40
src/main.rs
|
@ -28,18 +28,6 @@ use smoltcp::{
|
||||||
time::Instant,
|
time::Instant,
|
||||||
wire::EthernetAddress,
|
wire::EthernetAddress,
|
||||||
};
|
};
|
||||||
use uom::{
|
|
||||||
fmt::DisplayStyle::Abbreviation,
|
|
||||||
si::{
|
|
||||||
f64::{
|
|
||||||
ElectricPotential,
|
|
||||||
ElectricalResistance,
|
|
||||||
},
|
|
||||||
electric_current::ampere,
|
|
||||||
electric_potential::volt,
|
|
||||||
electrical_resistance::ohm,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
mod init_log;
|
mod init_log;
|
||||||
use init_log::init_log;
|
use init_log::init_log;
|
||||||
|
@ -57,6 +45,8 @@ use session::{Session, SessionOutput};
|
||||||
mod command_parser;
|
mod command_parser;
|
||||||
use command_parser::{Command, ShowCommand, PwmPin};
|
use command_parser::{Command, ShowCommand, PwmPin};
|
||||||
mod timer;
|
mod timer;
|
||||||
|
mod units;
|
||||||
|
use units::{Ohms, Volts};
|
||||||
mod pid;
|
mod pid;
|
||||||
mod steinhart_hart;
|
mod steinhart_hart;
|
||||||
mod channels;
|
mod channels;
|
||||||
|
@ -119,6 +109,10 @@ fn main() -> ! {
|
||||||
usb::State::setup(usb);
|
usb::State::setup(usb);
|
||||||
|
|
||||||
let mut channels = Channels::new(pins);
|
let mut channels = Channels::new(pins);
|
||||||
|
let adc_calibration = [
|
||||||
|
channels.adc.get_calibration(0).unwrap(),
|
||||||
|
channels.adc.get_calibration(1).unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
#[cfg(not(feature = "generate-hwaddr"))]
|
#[cfg(not(feature = "generate-hwaddr"))]
|
||||||
let hwaddr = EthernetAddress(NET_HWADDR);
|
let hwaddr = EthernetAddress(NET_HWADDR);
|
||||||
|
@ -171,19 +165,19 @@ fn main() -> ! {
|
||||||
let dac_feedback = channels.read_dac_feedback(channel);
|
let dac_feedback = channels.read_dac_feedback(channel);
|
||||||
|
|
||||||
let itec = channels.read_itec(channel);
|
let itec = channels.read_itec(channel);
|
||||||
let tec_i = -(itec - ElectricPotential::new::<volt>(1.5)) / ElectricalResistance::new::<ohm>(0.4);
|
let tec_i = -(itec - Volts(1.5)) / Ohms(0.4);
|
||||||
|
|
||||||
let tec_u_meas = channels.read_tec_u_meas(channel);
|
let tec_u_meas = channels.read_tec_u_meas(channel);
|
||||||
|
|
||||||
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_raw{}=0x{:06X} adc{}={:.3}V vref={} dac_feedback={} itec={} tec={} tec_u_meas={}",
|
||||||
channel,
|
channel,
|
||||||
state.adc_time, channel, adc_data,
|
state.adc_time, channel, adc_data,
|
||||||
vref.into_format_args(volt, Abbreviation), dac_feedback.into_format_args(volt, Abbreviation),
|
channel, adc_calibration[channel].convert_data(adc_data),
|
||||||
itec.into_format_args(volt, Abbreviation), tec_i.into_format_args(ampere, Abbreviation),
|
vref, dac_feedback,
|
||||||
tec_u_meas.into_format_args(volt, Abbreviation),
|
itec, tec_i,
|
||||||
(tec_u_meas / tec_i).into_format_args(ohm, Abbreviation),
|
tec_u_meas,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let _ = writeln!(socket, "channel {}: no adc input", channel);
|
let _ = writeln!(socket, "channel {}: no adc input", channel);
|
||||||
|
@ -225,7 +219,7 @@ fn main() -> ! {
|
||||||
channel,
|
channel,
|
||||||
if state.pid_engaged { "engaged" } else { "disengaged" }
|
if state.pid_engaged { "engaged" } else { "disengaged" }
|
||||||
);
|
);
|
||||||
let _ = writeln!(socket, "- i_set={}", state.dac_value.into_format_args(volt, Abbreviation));
|
let _ = writeln!(socket, "- i_set={}", state.dac_value);
|
||||||
fn show_pwm_channel<S, P>(mut socket: S, name: &str, pin: &P)
|
fn show_pwm_channel<S, P>(mut socket: S, name: &str, pin: &P)
|
||||||
where
|
where
|
||||||
S: core::fmt::Write,
|
S: core::fmt::Write,
|
||||||
|
@ -293,11 +287,11 @@ fn main() -> ! {
|
||||||
Command::Pwm { channel, pin: PwmPin::ISet, duty } => {
|
Command::Pwm { channel, pin: PwmPin::ISet, duty } => {
|
||||||
channels.channel_state(channel).pid_engaged = false;
|
channels.channel_state(channel).pid_engaged = false;
|
||||||
leds.g3.off();
|
leds.g3.off();
|
||||||
let voltage = ElectricPotential::new::<volt>(duty);
|
let voltage = Volts(duty);
|
||||||
channels.set_dac(channel, voltage);
|
channels.set_dac(channel, voltage);
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "channel {}: PWM duty cycle manually set to {}",
|
socket, "channel {}: PWM duty cycle manually set to {}",
|
||||||
channel, voltage.into_format_args(volt, Abbreviation),
|
channel, voltage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Command::Pwm { channel, pin, duty } => {
|
Command::Pwm { channel, pin, duty } => {
|
||||||
|
@ -394,9 +388,9 @@ fn main() -> ! {
|
||||||
let state = &mut channels.channel_state(usize::from(channel));
|
let state = &mut channels.channel_state(usize::from(channel));
|
||||||
let adc_data = state.adc_data.unwrap_or(0);
|
let adc_data = state.adc_data.unwrap_or(0);
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "t={} raw{}=0x{:06X} value={}",
|
socket, "t={} raw{}=0x{:06X} value={:.3}V",
|
||||||
state.adc_time, channel, adc_data,
|
state.adc_time, channel, adc_data,
|
||||||
state.get_adc().unwrap().into_format_args(volt, Abbreviation),
|
adc_calibration[channel].convert_data(adc_data),
|
||||||
).map(|_| {
|
).map(|_| {
|
||||||
session.mark_report_sent(channel);
|
session.mark_report_sent(channel);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
use core::{
|
||||||
|
fmt,
|
||||||
|
ops::{Add, Div, Neg, Sub},
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! impl_add_sub {
|
||||||
|
($Type: ident) => {
|
||||||
|
impl Add<$Type> for $Type {
|
||||||
|
type Output = $Type;
|
||||||
|
fn add(self, rhs: $Type) -> $Type {
|
||||||
|
$Type(self.0 + rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<$Type> for $Type {
|
||||||
|
type Output = $Type;
|
||||||
|
fn sub(self, rhs: $Type) -> $Type {
|
||||||
|
$Type(self.0 - rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for $Type {
|
||||||
|
type Output = $Type;
|
||||||
|
fn neg(self) -> $Type {
|
||||||
|
$Type(-self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub struct Volts(pub f64);
|
||||||
|
impl_add_sub!(Volts);
|
||||||
|
|
||||||
|
impl fmt::Display for Volts {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:.3}V", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div<Ohms> for Volts {
|
||||||
|
type Output = Amps;
|
||||||
|
fn div(self, rhs: Ohms) -> Amps {
|
||||||
|
Amps(self.0 / rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub struct Amps(pub f64);
|
||||||
|
impl_add_sub!(Amps);
|
||||||
|
|
||||||
|
impl fmt::Display for Amps {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:.3}A", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub struct Ohms(pub f64);
|
||||||
|
impl_add_sub!(Ohms);
|
||||||
|
|
||||||
|
impl fmt::Display for Ohms {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:.3}Ω", self.0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue