Compare commits

..

1 Commits

Author SHA1 Message Date
3ec5e185ee Move PwmLimits into its own file 2024-10-21 10:19:07 +08:00
10 changed files with 136 additions and 137 deletions

View File

@ -93,15 +93,15 @@ Send commands as simple text string terminated by `\n`. Responses are
formatted as line-delimited JSON. formatted as line-delimited JSON.
| Syntax | Function | | Syntax | Function |
|-------------------------------------------|-------------------------------------------------------------------------------| |------------------------------------------- |-------------------------------------------------------------------------------|
| `report` | Show latest report of channel parameters (see *Reports* section) | | `report` | Show latest report of channel parameters (see *Reports* section) |
| `output` | Show current output settings | | `pwm` | Show current PWM settings |
| `output <0/1> max_i_pos <amp>` | Set maximum positive output current, clamped to [0, 2] | | `pwm <0/1> max_i_pos <amp>` | Set maximum positive output current, clamped to [0, 2] |
| `output <0/1> max_i_neg <amp>` | Set maximum negative output current, clamped to [0, 2] | | `pwm <0/1> max_i_neg <amp>` | Set maximum negative output current, clamped to [0, 2] |
| `output <0/1> max_v <volt>` | Set maximum output voltage, clamped to [0, 4] | | `pwm <0/1> max_v <volt>` | Set maximum output voltage, clamped to [0, 4] |
| `output <0/1> i_set <amp>` | Disengage PID, set fixed output current, clamped to [-2, 2] | | `pwm <0/1> i_set <amp>` | Disengage PID, set fixed output current, clamped to [-2, 2] |
| `output <0/1> polarity <normal/reversed>` | Set output current polarity, with 'normal' being the front panel polarity | | `pwm <0/1> polarity <normal/reversed>` | Set output current polarity, with 'normal' being the front panel polarity |
| `output <0/1> pid` | Let output current to be controlled by the PID | | `pwm <0/1> pid` | Let output current to be controlled by the PID |
| `center <0/1> <volt>` | Set the MAX1968 0A-centerpoint to the specified fixed voltage | | `center <0/1> <volt>` | Set the MAX1968 0A-centerpoint to the specified fixed voltage |
| `center <0/1> vref` | Set the MAX1968 0A-centerpoint to measure from VREF | | `center <0/1> vref` | Set the MAX1968 0A-centerpoint to measure from VREF |
| `pid` | Show PID configuration | | `pid` | Show PID configuration |
@ -183,7 +183,7 @@ postfilter rate can be tuned with the `postfilter` command.
When using a TEC module with the Thermostat, the Thermostat expects the thermal load (where the thermistor is located) to cool down with a positive software current set point, and heat up with a negative current set point. When using a TEC module with the Thermostat, the Thermostat expects the thermal load (where the thermistor is located) to cool down with a positive software current set point, and heat up with a negative current set point.
If the Thermostat is used for temperature control with the Sinara 5432 DAC "Zotino", and is connected via an IDC cable, the TEC polarity may need to be reversed with the `output <ch> polarity reversed` TCP command. If the Thermostat is used for temperature control with the Sinara 5432 DAC "Zotino", and is connected via an IDC cable, the TEC polarity may need to be reversed with the `pwm <ch> polarity reversed` TCP command.
Testing heat flow direction with a low set current is recommended before installation of the TEC module. Testing heat flow direction with a low set current is recommended before installation of the TEC module.
@ -192,7 +192,7 @@ Testing heat flow direction with a low set current is recommended before install
Each MAX1968 TEC driver has analog/PWM inputs for setting Each MAX1968 TEC driver has analog/PWM inputs for setting
output limits. output limits.
Use the `output` command to see current settings and maximum values. Use the `pwm` command to see current settings and maximum values.
| Limit | Unit | Description | | Limit | Unit | Description |
| --- | :---: | --- | | --- | :---: | --- |
@ -203,28 +203,28 @@ Use the `output` command to see current settings and maximum values.
Example: set the maximum voltage of channel 0 to 1.5 V. Example: set the maximum voltage of channel 0 to 1.5 V.
``` ```
output 0 max_v 1.5 pwm 0 max_v 1.5
``` ```
Example: set the maximum negative current of channel 0 to -3 A. Example: set the maximum negative current of channel 0 to -3 A.
``` ```
output 0 max_i_neg 3 pwm 0 max_i_neg 3
``` ```
Example: set the maximum positive current of channel 1 to 3 A. Example: set the maximum positive current of channel 1 to 3 A.
``` ```
output 0 max_i_pos 3 pwm 0 max_i_pos 3
``` ```
### Open-loop mode ### Open-loop mode
To manually control TEC output current, set a fixed output current with To manually control TEC output current, set a fixed output current with
the `output` command. Doing so will disengage the PID control for that the `pwm` command. Doing so will disengage the PID control for that
channel. channel.
Example: set output current of channel 0 to 0 A. Example: set output current of channel 0 to 0 A.
``` ```
output 0 i_set 0 pwm 0 i_set 0
``` ```
## PID-stabilized temperature control ## PID-stabilized temperature control
@ -237,7 +237,7 @@ pid 0 target 20
Enter closed-loop mode by switching control of the TEC output current Enter closed-loop mode by switching control of the TEC output current
of channel 0 to the PID algorithm: of channel 0 to the PID algorithm:
``` ```
output 0 pid pwm 0 pid
``` ```
## LED indicators ## LED indicators

View File

@ -253,9 +253,9 @@ def main():
tuner_out = tuner.output() tuner_out = tuner.output()
tec.set_param("output", channel, "i_set", tuner_out) tec.set_param("pwm", channel, "i_set", tuner_out)
tec.set_param("output", channel, "i_set", 0) tec.set_param("pwm", channel, "i_set", 0)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -2,9 +2,9 @@ from pytec.client import Client
tec = Client() #(host="localhost", port=6667) tec = Client() #(host="localhost", port=6667)
tec.set_param("s-h", 1, "t0", 20) tec.set_param("s-h", 1, "t0", 20)
print(tec.get_output()) print(tec.get_pwm())
print(tec.get_pid()) print(tec.get_pid())
print(tec.get_output()) print(tec.get_pwm())
print(tec.get_postfilter()) print(tec.get_postfilter())
print(tec.get_steinhart_hart()) print(tec.get_steinhart_hart())
for data in tec.report_mode(): for data in tec.report_mode():

View File

@ -13,11 +13,11 @@ class Client:
self._check_zero_limits() self._check_zero_limits()
def _check_zero_limits(self): def _check_zero_limits(self):
output_report = self.get_output() pwm_report = self.get_pwm()
for output_channel in output_report: for pwm_channel in pwm_report:
for limit in ["max_i_neg", "max_i_pos", "max_v"]: for limit in ["max_i_neg", "max_i_pos", "max_v"]:
if output_channel[limit] == 0.0: if pwm_channel[limit] == 0.0:
logging.warning("`{}` limit is set to zero on channel {}".format(limit, output_channel["channel"])) logging.warning("`{}` limit is set to zero on channel {}".format(limit, pwm_channel["channel"]))
def _read_line(self): def _read_line(self):
# read more lines # read more lines
@ -47,8 +47,8 @@ class Client:
result[int(item["channel"])] = item result[int(item["channel"])] = item
return result return result
def get_output(self): def get_pwm(self):
"""Retrieve output limits for the TEC """Retrieve PWM limits for the TEC
Example:: Example::
[{'channel': 0, [{'channel': 0,
@ -67,7 +67,7 @@ class Client:
'polarity': 'normal', 'polarity': 'normal',
] ]
""" """
return self._get_conf("output") return self._get_conf("pwm")
def get_pid(self): def get_pid(self):
"""Retrieve PID control state """Retrieve PID control state
@ -144,7 +144,7 @@ class Client:
"""Set configuration parameters """Set configuration parameters
Examples:: Examples::
tec.set_param("output", 0, "max_v", 2.0) tec.set_param("pwm", 0, "max_v", 2.0)
tec.set_param("pid", 1, "output_max", 2.5) tec.set_param("pid", 1, "output_max", 2.5)
tec.set_param("s-h", 0, "t0", 20.0) tec.set_param("s-h", 0, "t0", 20.0)
tec.set_param("center", 0, "vref") tec.set_param("center", 0, "vref")
@ -161,7 +161,7 @@ class Client:
def power_up(self, channel, target): def power_up(self, channel, target):
"""Start closed-loop mode""" """Start closed-loop mode"""
self.set_param("pid", channel, "target", value=target) self.set_param("pid", channel, "target", value=target)
self.set_param("output", channel, "pid") self.set_param("pwm", channel, "pid")
def save_config(self): def save_config(self):
"""Save current configuration to EEPROM""" """Save current configuration to EEPROM"""

View File

@ -5,7 +5,6 @@ use crate::{
pwm_limits::PwmLimits, pwm_limits::PwmLimits,
steinhart_hart as sh, steinhart_hart as sh,
}; };
use num_traits::Zero;
use smoltcp::time::{Duration, Instant}; use smoltcp::time::{Duration, Instant};
use uom::si::{ use uom::si::{
electric_current::ampere, electric_current::ampere,
@ -49,9 +48,9 @@ impl ChannelState {
dac_value: ElectricPotential::new::<volt>(0.0), dac_value: ElectricPotential::new::<volt>(0.0),
i_set: ElectricCurrent::new::<ampere>(0.0), i_set: ElectricCurrent::new::<ampere>(0.0),
pwm_limits: PwmLimits { pwm_limits: PwmLimits {
max_v: ElectricPotential::zero(), max_v: 0.0,
max_i_pos: ElectricCurrent::zero(), max_i_pos: 0.0,
max_i_neg: ElectricCurrent::zero(), max_i_neg: 0.0,
}, },
pid_engaged: false, pid_engaged: false,
pid: pid::Controller::new(pid::Parameters::default()), pid: pid::Controller::new(pid::Parameters::default()),

View File

@ -144,7 +144,7 @@ impl Channels {
voltage voltage
} }
pub fn get_i_set(&mut self, channel: usize) -> ElectricCurrent { pub fn get_i(&mut self, channel: usize) -> ElectricCurrent {
let i_set = self.channel_state(channel).i_set; let i_set = self.channel_state(channel).i_set;
i_set i_set
} }
@ -364,15 +364,15 @@ impl Channels {
} }
pub fn get_max_v(&mut self, channel: usize) -> ElectricPotential { pub fn get_max_v(&mut self, channel: usize) -> ElectricPotential {
self.channel_state(channel).pwm_limits.max_v ElectricPotential::new::<volt>(self.channel_state(channel).pwm_limits.max_v)
} }
pub fn get_max_i_pos(&mut self, channel: usize) -> ElectricCurrent { pub fn get_max_i_pos(&mut self, channel: usize) -> ElectricCurrent {
self.channel_state(channel).pwm_limits.max_i_pos ElectricCurrent::new::<ampere>(self.channel_state(channel).pwm_limits.max_i_pos)
} }
pub fn get_max_i_neg(&mut self, channel: usize) -> ElectricCurrent { pub fn get_max_i_neg(&mut self, channel: usize) -> ElectricCurrent {
self.channel_state(channel).pwm_limits.max_i_neg ElectricCurrent::new::<ampere>(self.channel_state(channel).pwm_limits.max_i_neg)
} }
// Get current passing through TEC // Get current passing through TEC
@ -420,7 +420,7 @@ impl Channels {
let max_v = max_v.min(MAX_TEC_V).max(ElectricPotential::zero()); let max_v = max_v.min(MAX_TEC_V).max(ElectricPotential::zero());
let duty = (max_v / max).get::<ratio>(); let duty = (max_v / max).get::<ratio>();
let duty = self.set_pwm(channel, PwmPin::MaxV, duty); let duty = self.set_pwm(channel, PwmPin::MaxV, duty);
self.channel_state(channel).pwm_limits.max_v = max_v; self.channel_state(channel).pwm_limits.max_v = max_v.get::<volt>();
(duty * max, max) (duty * max, max)
} }
@ -436,7 +436,7 @@ impl Channels {
Polarity::Normal => self.set_pwm(channel, PwmPin::MaxIPos, duty), Polarity::Normal => self.set_pwm(channel, PwmPin::MaxIPos, duty),
Polarity::Reversed => self.set_pwm(channel, PwmPin::MaxINeg, duty), Polarity::Reversed => self.set_pwm(channel, PwmPin::MaxINeg, duty),
}; };
self.channel_state(channel).pwm_limits.max_i_pos = max_i_pos; self.channel_state(channel).pwm_limits.max_i_pos = max_i_pos.get::<ampere>();
(duty * MAX_TEC_I_DUTY_TO_CURRENT_RATE, max) (duty * MAX_TEC_I_DUTY_TO_CURRENT_RATE, max)
} }
@ -452,7 +452,7 @@ impl Channels {
Polarity::Normal => self.set_pwm(channel, PwmPin::MaxINeg, duty), Polarity::Normal => self.set_pwm(channel, PwmPin::MaxINeg, duty),
Polarity::Reversed => self.set_pwm(channel, PwmPin::MaxIPos, duty), Polarity::Reversed => self.set_pwm(channel, PwmPin::MaxIPos, duty),
}; };
self.channel_state(channel).pwm_limits.max_i_neg = max_i_neg; self.channel_state(channel).pwm_limits.max_i_neg = max_i_neg.get::<ampere>();
(duty * MAX_TEC_I_DUTY_TO_CURRENT_RATE, max) (duty * MAX_TEC_I_DUTY_TO_CURRENT_RATE, max)
} }
@ -470,7 +470,7 @@ impl Channels {
} }
fn report(&mut self, channel: usize) -> Report { fn report(&mut self, channel: usize) -> Report {
let i_set = self.get_i_set(channel); let i_set = self.get_i(channel);
let i_tec = self.adc_read(channel, PinsAdcReadTarget::ITec, 16); let i_tec = self.adc_read(channel, PinsAdcReadTarget::ITec, 16);
let tec_i = self.get_tec_i(channel); let tec_i = self.get_tec_i(channel);
let dac_value = self.get_dac(channel); let dac_value = self.get_dac(channel);
@ -521,11 +521,11 @@ impl Channels {
false false
} }
fn output_summary(&mut self, channel: usize) -> OutputSummary { fn pwm_summary(&mut self, channel: usize) -> PwmSummary {
OutputSummary { PwmSummary {
channel, channel,
center: CenterPointJson(self.channel_state(channel).center.clone()), center: CenterPointJson(self.channel_state(channel).center.clone()),
i_set: self.get_i_set(channel), i_set: self.get_i(channel),
max_v: self.get_max_v(channel), max_v: self.get_max_v(channel),
max_i_pos: self.get_max_i_pos(channel), max_i_pos: self.get_max_i_pos(channel),
max_i_neg: self.get_max_i_neg(channel), max_i_neg: self.get_max_i_neg(channel),
@ -533,10 +533,10 @@ impl Channels {
} }
} }
pub fn output_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> { pub fn pwm_summaries_json(&mut self) -> Result<JsonBuffer, serde_json_core::ser::Error> {
let mut summaries = Vec::<_, U2>::new(); let mut summaries = Vec::<_, U2>::new();
for channel in 0..CHANNELS { for channel in 0..CHANNELS {
let _ = summaries.push(self.output_summary(channel)); let _ = summaries.push(self.pwm_summary(channel));
} }
serde_json_core::to_vec(&summaries) serde_json_core::to_vec(&summaries)
} }
@ -630,7 +630,7 @@ impl Serialize for PolarityJson {
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct OutputSummary { pub struct PwmSummary {
channel: usize, channel: usize,
center: CenterPointJson, center: CenterPointJson,
i_set: ElectricCurrent, i_set: ElectricCurrent,

View File

@ -19,11 +19,7 @@ use uom::si::{
electric_current::ampere, electric_current::ampere,
electric_potential::volt, electric_potential::volt,
electrical_resistance::ohm, electrical_resistance::ohm,
f64::{ f64::{ElectricCurrent, ElectricPotential, ElectricalResistance, ThermodynamicTemperature},
ElectricCurrent, ElectricPotential, ElectricalResistance, TemperatureInterval,
ThermodynamicTemperature,
},
temperature_interval::kelvin,
thermodynamic_temperature::degree_celsius, thermodynamic_temperature::degree_celsius,
}; };
@ -100,7 +96,7 @@ impl Handler {
} }
fn show_pwm(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> { fn show_pwm(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> {
match channels.output_summaries_json() { match channels.pwm_summaries_json() {
Ok(buf) => { Ok(buf) => {
send_line(socket, &buf); send_line(socket, &buf);
} }
@ -210,7 +206,7 @@ impl Handler {
channel: usize, channel: usize,
center: CenterPoint, center: CenterPoint,
) -> Result<Handler, Error> { ) -> Result<Handler, Error> {
let i_set = channels.get_i_set(channel); let i_set = channels.get_i(channel);
let state = channels.channel_state(channel); let state = channels.channel_state(channel);
state.center = center; state.center = center;
if !state.pid_engaged { if !state.pid_engaged {
@ -252,7 +248,7 @@ impl Handler {
use super::command_parser::ShParameter::*; use super::command_parser::ShParameter::*;
match parameter { match parameter {
T0 => sh.t0 = ThermodynamicTemperature::new::<degree_celsius>(value), T0 => sh.t0 = ThermodynamicTemperature::new::<degree_celsius>(value),
B => sh.b = TemperatureInterval::new::<kelvin>(value), B => sh.b = value,
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value), R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
} }
send_line(socket, b"{}"); send_line(socket, b"{}");
@ -479,17 +475,17 @@ impl Handler {
Command::Quit => Ok(Handler::CloseSocket), Command::Quit => Ok(Handler::CloseSocket),
Command::Show(ShowCommand::Input) => Handler::show_report(socket, channels), Command::Show(ShowCommand::Input) => Handler::show_report(socket, channels),
Command::Show(ShowCommand::Pid) => Handler::show_pid(socket, channels), Command::Show(ShowCommand::Pid) => Handler::show_pid(socket, channels),
Command::Show(ShowCommand::Output) => Handler::show_pwm(socket, channels), Command::Show(ShowCommand::Pwm) => Handler::show_pwm(socket, channels),
Command::Show(ShowCommand::SteinhartHart) => { Command::Show(ShowCommand::SteinhartHart) => {
Handler::show_steinhart_hart(socket, channels) Handler::show_steinhart_hart(socket, channels)
} }
Command::Show(ShowCommand::PostFilter) => Handler::show_post_filter(socket, channels), Command::Show(ShowCommand::PostFilter) => Handler::show_post_filter(socket, channels),
Command::Show(ShowCommand::Ipv4) => Handler::show_ipv4(socket, ipv4_config), Command::Show(ShowCommand::Ipv4) => Handler::show_ipv4(socket, ipv4_config),
Command::OutputPid { channel } => Handler::engage_pid(socket, channels, channel), Command::PwmPid { channel } => Handler::engage_pid(socket, channels, channel),
Command::OutputPolarity { channel, polarity } => { Command::PwmPolarity { channel, polarity } => {
Handler::set_polarity(socket, channels, channel, polarity) Handler::set_polarity(socket, channels, channel, polarity)
} }
Command::Output { Command::Pwm {
channel, channel,
pin, pin,
value, value,

View File

@ -91,7 +91,7 @@ pub struct Ipv4Config {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum ShowCommand { pub enum ShowCommand {
Input, Input,
Output, Pwm,
Pid, Pid,
SteinhartHart, SteinhartHart,
PostFilter, PostFilter,
@ -149,16 +149,16 @@ pub enum Command {
Ipv4(Ipv4Config), Ipv4(Ipv4Config),
Show(ShowCommand), Show(ShowCommand),
/// PWM parameter setting /// PWM parameter setting
Output { Pwm {
channel: usize, channel: usize,
pin: PwmPin, pin: PwmPin,
value: f64, value: f64,
}, },
/// Enable PID control for `i_set` /// Enable PID control for `i_set`
OutputPid { PwmPid {
channel: usize, channel: usize,
}, },
OutputPolarity { PwmPolarity {
channel: usize, channel: usize,
polarity: Polarity, polarity: Polarity,
}, },
@ -260,12 +260,12 @@ fn pwm_setup(input: &[u8]) -> IResult<&[u8], Result<(PwmPin, f64), Error>> {
))(input) ))(input)
} }
/// `output <0-1> pid` - Set output to be controlled by PID /// `pwm <0-1> pid` - Set PWM to be controlled by PID
fn output_pid(input: &[u8]) -> IResult<&[u8], ()> { fn pwm_pid(input: &[u8]) -> IResult<&[u8], ()> {
value((), tag("pid"))(input) value((), tag("pid"))(input)
} }
fn output_polarity(input: &[u8]) -> IResult<&[u8], Polarity> { fn pwm_polarity(input: &[u8]) -> IResult<&[u8], Polarity> {
preceded( preceded(
tag("polarity"), tag("polarity"),
preceded( preceded(
@ -278,8 +278,8 @@ fn output_polarity(input: &[u8]) -> IResult<&[u8], Polarity> {
)(input) )(input)
} }
fn output(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> { fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
let (input, _) = tag("output")(input)?; let (input, _) = tag("pwm")(input)?;
alt(( alt((
|input| { |input| {
let (input, _) = whitespace(input)?; let (input, _) = whitespace(input)?;
@ -287,19 +287,19 @@ fn output(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
let (input, _) = whitespace(input)?; let (input, _) = whitespace(input)?;
let (input, result) = alt(( let (input, result) = alt((
|input| { |input| {
let (input, ()) = output_pid(input)?; let (input, ()) = pwm_pid(input)?;
Ok((input, Ok(Command::OutputPid { channel }))) Ok((input, Ok(Command::PwmPid { channel })))
}, },
|input| { |input| {
let (input, polarity) = output_polarity(input)?; let (input, polarity) = pwm_polarity(input)?;
Ok((input, Ok(Command::OutputPolarity { channel, polarity }))) Ok((input, Ok(Command::PwmPolarity { channel, polarity })))
}, },
|input| { |input| {
let (input, config) = pwm_setup(input)?; let (input, config) = pwm_setup(input)?;
match config { match config {
Ok((pin, value)) => Ok(( Ok((pin, value)) => Ok((
input, input,
Ok(Command::Output { Ok(Command::Pwm {
channel, channel,
pin, pin,
value, value,
@ -312,7 +312,7 @@ fn output(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
end(input)?; end(input)?;
Ok((input, result)) Ok((input, result))
}, },
value(Ok(Command::Show(ShowCommand::Output)), end), value(Ok(Command::Show(ShowCommand::Pwm)), end),
))(input) ))(input)
} }
@ -569,7 +569,7 @@ fn command(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
value(Ok(Command::Reset), tag("reset")), value(Ok(Command::Reset), tag("reset")),
ipv4, ipv4,
map(report, Ok), map(report, Ok),
output, pwm,
center_point, center_point,
pid, pid,
steinhart_hart, steinhart_hart,
@ -664,11 +664,11 @@ mod test {
} }
#[test] #[test]
fn parse_output_i_set() { fn parse_pwm_i_set() {
let command = Command::parse(b"output 1 i_set 16383"); let command = Command::parse(b"pwm 1 i_set 16383");
assert_eq!( assert_eq!(
command, command,
Ok(Command::Output { Ok(Command::Pwm {
channel: 1, channel: 1,
pin: PwmPin::ISet, pin: PwmPin::ISet,
value: 16383.0, value: 16383.0,
@ -677,11 +677,11 @@ mod test {
} }
#[test] #[test]
fn parse_output_polarity() { fn parse_pwm_polarity() {
let command = Command::parse(b"pwm 0 polarity reversed"); let command = Command::parse(b"pwm 0 polarity reversed");
assert_eq!( assert_eq!(
command, command,
Ok(Command::OutputPolarity { Ok(Command::PwmPolarity {
channel: 0, channel: 0,
polarity: Polarity::Reversed, polarity: Polarity::Reversed,
}) })
@ -689,17 +689,17 @@ mod test {
} }
#[test] #[test]
fn parse_output_pid() { fn parse_pwm_pid() {
let command = Command::parse(b"output 0 pid"); let command = Command::parse(b"pwm 0 pid");
assert_eq!(command, Ok(Command::OutputPid { channel: 0 })); assert_eq!(command, Ok(Command::PwmPid { channel: 0 }));
} }
#[test] #[test]
fn parse_output_max_i_pos() { fn parse_pwm_max_i_pos() {
let command = Command::parse(b"output 0 max_i_pos 7"); let command = Command::parse(b"pwm 0 max_i_pos 7");
assert_eq!( assert_eq!(
command, command,
Ok(Command::Output { Ok(Command::Pwm {
channel: 0, channel: 0,
pin: PwmPin::MaxIPos, pin: PwmPin::MaxIPos,
value: 7.0, value: 7.0,
@ -708,11 +708,11 @@ mod test {
} }
#[test] #[test]
fn parse_output_max_i_neg() { fn parse_pwm_max_i_neg() {
let command = Command::parse(b"output 0 max_i_neg 128"); let command = Command::parse(b"pwm 0 max_i_neg 128");
assert_eq!( assert_eq!(
command, command,
Ok(Command::Output { Ok(Command::Pwm {
channel: 0, channel: 0,
pin: PwmPin::MaxINeg, pin: PwmPin::MaxINeg,
value: 128.0, value: 128.0,
@ -721,11 +721,11 @@ mod test {
} }
#[test] #[test]
fn parse_output_max_v() { fn parse_pwm_max_v() {
let command = Command::parse(b"output 0 max_v 32768"); let command = Command::parse(b"pwm 0 max_v 32768");
assert_eq!( assert_eq!(
command, command,
Ok(Command::Output { Ok(Command::Pwm {
channel: 0, channel: 0,
pin: PwmPin::MaxV, pin: PwmPin::MaxV,
value: 32768.0, value: 32768.0,

View File

@ -1,28 +1,33 @@
use crate::channels::Channels; use crate::channels::Channels;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uom::si::{ use uom::si::{
electric_current::ampere,
electric_potential::volt,
f64::{ElectricCurrent, ElectricPotential}, f64::{ElectricCurrent, ElectricPotential},
}; };
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PwmLimits { pub struct PwmLimits {
pub max_v: ElectricPotential, pub max_v: f64,
pub max_i_pos: ElectricCurrent, pub max_i_pos: f64,
pub max_i_neg: ElectricCurrent, pub max_i_neg: f64,
} }
impl PwmLimits { impl PwmLimits {
pub fn new(channels: &mut Channels, channel: usize) -> Self { pub fn new(channels: &mut Channels, channel: usize) -> Self {
let max_v = channels.get_max_v(channel);
let max_i_pos = channels.get_max_i_pos(channel);
let max_i_neg = channels.get_max_i_neg(channel);
PwmLimits { PwmLimits {
max_v: channels.get_max_v(channel), max_v: max_v.get::<volt>(),
max_i_pos: channels.get_max_i_pos(channel), max_i_pos: max_i_pos.get::<ampere>(),
max_i_neg: channels.get_max_i_neg(channel), max_i_neg: max_i_neg.get::<ampere>(),
} }
} }
pub fn apply(&self, channels: &mut Channels, channel: usize) { pub fn apply(&self, channels: &mut Channels, channel: usize) {
channels.set_max_v(channel, self.max_v); channels.set_max_v(channel, ElectricPotential::new::<volt>(self.max_v));
channels.set_max_i_pos(channel, self.max_i_pos); channels.set_max_i_pos(channel, ElectricCurrent::new::<ampere>(self.max_i_pos));
channels.set_max_i_neg(channel, self.max_i_neg); channels.set_max_i_neg(channel, ElectricCurrent::new::<ampere>(self.max_i_neg));
} }
} }

View File

@ -2,9 +2,8 @@ use num_traits::float::Float;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uom::si::{ use uom::si::{
electrical_resistance::ohm, electrical_resistance::ohm,
f64::{ElectricalResistance, TemperatureInterval, ThermodynamicTemperature}, f64::{ElectricalResistance, ThermodynamicTemperature},
ratio::ratio, ratio::ratio,
temperature_interval::kelvin as kelvin_interval,
thermodynamic_temperature::{degree_celsius, kelvin}, thermodynamic_temperature::{degree_celsius, kelvin},
}; };
@ -13,17 +12,17 @@ use uom::si::{
pub struct Parameters { pub struct Parameters {
/// Base temperature /// Base temperature
pub t0: ThermodynamicTemperature, pub t0: ThermodynamicTemperature,
/// Resistance at base temperature /// Base resistance
pub r0: ElectricalResistance, pub r0: ElectricalResistance,
/// Beta /// Beta
pub b: TemperatureInterval, pub b: f64,
} }
impl Parameters { impl Parameters {
/// Perform the resistance to temperature conversion. /// Perform the voltage to temperature conversion.
pub fn get_temperature(&self, r: ElectricalResistance) -> ThermodynamicTemperature { pub fn get_temperature(&self, r: ElectricalResistance) -> ThermodynamicTemperature {
let temp = (self.t0.recip() + (r / self.r0).get::<ratio>().ln() / self.b).recip(); let inv_temp = 1.0 / self.t0.get::<kelvin>() + (r / self.r0).get::<ratio>().ln() / self.b;
ThermodynamicTemperature::new::<kelvin>(temp.get::<kelvin_interval>()) ThermodynamicTemperature::new::<kelvin>(1.0 / inv_temp)
} }
} }
@ -32,7 +31,7 @@ impl Default for Parameters {
Parameters { Parameters {
t0: ThermodynamicTemperature::new::<degree_celsius>(25.0), t0: ThermodynamicTemperature::new::<degree_celsius>(25.0),
r0: ElectricalResistance::new::<ohm>(10_000.0), r0: ElectricalResistance::new::<ohm>(10_000.0),
b: TemperatureInterval::new::<kelvin_interval>(3800.0), b: 3800.0,
} }
} }
} }