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)
|
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):
|
async def get_status_report(self):
|
||||||
"""
|
"""
|
||||||
Get status of all peripherals in a json object
|
Get status of all peripherals in a json object
|
||||||
|
@ -541,6 +557,8 @@ class Kirdy:
|
||||||
self._cmd_list = {
|
self._cmd_list = {
|
||||||
TARGET_DEVICE: {
|
TARGET_DEVICE: {
|
||||||
"SetIPSettings": IP_SETTINGS,
|
"SetIPSettings": IP_SETTINGS,
|
||||||
|
"SetPdFinGain": DATA_F32,
|
||||||
|
"SetPdTransconductance": DATA_F32,
|
||||||
"SetActiveReportMode": DATA_BOOL,
|
"SetActiveReportMode": DATA_BOOL,
|
||||||
"GetStatusReport": None,
|
"GetStatusReport": None,
|
||||||
"GetSettingsSummary": None,
|
"GetSettingsSummary": None,
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use log::info;
|
||||||
use miniconf::Tree;
|
use miniconf::Tree;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use stm32f4xx_hal::{pac::{ADC3, TIM2},
|
use stm32f4xx_hal::{pac::{ADC3, TIM2},
|
||||||
timer::CounterUs};
|
timer::CounterUs};
|
||||||
use uom::{si::{electric_current::{ampere, milliampere},
|
use uom::si::{electric_current::{ampere, milliampere},
|
||||||
f32::{ElectricCurrent, ElectricPotential, Power},
|
f32::{ElectricCurrent, ElectricPotential, ElectricalConductance, ElectricalResistance, Power},
|
||||||
power::milliwatt,
|
power::milliwatt};
|
||||||
Quantity, ISQ, SI},
|
|
||||||
typenum::*};
|
|
||||||
|
|
||||||
use crate::{device::sys_timer::sleep,
|
use crate::{device::sys_timer::sleep,
|
||||||
laser_diode::{ld_ctrl::{Impedance, LdCtrl},
|
laser_diode::{ld_ctrl::{Impedance, LdCtrl},
|
||||||
|
@ -16,11 +15,6 @@ use crate::{device::sys_timer::sleep,
|
||||||
ld_pwr_exc_protector::{self, LdPwrExcProtector},
|
ld_pwr_exc_protector::{self, LdPwrExcProtector},
|
||||||
pd_mon_params}};
|
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 {
|
impl Settings {
|
||||||
pub const LD_CURRENT_MAX: ElectricCurrent = ElectricCurrent {
|
pub const LD_CURRENT_MAX: ElectricCurrent = ElectricCurrent {
|
||||||
dimension: PhantomData,
|
dimension: PhantomData,
|
||||||
|
@ -33,14 +27,7 @@ impl Settings {
|
||||||
value: 4.096,
|
value: 4.096,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unit: A/V
|
const LD_DRIVE_TRANSIMPEDANCE: ElectricalResistance = ElectricalResistance {
|
||||||
const PD_MON_TRANSCONDUCTANCE: TransconductanceUnit = TransconductanceUnit {
|
|
||||||
dimension: PhantomData,
|
|
||||||
units: PhantomData,
|
|
||||||
value: 0.001,
|
|
||||||
};
|
|
||||||
|
|
||||||
const LD_DRIVE_TRANSIMPEDANCE: TransimpedanceUnit = TransimpedanceUnit {
|
|
||||||
dimension: PhantomData,
|
dimension: PhantomData,
|
||||||
units: PhantomData,
|
units: PhantomData,
|
||||||
value: 10.0 / 0.75,
|
value: 10.0 / 0.75,
|
||||||
|
@ -152,13 +139,17 @@ impl LdDrive {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pd_i(&mut self) -> ElectricCurrent {
|
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 {
|
pub fn get_pd_pwr(&mut self) -> Power {
|
||||||
|
self.settings.pd_mon_params.get_ld_pwr_from_ld_i(
|
||||||
self.settings
|
self.settings
|
||||||
.pd_mon_params
|
.pd_mon_params
|
||||||
.get_ld_pwr_from_ld_i(LdPwrExcProtector::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE)
|
.get_pd_i_from_pd_v(LdPwrExcProtector::get_status().v),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ld_set_i(&mut self, i: ElectricCurrent) {
|
pub fn ld_set_i(&mut self, i: ElectricCurrent) {
|
||||||
|
@ -188,6 +179,10 @@ impl LdDrive {
|
||||||
LdPwrExcProtector::clear_alarm_status();
|
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) {
|
pub fn set_pd_responsitivity(&mut self, responsitivity: pd_mon_params::ResponsitivityUnit) {
|
||||||
self.settings.pd_mon_params.set(responsitivity);
|
self.settings.pd_mon_params.set(responsitivity);
|
||||||
}
|
}
|
||||||
|
@ -198,13 +193,13 @@ impl LdDrive {
|
||||||
|
|
||||||
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) {
|
pub fn set_ld_power_limit(&mut self, pwr_limit: Power) {
|
||||||
LdPwrExcProtector::set_trigger_threshold_v(
|
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;
|
self.settings.ld_pwr_limit = pwr_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent) {
|
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) {
|
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,
|
pac::SPI2,
|
||||||
spi::Spi};
|
spi::Spi};
|
||||||
use uom::si::{electric_current::ampere,
|
use uom::si::{electric_current::ampere,
|
||||||
f32::{ElectricCurrent, ElectricPotential},
|
f32::{ElectricCurrent, ElectricPotential, ElectricalResistance},
|
||||||
ratio::ratio};
|
ratio::ratio};
|
||||||
|
|
||||||
use crate::laser_diode::{laser_diode::TransimpedanceUnit,
|
use crate::laser_diode::max5719::{self, Dac};
|
||||||
max5719::{self, Dac}};
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
|
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]
|
||||||
pub enum Impedance {
|
pub enum Impedance {
|
||||||
|
@ -84,7 +83,7 @@ impl LdCtrl {
|
||||||
pub fn set_i(
|
pub fn set_i(
|
||||||
&mut self,
|
&mut self,
|
||||||
current: ElectricCurrent,
|
current: ElectricCurrent,
|
||||||
transimpedance: TransimpedanceUnit,
|
transimpedance: ElectricalResistance,
|
||||||
dac_out_v_max: ElectricPotential,
|
dac_out_v_max: ElectricPotential,
|
||||||
) -> ElectricCurrent {
|
) -> ElectricCurrent {
|
||||||
self.i_set = self.set_dac(current * transimpedance, dac_out_v_max) / transimpedance;
|
self.i_set = self.set_dac(current * transimpedance, dac_out_v_max) / transimpedance;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use core::{f32::NAN, marker::PhantomData};
|
use core::{f32::NAN, marker::PhantomData};
|
||||||
|
|
||||||
use miniconf::Tree;
|
use miniconf::Tree;
|
||||||
|
use num_traits::Zero;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uom::{si::{electric_current::microampere,
|
use uom::{si::{electric_current::microampere,
|
||||||
f32::{ElectricCurrent, Power},
|
f32::{ElectricCurrent, ElectricPotential, ElectricalConductance, Power},
|
||||||
Quantity, ISQ, SI},
|
Quantity, ISQ, SI},
|
||||||
typenum::*};
|
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)]
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Tree)]
|
||||||
pub struct Parameters {
|
pub struct Parameters {
|
||||||
|
pub transconductance: ElectricalConductance,
|
||||||
responsitivity: ResponsitivityUnit,
|
responsitivity: ResponsitivityUnit,
|
||||||
i_dark: ElectricCurrent,
|
i_dark: ElectricCurrent,
|
||||||
}
|
}
|
||||||
|
@ -22,11 +24,15 @@ impl Parameters {
|
||||||
ld_power
|
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;
|
let ld_i = pwr * self.responsitivity + self.i_dark;
|
||||||
ld_i
|
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) {
|
pub fn set(&mut self, responsitivity: ResponsitivityUnit) {
|
||||||
self.responsitivity = responsitivity;
|
self.responsitivity = responsitivity;
|
||||||
}
|
}
|
||||||
|
@ -34,11 +40,20 @@ impl Parameters {
|
||||||
pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) {
|
pub fn set_i_dark(&mut self, i_dark: ElectricCurrent) {
|
||||||
self.i_dark = i_dark;
|
self.i_dark = i_dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_transconductance(&mut self, transconductance: ElectricalConductance) {
|
||||||
|
self.transconductance = transconductance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Parameters {
|
impl Default for Parameters {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Parameters {
|
Parameters {
|
||||||
|
transconductance: ElectricalConductance {
|
||||||
|
dimension: PhantomData,
|
||||||
|
units: PhantomData,
|
||||||
|
value: 1.0 / 1000.0,
|
||||||
|
},
|
||||||
responsitivity: ResponsitivityUnit {
|
responsitivity: ResponsitivityUnit {
|
||||||
dimension: PhantomData,
|
dimension: PhantomData,
|
||||||
units: 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_main)]
|
||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use stm32f4xx_hal::pac::{CorePeripherals, Peripherals};
|
use stm32f4xx_hal::pac::{CorePeripherals, Peripherals};
|
||||||
|
use uom::si::f32::ElectricalConductance;
|
||||||
mod device;
|
mod device;
|
||||||
mod laser_diode;
|
mod laser_diode;
|
||||||
mod net;
|
mod net;
|
||||||
|
@ -35,6 +38,8 @@ static mut ETH_DATA_BUFFER: [u8; 1024] = [0; 1024];
|
||||||
#[derive(Deserialize, Serialize, Clone, Copy, Debug)]
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug)]
|
||||||
pub struct DeviceSettings {
|
pub struct DeviceSettings {
|
||||||
ip_settings: IpSettings,
|
ip_settings: IpSettings,
|
||||||
|
pd_mon_fin_gain: f32,
|
||||||
|
pd_mon_transconductance: ElectricalConductance,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONFIG_KEY: [&str; 3] = ["Device", "Laser_0", "Thermostat_0"];
|
const CONFIG_KEY: [&str; 3] = ["Device", "Laser_0", "Thermostat_0"];
|
||||||
|
@ -63,6 +68,12 @@ fn main() -> ! {
|
||||||
|
|
||||||
let mut device_settings = DeviceSettings {
|
let mut device_settings = DeviceSettings {
|
||||||
ip_settings: IpSettings::default(),
|
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];
|
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]) {
|
match flash_store.read_value(CONFIG_KEY[0]) {
|
||||||
Ok(Some(config)) => {
|
Ok(Some(config)) => {
|
||||||
device_settings_flash = config;
|
device_settings_flash = config;
|
||||||
|
laser.set_pd_transconductance(config.pd_mon_fin_gain * config.pd_mon_transconductance);
|
||||||
debug!("Found Device Settings");
|
debug!("Found Device Settings");
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
|
|
@ -6,13 +6,14 @@ use serde::{Deserialize, Serialize};
|
||||||
use smoltcp::iface::SocketHandle;
|
use smoltcp::iface::SocketHandle;
|
||||||
use uom::si::{electric_current::{ampere, ElectricCurrent},
|
use uom::si::{electric_current::{ampere, ElectricCurrent},
|
||||||
electric_potential::{volt, ElectricPotential},
|
electric_potential::{volt, ElectricPotential},
|
||||||
|
electrical_conductance::{siemens, ElectricalConductance},
|
||||||
electrical_resistance::{ohm, ElectricalResistance},
|
electrical_resistance::{ohm, ElectricalResistance},
|
||||||
power::{watt, Power},
|
power::{watt, Power},
|
||||||
thermodynamic_temperature::{degree_celsius, ThermodynamicTemperature}};
|
thermodynamic_temperature::{degree_celsius, ThermodynamicTemperature}};
|
||||||
|
|
||||||
use crate::{device::{dfu, sys_timer},
|
use crate::{device::{dfu, sys_timer},
|
||||||
laser_diode::{laser_diode::{LdDrive, LdSettingsSummary, StatusReport as LdStatusReport},
|
laser_diode::{laser_diode::{LdDrive, LdSettingsSummary, StatusReport as LdStatusReport},
|
||||||
pd_mon_params::ResponsitivityUnit},
|
pd_mon_params::{self, ResponsitivityUnit}},
|
||||||
net::net,
|
net::net,
|
||||||
thermostat::{ad7172::FilterType,
|
thermostat::{ad7172::FilterType,
|
||||||
pid_state::PidSettings::*,
|
pid_state::PidSettings::*,
|
||||||
|
@ -61,6 +62,8 @@ enum DeviceCmd {
|
||||||
Reserved,
|
Reserved,
|
||||||
SetIPSettings,
|
SetIPSettings,
|
||||||
SetActiveReportMode,
|
SetActiveReportMode,
|
||||||
|
SetPdFinGain,
|
||||||
|
SetPdTransconductance,
|
||||||
GetStatusReport,
|
GetStatusReport,
|
||||||
GetSettingsSummary,
|
GetSettingsSummary,
|
||||||
Dfu,
|
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) => {
|
Some(DeviceCmd::GetStatusReport) => {
|
||||||
send_status_report(buffer, laser, thermostat, socket);
|
send_status_report(buffer, laser, thermostat, socket);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue