Change multi to sweep.

This commit is contained in:
2025-11-06 12:13:32 +01:00
parent ce23d40b38
commit b7bce96407
6 changed files with 47 additions and 46 deletions

View File

@@ -43,7 +43,7 @@ const MEASUREMENT_POINTS_VARIANTS: [MeasurementPointSet; 2] = [
#[derive(Clone, Copy,Debug, PartialEq, Eq)]
enum TabActive {
Single,
Multi,
Sweep,
Shortcuts,
}
@@ -66,7 +66,7 @@ pub struct App {
pub dft_num: Arc<Mutex<IcdDftNum>>,
pub measurement_points: Arc<Mutex<MeasurementPointSet>>,
pub periods_per_dft: Arc<Mutex<Option<f32>>>,
pub periods_per_dft_multi: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
pub periods_per_dft_sweep: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
pub gui_logging_enabled: Arc<AtomicBool>,
log_filename: String,
}
@@ -83,7 +83,7 @@ struct TabViewer {
dft_num: Arc<Mutex<IcdDftNum>>,
measurement_points: Arc<Mutex<MeasurementPointSet>>,
periods_per_dft: Arc<Mutex<Option<f32>>>,
periods_per_dft_multi: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
periods_per_dft_sweep: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
show_settings: bool,
show_settings_toggle: Option<bool>,
}
@@ -216,7 +216,8 @@ impl TabViewer {
});
}
fn multi_tab(&mut self, ui: &mut egui::Ui) {
fn sweep_tab(&mut self, ui: &mut egui::Ui) {
egui::Frame::default().inner_margin(5).show(ui, |ui| {
let settings = CollapsingHeader::new("Settings")
.open(self.show_settings_toggle)
@@ -269,7 +270,7 @@ impl TabViewer {
});
});
ui.add_enabled_ui(*on, |ui| {
let (freq, periods_per_dft_vec) = self.periods_per_dft_multi.lock().unwrap().clone();
let (freq, periods_per_dft_vec) = self.periods_per_dft_sweep.lock().unwrap().clone();
fn format_frequency(freq: u32) -> String {
if freq >= 1_000 {
@@ -474,7 +475,7 @@ impl egui_dock::TabViewer for TabViewer {
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
match tab.as_str() {
"Single" => self.single_tab(ui),
"Multi" => self.multi_tab(ui),
"Sweep" => self.sweep_tab(ui),
"Shortcuts" => self.shortcuts(ui),
_ => {
let _ = ui.label("Unknown tab");
@@ -496,7 +497,7 @@ impl App {
let dft_num = Arc::new(Mutex::new(IcdDftNum::Num2048));
let measurement_points = Arc::new(Mutex::new(MeasurementPointSet::Eighteen));
let periods_per_dft = Arc::new(Mutex::new(None));
let periods_per_dft_multi = Arc::new(Mutex::new((MeasurementPointSet::Eighteen.values().to_vec(), None)));
let periods_per_dft_sweep = Arc::new(Mutex::new((MeasurementPointSet::Eighteen.values().to_vec(), None)));
let on = Arc::new(Mutex::new(true));
let tab_active = TabActive::Single;
@@ -512,7 +513,7 @@ impl App {
dft_num: dft_num.clone(),
measurement_points: measurement_points.clone(),
periods_per_dft: periods_per_dft.clone(),
periods_per_dft_multi: periods_per_dft_multi.clone(),
periods_per_dft_sweep: periods_per_dft_sweep.clone(),
on: on.clone(),
show_settings: false,
show_settings_toggle: None,
@@ -520,7 +521,7 @@ impl App {
// Step 3: Construct App
let app = App {
tree: DockState::new(vec!["Single".to_string(), "Multi".to_string(), "Shortcuts".to_string()]),
tree: DockState::new(vec!["Single".to_string(), "Sweep".to_string(), "Shortcuts".to_string()]),
tab_viewer,
run_impedancemeter_tx,
log_tx,
@@ -538,7 +539,7 @@ impl App {
dft_num,
measurement_points,
periods_per_dft,
periods_per_dft_multi,
periods_per_dft_sweep,
gui_logging_enabled: Arc::new(AtomicBool::new(false)),
log_filename: format!("log_{}.csv", Local::now().format("%Y%m%d"))
};
@@ -572,8 +573,8 @@ impl App {
error!("Failed to send start command: {:?}", e);
}
},
(TabActive::Multi, true) => {
if let Err(e) = self.run_impedancemeter_tx.try_send(StartStopSignal::StartMulti(*self.lead_mode.lock().unwrap(), *self.measurement_points.lock().unwrap())) {
(TabActive::Sweep, true) => {
if let Err(e) = self.run_impedancemeter_tx.try_send(StartStopSignal::StartSweep(*self.lead_mode.lock().unwrap(), *self.measurement_points.lock().unwrap())) {
error!("Failed to send start command: {:?}", e);
}
},
@@ -684,12 +685,12 @@ impl eframe::App for App {
info!("Switched to Single tab");
}
}
"Multi" => {
if self.tab_active != TabActive::Multi {
self.tab_active = TabActive::Multi;
"Sweep" => {
if self.tab_active != TabActive::Sweep {
self.tab_active = TabActive::Sweep;
*self.on.lock().unwrap() = false;
self.update_start_stop();
info!("Switched to Multi tab");
info!("Switched to Sweep tab");
}
}
"Shortcuts" => {

View File

@@ -41,7 +41,7 @@ async fn main() {
let data_frequency_clone = app.data_frequency.clone();
let periods_per_dft = app.periods_per_dft.clone();
let periods_per_dft_multi = app.periods_per_dft_multi.clone();
let periods_per_dft_sweep = app.periods_per_dft_sweep.clone();
let gui_logging_enabled = app.gui_logging_enabled.clone();
@@ -61,7 +61,7 @@ async fn main() {
connected_clone,
data_frequency_clone,
periods_per_dft,
periods_per_dft_multi,
periods_per_dft_sweep,
gui_logging_enabled,
log_tx_clone,
));

View File

@@ -5,7 +5,7 @@ use postcard_rpc::{
};
use std::convert::Infallible;
use bioz_icd_rs::{
BioImpedanceLeadMode, GetUniqueIdEndpoint, ImpedanceInitResult, MultiImpedanceInitResult, MultiImpedanceStartRequest, PingEndpoint, SetGreenLedEndpoint, SingleImpedanceStartRequest, StartMultiImpedanceEndpoint, StartSingleImpedanceEndpoint, StopSingleImpedanceEndpoint
BioImpedanceLeadMode, GetUniqueIdEndpoint, ImpedanceInitResult, SweepImpedanceInitResult, SweepImpedanceStartRequest, PingEndpoint, SetGreenLedEndpoint, SingleImpedanceStartRequest, StartSweepImpedanceEndpoint, StartSingleImpedanceEndpoint, StopImpedanceEndpoint
};
use crate::icd::{IcdDftNum, MeasurementPointSet};
@@ -74,13 +74,13 @@ impl WorkbookClient {
Ok(response)
}
pub async fn start_impedancemeter_multi(
pub async fn start_impedancemeter_sweep(
&self,
lead_mode: BioImpedanceLeadMode,
points: MeasurementPointSet,
) -> Result<MultiImpedanceInitResult, WorkbookError<Infallible>> {
) -> Result<SweepImpedanceInitResult, WorkbookError<Infallible>> {
let response = self.client
.send_resp::<StartMultiImpedanceEndpoint>(&MultiImpedanceStartRequest { lead_mode, points })
.send_resp::<StartSweepImpedanceEndpoint>(&SweepImpedanceStartRequest { lead_mode, points })
.await?;
Ok(response)
}
@@ -88,7 +88,7 @@ impl WorkbookClient {
pub async fn stop_impedancemeter(&self) -> Result<bool, WorkbookError<Infallible>> {
let res = self
.client
.send_resp::<StopSingleImpedanceEndpoint>(&())
.send_resp::<StopImpedanceEndpoint>(&())
.await?;
Ok(res)
}

View File

@@ -30,7 +30,7 @@ pub async fn communicate_with_hardware(
connected: Arc<AtomicBool>,
data_frequency: Arc<AtomicF32>,
periods_per_dft: Arc<Mutex<Option<f32>>>,
periods_per_dft_multi: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
periods_per_dft_sweep: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
gui_logging_enabled: Arc<AtomicBool>,
log_tx: Sender<LoggingSignal>,
) {
@@ -120,22 +120,22 @@ pub async fn communicate_with_hardware(
info!("SingleImpedanceOutputTopic subscription ended.");
});
// Subscribe to MultiImpedanceOutputTopic8
let mut multi_impedance_sub = workbook_client
// Subscribe to SweepImpedanceOutputTopic8
let mut sweep_impedance_sub = workbook_client
.client
.subscribe_multi::<icd::MultiImpedanceOutputTopic>(8)
.subscribe_multi::<icd::SweepImpedanceOutputTopic>(8)
.await
.unwrap();
let data = bode_series.clone();
let data_counter_clone_multi = data_counter_clone.clone();
let data_counter_clone_sweep = data_counter_clone.clone();
// Clone log_tx for the task
let gui_logging_enabled_clone = gui_logging_enabled.clone();
let log_tx_clone = log_tx.clone();
tokio::spawn(async move {
while let Ok(val) = multi_impedance_sub.recv().await {
while let Ok(val) = sweep_impedance_sub.recv().await {
match val.points {
@@ -148,7 +148,7 @@ pub async fn communicate_with_hardware(
bode_plot.update_phases(MeasurementPointSet::Eight, phases.clone());
}
if gui_logging_enabled_clone.load(Ordering::Relaxed) {
if let Err(e) = log_tx_clone.send(LoggingSignal::MultiImpedance(SystemTime::now(), MeasurementPointSet::Eight.values().to_vec(), magnitudes.clone(), phases.clone())).await {
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), MeasurementPointSet::Eight.values().to_vec(), magnitudes.clone(), phases.clone())).await {
error!("Failed to send logging signal: {:?}", e);
}
}
@@ -162,14 +162,14 @@ pub async fn communicate_with_hardware(
bode_plot.update_phases(MeasurementPointSet::Eighteen, phases.clone());
}
if gui_logging_enabled_clone.load(Ordering::Relaxed) {
if let Err(e) = log_tx_clone.send(LoggingSignal::MultiImpedance(SystemTime::now(), MeasurementPointSet::Eighteen.values().to_vec(), magnitudes.clone(), phases.clone())).await {
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), MeasurementPointSet::Eighteen.values().to_vec(), magnitudes.clone(), phases.clone())).await {
error!("Failed to send logging signal: {:?}", e);
}
}
},
}
data_counter_clone_multi.fetch_add(1, Ordering::Relaxed);
data_counter_clone_sweep.fetch_add(1, Ordering::Relaxed);
}
});
@@ -194,27 +194,27 @@ pub async fn communicate_with_hardware(
}
}
},
StartStopSignal::StartMulti(lead_mode, num_points) => {
match workbook_client.start_impedancemeter_multi(lead_mode, num_points).await {
StartStopSignal::StartSweep(lead_mode, num_points) => {
match workbook_client.start_impedancemeter_sweep(lead_mode, num_points).await {
Ok(Ok(periods)) => {
settings.lock().unwrap().frequency = Some(StartStopSignal::StartMulti(lead_mode, num_points));
info!("Multi-point Impedancemeter started.");
settings.lock().unwrap().frequency = Some(StartStopSignal::StartSweep(lead_mode, num_points));
info!("Sweep Impedancemeter started.");
match num_points {
MeasurementPointSet::Eight => {
*periods_per_dft_multi.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_8.into_iter().collect()));
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_8.into_iter().collect()));
},
MeasurementPointSet::Eighteen => {
*periods_per_dft_multi.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_18.into_iter().collect()));
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_18.into_iter().collect()));
},
}
},
Ok(Err(e)) => {
error!("Failed to multi-init on hardware: {:?}", e);
*periods_per_dft_multi.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
error!("Failed to sweep-init on hardware: {:?}", e);
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
},
Err(e) => {
error!("Communication error when starting impedancemeter: {:?}", e);
*periods_per_dft_multi.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
}
}
},
@@ -224,8 +224,8 @@ pub async fn communicate_with_hardware(
} else {
settings.lock().unwrap().frequency = Some(StartStopSignal::Stop);
*periods_per_dft.lock().unwrap() = None;
let (freq, _) = periods_per_dft_multi.lock().unwrap().clone();
*periods_per_dft_multi.lock().unwrap() = (freq, None);
let (freq, _) = periods_per_dft_sweep.lock().unwrap().clone();
*periods_per_dft_sweep.lock().unwrap() = (freq, None);
info!("Impedancemeter stopped.");
}
},

View File

@@ -22,7 +22,7 @@ pub async fn log_data(mut data: Receiver<LoggingSignal>) {
.await;
}
}
LoggingSignal::MultiImpedance(timestamp, frequencies, magnitudes, phases) => {
LoggingSignal::SweepImpedance(timestamp, frequencies, magnitudes, phases) => {
if let Some(f) = file.as_mut() {
for i in 0..frequencies.len() {
let _ = f.write_all(

View File

@@ -5,13 +5,13 @@ use crate::icd::{BioImpedanceLeadMode, IcdDftNum, MeasurementPointSet};
#[derive(Copy, Clone, Debug)]
pub enum StartStopSignal {
StartSingle(u32, BioImpedanceLeadMode, IcdDftNum), // frequency in Hz, lead mode, DFT number
StartMulti(BioImpedanceLeadMode, MeasurementPointSet), // lead mode, number of points per measurement
StartSweep(BioImpedanceLeadMode, MeasurementPointSet), // lead mode, number of points per measurement
Stop,
}
pub enum LoggingSignal {
SingleImpedance(SystemTime, u32, f32, f32), // frequency, magnitude, phase
MultiImpedance(SystemTime, Vec<u32>, Vec<f32>, Vec<f32>), // frequency, magnitude, phase
SweepImpedance(SystemTime, Vec<u32>, Vec<f32>, Vec<f32>), // frequency, magnitude, phase
StartFileLogging(String), // e.g. filename
StopFileLogging,
}