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:
linuswck 2024-06-13 11:10:40 +08:00
parent d1660c6090
commit d5a620c76b
6 changed files with 109 additions and 31 deletions

View File

@ -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,

View File

@ -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) {

View File

@ -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;

View File

@ -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,

View File

@ -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) => {

View File

@ -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);
}