forked from M-Labs/kirdy
pd_mon: make transconductance user-configurable
- hw change: different boards now have different gain settings in order to set a pd current range close to the ld being used - transconductance and fin_gain params are added to flash with "Device" as key
This commit is contained in:
parent
d1660c6090
commit
d5a620c76b
@ -132,6 +132,22 @@ class Device:
|
||||
"""
|
||||
return await self._send_cmd(TARGET_DEVICE, "SetActiveReportMode", on)
|
||||
|
||||
async def set_pd_mon_fin_gain(self, gain):
|
||||
"""
|
||||
Configure the photodiode monitor transconductance
|
||||
- gain: unitless
|
||||
"""
|
||||
print("set_pd_mon_fin_gain")
|
||||
return await self._send_cmd(TARGET_DEVICE, "SetPdFinGain", gain)
|
||||
|
||||
async def set_pd_mon_transconductance(self, transconductance):
|
||||
"""
|
||||
Configure the photodiode monitor transconductance
|
||||
- transconductance: 1/Ohm
|
||||
"""
|
||||
print("set_pd_mon_transconductance")
|
||||
return await self._send_cmd(TARGET_DEVICE, "SetPdTransconductance", transconductance)
|
||||
|
||||
async def get_status_report(self):
|
||||
"""
|
||||
Get status of all peripherals in a json object
|
||||
@ -541,6 +557,8 @@ class Kirdy:
|
||||
self._cmd_list = {
|
||||
TARGET_DEVICE: {
|
||||
"SetIPSettings": IP_SETTINGS,
|
||||
"SetPdFinGain": DATA_F32,
|
||||
"SetPdTransconductance": DATA_F32,
|
||||
"SetActiveReportMode": DATA_BOOL,
|
||||
"GetStatusReport": None,
|
||||
"GetSettingsSummary": None,
|
||||
|
@ -1,14 +1,13 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use log::info;
|
||||
use miniconf::Tree;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stm32f4xx_hal::{pac::{ADC3, TIM2},
|
||||
timer::CounterUs};
|
||||
use uom::{si::{electric_current::{ampere, milliampere},
|
||||
f32::{ElectricCurrent, ElectricPotential, Power},
|
||||
power::milliwatt,
|
||||
Quantity, ISQ, SI},
|
||||
typenum::*};
|
||||
use uom::si::{electric_current::{ampere, milliampere},
|
||||
f32::{ElectricCurrent, ElectricPotential, ElectricalConductance, ElectricalResistance, Power},
|
||||
power::milliwatt};
|
||||
|
||||
use crate::{device::sys_timer::sleep,
|
||||
laser_diode::{ld_ctrl::{Impedance, LdCtrl},
|
||||
@ -16,11 +15,6 @@ use crate::{device::sys_timer::sleep,
|
||||
ld_pwr_exc_protector::{self, LdPwrExcProtector},
|
||||
pd_mon_params}};
|
||||
|
||||
// Volt / Ampere
|
||||
pub type TransimpedanceUnit = Quantity<ISQ<P2, P1, N3, N2, Z0, Z0, Z0>, SI<f32>, f32>;
|
||||
// Ampere / Volt
|
||||
type TransconductanceUnit = Quantity<ISQ<N2, N1, P3, P2, Z0, Z0, Z0>, SI<f32>, f32>;
|
||||
|
||||
impl Settings {
|
||||
pub const LD_CURRENT_MAX: ElectricCurrent = ElectricCurrent {
|
||||
dimension: PhantomData,
|
||||
@ -33,14 +27,7 @@ impl Settings {
|
||||
value: 4.096,
|
||||
};
|
||||
|
||||
// Unit: A/V
|
||||
const PD_MON_TRANSCONDUCTANCE: TransconductanceUnit = TransconductanceUnit {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 0.001,
|
||||
};
|
||||
|
||||
const LD_DRIVE_TRANSIMPEDANCE: TransimpedanceUnit = TransimpedanceUnit {
|
||||
const LD_DRIVE_TRANSIMPEDANCE: ElectricalResistance = ElectricalResistance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 10.0 / 0.75,
|
||||
@ -152,13 +139,17 @@ impl LdDrive {
|
||||
}
|
||||
|
||||
pub fn get_pd_i(&mut self) -> ElectricCurrent {
|
||||
LdPwrExcProtector::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE
|
||||
self.settings
|
||||
.pd_mon_params
|
||||
.get_pd_i_from_pd_v(LdPwrExcProtector::get_status().v)
|
||||
}
|
||||
|
||||
pub fn get_pd_pwr(&mut self) -> Power {
|
||||
self.settings
|
||||
.pd_mon_params
|
||||
.get_ld_pwr_from_ld_i(LdPwrExcProtector::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE)
|
||||
self.settings.pd_mon_params.get_ld_pwr_from_ld_i(
|
||||
self.settings
|
||||
.pd_mon_params
|
||||
.get_pd_i_from_pd_v(LdPwrExcProtector::get_status().v),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn ld_set_i(&mut self, i: ElectricCurrent) {
|
||||
@ -188,6 +179,10 @@ impl LdDrive {
|
||||
LdPwrExcProtector::clear_alarm_status();
|
||||
}
|
||||
|
||||
pub fn set_pd_transconductance(&mut self, transconductance: ElectricalConductance) {
|
||||
self.settings.pd_mon_params.set_transconductance(transconductance)
|
||||
}
|
||||
|
||||
pub fn set_pd_responsitivity(&mut self, responsitivity: pd_mon_params::ResponsitivityUnit) {
|
||||
self.settings.pd_mon_params.set(responsitivity);
|
||||
}
|
||||
@ -198,13 +193,13 @@ impl LdDrive {
|
||||
|
||||
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) {
|
||||
LdPwrExcProtector::set_trigger_threshold_v(
|
||||
self.settings.pd_mon_params.get_ld_i_from_ld_pwr(pwr_limit) / Settings::PD_MON_TRANSCONDUCTANCE,
|
||||
self.settings.pd_mon_params.get_pd_i_from_ld_pwr(pwr_limit) / self.settings.pd_mon_params.transconductance,
|
||||
);
|
||||
self.settings.ld_pwr_limit = pwr_limit;
|
||||
}
|
||||
|
||||
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) {
|
||||
LdPwrExcProtector::set_trigger_threshold_v(i / Settings::PD_MON_TRANSCONDUCTANCE);
|
||||
LdPwrExcProtector::set_trigger_threshold_v(i / self.settings.pd_mon_params.transconductance);
|
||||
}
|
||||
|
||||
pub fn set_default_pwr_on(&mut self, pwr_on: bool) {
|
||||
|
@ -5,11 +5,10 @@ use stm32f4xx_hal::{gpio::{gpioa::*, gpiob::*, gpiod::*, Input, Output, PushPull
|
||||
pac::SPI2,
|
||||
spi::Spi};
|
||||
use uom::si::{electric_current::ampere,
|
||||
f32::{ElectricCurrent, ElectricPotential},
|
||||
f32::{ElectricCurrent, ElectricPotential, ElectricalResistance},
|
||||
ratio::ratio};
|
||||
|
||||
use crate::laser_diode::{laser_diode::TransimpedanceUnit,
|
||||
max5719::{self, Dac}};
|
||||
use crate::laser_diode::max5719::{self, Dac};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
|
||||
pub enum Impedance {
|
||||
@ -84,7 +83,7 @@ impl LdCtrl {
|
||||
pub fn set_i(
|
||||
&mut self,
|
||||
current: ElectricCurrent,
|
||||
transimpedance: TransimpedanceUnit,
|
||||
transimpedance: ElectricalResistance,
|
||||
dac_out_v_max: ElectricPotential,
|
||||
) -> ElectricCurrent {
|
||||
self.i_set = self.set_dac(current * transimpedance, dac_out_v_max) / transimpedance;
|
||||
|
@ -1,9 +1,10 @@
|
||||
use core::{f32::NAN, marker::PhantomData};
|
||||
|
||||
use miniconf::Tree;
|
||||
use num_traits::Zero;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uom::{si::{electric_current::microampere,
|
||||
f32::{ElectricCurrent, Power},
|
||||
f32::{ElectricCurrent, ElectricPotential, ElectricalConductance, Power},
|
||||
Quantity, ISQ, SI},
|
||||
typenum::*};
|
||||
|
||||
@ -12,6 +13,7 @@ pub type ResponsitivityUnit = Quantity<ISQ<N2, N1, P3, P1, Z0, Z0, Z0>, SI<f32>,
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Tree)]
|
||||
pub struct Parameters {
|
||||
pub transconductance: ElectricalConductance,
|
||||
responsitivity: ResponsitivityUnit,
|
||||
i_dark: ElectricCurrent,
|
||||
}
|
||||
@ -22,11 +24,15 @@ impl Parameters {
|
||||
ld_power
|
||||
}
|
||||
|
||||
pub fn get_ld_i_from_ld_pwr(&self, pwr: Power) -> ElectricCurrent {
|
||||
pub fn get_pd_i_from_ld_pwr(&self, pwr: Power) -> ElectricCurrent {
|
||||
let ld_i = pwr * self.responsitivity + self.i_dark;
|
||||
ld_i
|
||||
}
|
||||
|
||||
pub fn get_pd_i_from_pd_v(&self, v: ElectricPotential) -> ElectricCurrent {
|
||||
(v * self.transconductance).max(ElectricCurrent::zero())
|
||||
}
|
||||
|
||||
pub fn set(&mut self, responsitivity: ResponsitivityUnit) {
|
||||
self.responsitivity = responsitivity;
|
||||
}
|
||||
@ -34,11 +40,20 @@ impl Parameters {
|
||||
pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) {
|
||||
self.i_dark = i_dark;
|
||||
}
|
||||
|
||||
pub fn set_transconductance(&mut self, transconductance: ElectricalConductance) {
|
||||
self.transconductance = transconductance;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Parameters {
|
||||
fn default() -> Self {
|
||||
Parameters {
|
||||
transconductance: ElectricalConductance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 1.0 / 1000.0,
|
||||
},
|
||||
responsitivity: ResponsitivityUnit {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
|
12
src/main.rs
12
src/main.rs
@ -1,9 +1,12 @@
|
||||
#![cfg_attr(not(test), no_main)]
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use log::{debug, info};
|
||||
use stm32f4xx_hal::pac::{CorePeripherals, Peripherals};
|
||||
use uom::si::f32::ElectricalConductance;
|
||||
mod device;
|
||||
mod laser_diode;
|
||||
mod net;
|
||||
@ -35,6 +38,8 @@ static mut ETH_DATA_BUFFER: [u8; 1024] = [0; 1024];
|
||||
#[derive(Deserialize, Serialize, Clone, Copy, Debug)]
|
||||
pub struct DeviceSettings {
|
||||
ip_settings: IpSettings,
|
||||
pd_mon_fin_gain: f32,
|
||||
pd_mon_transconductance: ElectricalConductance,
|
||||
}
|
||||
|
||||
const CONFIG_KEY: [&str; 3] = ["Device", "Laser_0", "Thermostat_0"];
|
||||
@ -63,6 +68,12 @@ fn main() -> ! {
|
||||
|
||||
let mut device_settings = DeviceSettings {
|
||||
ip_settings: IpSettings::default(),
|
||||
pd_mon_fin_gain: 1.0,
|
||||
pd_mon_transconductance: ElectricalConductance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 1.0 / 1000.0,
|
||||
},
|
||||
};
|
||||
|
||||
let mut active_report: [bool; net::net::NUM_OF_SOCKETS] = [false; net::net::NUM_OF_SOCKETS];
|
||||
@ -88,6 +99,7 @@ fn main() -> ! {
|
||||
match flash_store.read_value(CONFIG_KEY[0]) {
|
||||
Ok(Some(config)) => {
|
||||
device_settings_flash = config;
|
||||
laser.set_pd_transconductance(config.pd_mon_fin_gain * config.pd_mon_transconductance);
|
||||
debug!("Found Device Settings");
|
||||
}
|
||||
Ok(None) => {
|
||||
|
@ -6,13 +6,14 @@ use serde::{Deserialize, Serialize};
|
||||
use smoltcp::iface::SocketHandle;
|
||||
use uom::si::{electric_current::{ampere, ElectricCurrent},
|
||||
electric_potential::{volt, ElectricPotential},
|
||||
electrical_conductance::{siemens, ElectricalConductance},
|
||||
electrical_resistance::{ohm, ElectricalResistance},
|
||||
power::{watt, Power},
|
||||
thermodynamic_temperature::{degree_celsius, ThermodynamicTemperature}};
|
||||
|
||||
use crate::{device::{dfu, sys_timer},
|
||||
laser_diode::{laser_diode::{LdDrive, LdSettingsSummary, StatusReport as LdStatusReport},
|
||||
pd_mon_params::ResponsitivityUnit},
|
||||
pd_mon_params::{self, ResponsitivityUnit}},
|
||||
net::net,
|
||||
thermostat::{ad7172::FilterType,
|
||||
pid_state::PidSettings::*,
|
||||
@ -61,6 +62,8 @@ enum DeviceCmd {
|
||||
Reserved,
|
||||
SetIPSettings,
|
||||
SetActiveReportMode,
|
||||
SetPdFinGain,
|
||||
SetPdTransconductance,
|
||||
GetStatusReport,
|
||||
GetSettingsSummary,
|
||||
Dfu,
|
||||
@ -311,6 +314,42 @@ pub fn execute_cmd(
|
||||
);
|
||||
}
|
||||
},
|
||||
Some(DeviceCmd::SetPdFinGain) => match cmd.json.data_f32 {
|
||||
Some(val) => {
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
device_settings.pd_mon_fin_gain = val;
|
||||
laser.set_pd_transconductance(
|
||||
device_settings.pd_mon_fin_gain * device_settings.pd_mon_transconductance,
|
||||
);
|
||||
*state = State::SaveDeviceSettings;
|
||||
}
|
||||
None => {
|
||||
send_response(
|
||||
buffer,
|
||||
ResponseEnum::InvalidDatatype,
|
||||
Some(ERR_MSG_MISSING_DATA_F32),
|
||||
socket,
|
||||
);
|
||||
}
|
||||
},
|
||||
Some(DeviceCmd::SetPdTransconductance) => match cmd.json.data_f32 {
|
||||
Some(val) => {
|
||||
send_response(buffer, ResponseEnum::Acknowledge, None, socket);
|
||||
device_settings.pd_mon_transconductance = ElectricalConductance::new::<siemens>(val);
|
||||
laser.set_pd_transconductance(
|
||||
device_settings.pd_mon_fin_gain * device_settings.pd_mon_transconductance,
|
||||
);
|
||||
*state = State::SaveDeviceSettings;
|
||||
}
|
||||
None => {
|
||||
send_response(
|
||||
buffer,
|
||||
ResponseEnum::InvalidDatatype,
|
||||
Some(ERR_MSG_MISSING_DATA_F32),
|
||||
socket,
|
||||
);
|
||||
}
|
||||
},
|
||||
Some(DeviceCmd::GetStatusReport) => {
|
||||
send_status_report(buffer, laser, thermostat, socket);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user