laser: check pd_mon params & pwr limit before set
- Design to prevent Issue #47 on hardware kirdy repo from happening - responsitivity, i_dark & transconductance determine the pwr limit range - when "ApplyPdParams" and "SetLdPwrLimit" are called, pwr limit range is checked before applying new parameter - Send out a "InvalidSettings" response with error message if settings cannot be applied - Add settable power range to settings json object
This commit is contained in:
parent
1111967a7b
commit
86e6d3764e
|
@ -2,6 +2,7 @@ use core::marker::PhantomData;
|
|||
|
||||
use log::info;
|
||||
use miniconf::Tree;
|
||||
use num_traits::Zero;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stm32f4xx_hal::{pac::{ADC3, TIM2},
|
||||
timer::CounterUs};
|
||||
|
@ -42,6 +43,7 @@ struct Settings {
|
|||
pd_mon_params: pd_mon_params::Parameters,
|
||||
ld_pwr_limit: Power,
|
||||
ld_terms_short: bool,
|
||||
incoming_pd_mon_params: pd_mon_params::Parameters,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
|
@ -51,6 +53,7 @@ impl Default for Settings {
|
|||
default_pwr_on: false,
|
||||
ld_drive_current: ElectricCurrent::new::<milliampere>(0.0),
|
||||
pd_mon_params: pd_mon_params::Parameters::default(),
|
||||
incoming_pd_mon_params: pd_mon_params::Parameters::default(),
|
||||
ld_pwr_limit: Power::new::<milliwatt>(0.0),
|
||||
ld_terms_short: false,
|
||||
}
|
||||
|
@ -181,24 +184,51 @@ impl LdDrive {
|
|||
}
|
||||
|
||||
pub fn set_pd_responsitivity(&mut self, responsitivity: pd_mon_params::ResponsitivityUnit) {
|
||||
self.settings.pd_mon_params.set(responsitivity);
|
||||
self.set_ld_power_limit(self.settings.ld_pwr_limit)
|
||||
self.settings.incoming_pd_mon_params.set_responsitivity(responsitivity);
|
||||
}
|
||||
|
||||
pub fn set_pd_dark_current(&mut self, i_dark: ElectricCurrent) {
|
||||
self.settings.pd_mon_params.set_i_dark(i_dark);
|
||||
self.set_ld_power_limit(self.settings.ld_pwr_limit)
|
||||
self.settings.incoming_pd_mon_params.set_i_dark(i_dark);
|
||||
}
|
||||
|
||||
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) {
|
||||
LdPwrExcProtector::set_trigger_threshold_v(
|
||||
pub fn apply_pd_params(&mut self) -> bool {
|
||||
let prev_pd_params = self.settings.pd_mon_params;
|
||||
self.settings.incoming_pd_mon_params.transconductance = self.settings.pd_mon_params.transconductance;
|
||||
self.settings.pd_mon_params = self.settings.incoming_pd_mon_params;
|
||||
|
||||
let max_settable_pwr = self.get_ld_power_limit_range();
|
||||
let is_legal = self.settings.ld_pwr_limit <= max_settable_pwr;
|
||||
if is_legal {
|
||||
self.set_ld_power_limit(self.settings.ld_pwr_limit);
|
||||
} else {
|
||||
self.settings.pd_mon_params = prev_pd_params;
|
||||
}
|
||||
is_legal
|
||||
}
|
||||
|
||||
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) -> bool {
|
||||
let is_legal = LdPwrExcProtector::set_trigger_threshold_v(
|
||||
self.settings.pd_mon_params.get_pd_i_from_ld_pwr(pwr_limit) / self.settings.pd_mon_params.transconductance,
|
||||
);
|
||||
if is_legal {
|
||||
self.settings.ld_pwr_limit = pwr_limit;
|
||||
}
|
||||
is_legal
|
||||
}
|
||||
|
||||
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) {
|
||||
LdPwrExcProtector::set_trigger_threshold_v(i / self.settings.pd_mon_params.transconductance);
|
||||
pub fn get_ld_power_limit_range(&mut self) -> Power {
|
||||
let v_range = LdPwrExcProtector::get_settable_volt_range();
|
||||
let i_range = self.settings.pd_mon_params.get_pd_i_from_pd_v(v_range);
|
||||
let max_settable_pwr = self.settings.pd_mon_params.get_ld_pwr_from_ld_i(i_range);
|
||||
if max_settable_pwr.is_nan() || max_settable_pwr.is_infinite() {
|
||||
Power::zero()
|
||||
} else {
|
||||
max_settable_pwr
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) -> bool {
|
||||
return LdPwrExcProtector::set_trigger_threshold_v(i / self.settings.pd_mon_params.transconductance);
|
||||
}
|
||||
|
||||
pub fn set_default_pwr_on(&mut self, pwr_on: bool) {
|
||||
|
@ -234,7 +264,10 @@ impl LdDrive {
|
|||
max: Settings::LD_CURRENT_MAX,
|
||||
},
|
||||
pd_mon_params: settings.pd_mon_params,
|
||||
ld_pwr_limit: settings.ld_pwr_limit,
|
||||
ld_pwr_limit: LdSettingsSummaryField {
|
||||
value: settings.ld_pwr_limit,
|
||||
max: self.get_ld_power_limit_range(),
|
||||
},
|
||||
ld_terms_short: settings.ld_terms_short,
|
||||
}
|
||||
}
|
||||
|
@ -243,10 +276,10 @@ impl LdDrive {
|
|||
self.power_down();
|
||||
self.settings.ld_drive_current = settings.ld_drive_current.value;
|
||||
self.settings.pd_mon_params = settings.pd_mon_params;
|
||||
self.settings.ld_pwr_limit = settings.ld_pwr_limit;
|
||||
let max_pwr_limit = self.get_ld_power_limit_range();
|
||||
self.settings.ld_pwr_limit = settings.ld_pwr_limit.value.min(max_pwr_limit);
|
||||
self.settings.default_pwr_on = settings.default_pwr_on;
|
||||
|
||||
self.set_ld_power_limit(settings.ld_pwr_limit);
|
||||
self.set_ld_power_limit(self.settings.ld_pwr_limit);
|
||||
|
||||
if self.settings.ld_terms_short {
|
||||
self.ld_short();
|
||||
|
@ -267,7 +300,7 @@ pub struct LdSettingsSummary {
|
|||
default_pwr_on: bool,
|
||||
ld_drive_current: LdSettingsSummaryField<ElectricCurrent>,
|
||||
pd_mon_params: pd_mon_params::Parameters,
|
||||
ld_pwr_limit: Power,
|
||||
ld_pwr_limit: LdSettingsSummaryField<Power>,
|
||||
ld_terms_short: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use num_traits::Zero;
|
||||
use num_traits::{Float, Zero};
|
||||
use stm32f4xx_hal::{adc::{config::{self, AdcConfig},
|
||||
Adc},
|
||||
gpio::{gpioa::PA3, gpiod::PD9, Analog, Output, PushPull},
|
||||
|
@ -167,15 +167,19 @@ impl LdPwrExcProtector {
|
|||
ElectricPotential::new::<millivolt>(0.0)
|
||||
}
|
||||
|
||||
pub fn set_trigger_threshold_v(htr: ElectricPotential) {
|
||||
pub fn set_trigger_threshold_v(htr: ElectricPotential) -> bool {
|
||||
if let Some(ref mut wdg) = LdPwrExcProtector::get() {
|
||||
let code: u32 = ((((htr / (ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32))).get::<ratio>()
|
||||
* (MAX_SAMPLE as f32)) as u32)
|
||||
+ wdg.offset)
|
||||
.min(MAX_SAMPLE as u32);
|
||||
let code: u32 = (((htr / (ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32))).get::<ratio>()
|
||||
* (MAX_SAMPLE as f32))
|
||||
.ceil() as u32)
|
||||
+ wdg.offset;
|
||||
if code <= MAX_SAMPLE as u32 {
|
||||
wdg.pac.htr.write(|w| unsafe { w.bits(code) });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn set_calibrated_vdda(val: u32) {
|
||||
if let Some(ref mut wdg) = LdPwrExcProtector::get() {
|
||||
|
@ -209,6 +213,15 @@ impl LdPwrExcProtector {
|
|||
Status::default()
|
||||
}
|
||||
|
||||
pub fn get_settable_volt_range() -> ElectricPotential {
|
||||
if let Some(ref mut wdg) = LdPwrExcProtector::get() {
|
||||
return ElectricPotential::new::<millivolt>(wdg.calibrated_vdda as f32)
|
||||
* ((MAX_SAMPLE as u32 - wdg.offset) as f32)
|
||||
/ MAX_SAMPLE as f32;
|
||||
}
|
||||
ElectricPotential::zero()
|
||||
}
|
||||
|
||||
pub fn pwr_on_and_arm_protection() {
|
||||
if let Some(ref mut wdg) = LdPwrExcProtector::get() {
|
||||
if !wdg.alarm_status.pwr_excursion {
|
||||
|
|
|
@ -33,14 +33,22 @@ impl Parameters {
|
|||
(v * self.transconductance).max(ElectricCurrent::zero())
|
||||
}
|
||||
|
||||
pub fn set(&mut self, responsitivity: ResponsitivityUnit) {
|
||||
pub fn set_responsitivity(&mut self, responsitivity: ResponsitivityUnit) {
|
||||
self.responsitivity = responsitivity;
|
||||
}
|
||||
|
||||
pub fn get_responsitivity(&mut self) -> ResponsitivityUnit {
|
||||
self.responsitivity
|
||||
}
|
||||
|
||||
pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) {
|
||||
self.i_dark = i_dark;
|
||||
}
|
||||
|
||||
pub fn get_i_dark(&mut self) -> ElectricCurrent {
|
||||
self.i_dark
|
||||
}
|
||||
|
||||
pub fn set_transconductance(&mut self, transconductance: ElectricalConductance) {
|
||||
self.transconductance = transconductance;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ pub enum ResponseEnum {
|
|||
HwRev,
|
||||
Acknowledge,
|
||||
InvalidDatatype,
|
||||
InvalidSettings,
|
||||
InvalidCmd,
|
||||
HardReset,
|
||||
Dfu,
|
||||
|
@ -89,6 +90,7 @@ enum LdCmdEnum {
|
|||
// PD Mon Related
|
||||
SetPdResponsitivity,
|
||||
SetPdDarkCurrent,
|
||||
ApplyPdParams,
|
||||
SetLdPwrLimit,
|
||||
ClearAlarm,
|
||||
}
|
||||
|
@ -135,6 +137,8 @@ const ERR_MSG_MISSING_SINC5SINC1ODR: &str = "Required field \"sinc5sinc1odr\" do
|
|||
const ERR_MSG_MISSING_SINC3ODR: &str = "Required field \"sinc3odr\" does not exist";
|
||||
const ERR_MSG_MISSING_POSTFILTER: &str = "Required field \"PostFilter\" does not exist";
|
||||
const ERR_MSG_MISSING_SINC3FINEODR: &str = "Required field \"sinc3fineodr\" does not exist";
|
||||
const ERR_MSG_INVALID_PDMON_SETTINGS: &str = "Invalid PD Mon Parameter Setting(s)";
|
||||
const ERR_MSG_INVALID_LD_PWR_LIMIT_SETTING: &str = "Invalid LD Power Limit Setting";
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)]
|
||||
pub struct CmdJsonObj {
|
||||
|
@ -453,12 +457,12 @@ pub fn execute_cmd(
|
|||
},
|
||||
Some(LdCmdEnum::SetPdResponsitivity) => match cmd.json.data_f32 {
|
||||
Some(val) => {
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
laser.set_pd_responsitivity(ResponsitivityUnit {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: val,
|
||||
})
|
||||
});
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
}
|
||||
None => {
|
||||
send_response(
|
||||
|
@ -471,8 +475,8 @@ pub fn execute_cmd(
|
|||
},
|
||||
Some(LdCmdEnum::SetPdDarkCurrent) => match cmd.json.data_f32 {
|
||||
Some(val) => {
|
||||
laser.set_pd_dark_current(ElectricCurrent::new::<ampere>(val));
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
laser.set_pd_dark_current(ElectricCurrent::new::<ampere>(val))
|
||||
}
|
||||
None => {
|
||||
send_response(
|
||||
|
@ -483,10 +487,32 @@ pub fn execute_cmd(
|
|||
);
|
||||
}
|
||||
},
|
||||
Some(LdCmdEnum::ApplyPdParams) => {
|
||||
let is_legal = laser.apply_pd_params();
|
||||
if is_legal {
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
} else {
|
||||
send_response(
|
||||
buffer,
|
||||
ResponseEnum::InvalidSettings,
|
||||
Some(ERR_MSG_INVALID_PDMON_SETTINGS),
|
||||
socket,
|
||||
)
|
||||
}
|
||||
}
|
||||
Some(LdCmdEnum::SetLdPwrLimit) => match cmd.json.data_f32 {
|
||||
Some(val) => {
|
||||
let is_legal = laser.set_ld_power_limit(Power::new::<watt>(val));
|
||||
if is_legal {
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
laser.set_ld_power_limit(Power::new::<watt>(val))
|
||||
} else {
|
||||
send_response(
|
||||
buffer,
|
||||
ResponseEnum::InvalidSettings,
|
||||
Some(ERR_MSG_INVALID_LD_PWR_LIMIT_SETTING),
|
||||
socket,
|
||||
)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
send_response(
|
||||
|
|
Loading…
Reference in New Issue