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

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ pub async fn communicate_with_hardware(
connected: Arc<AtomicBool>, connected: Arc<AtomicBool>,
data_frequency: Arc<AtomicF32>, data_frequency: Arc<AtomicF32>,
periods_per_dft: Arc<Mutex<Option<f32>>>, 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>, gui_logging_enabled: Arc<AtomicBool>,
log_tx: Sender<LoggingSignal>, log_tx: Sender<LoggingSignal>,
) { ) {
@@ -120,22 +120,22 @@ pub async fn communicate_with_hardware(
info!("SingleImpedanceOutputTopic subscription ended."); info!("SingleImpedanceOutputTopic subscription ended.");
}); });
// Subscribe to MultiImpedanceOutputTopic8 // Subscribe to SweepImpedanceOutputTopic8
let mut multi_impedance_sub = workbook_client let mut sweep_impedance_sub = workbook_client
.client .client
.subscribe_multi::<icd::MultiImpedanceOutputTopic>(8) .subscribe_multi::<icd::SweepImpedanceOutputTopic>(8)
.await .await
.unwrap(); .unwrap();
let data = bode_series.clone(); 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 // Clone log_tx for the task
let gui_logging_enabled_clone = gui_logging_enabled.clone(); let gui_logging_enabled_clone = gui_logging_enabled.clone();
let log_tx_clone = log_tx.clone(); let log_tx_clone = log_tx.clone();
tokio::spawn(async move { 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 { match val.points {
@@ -148,7 +148,7 @@ pub async fn communicate_with_hardware(
bode_plot.update_phases(MeasurementPointSet::Eight, phases.clone()); bode_plot.update_phases(MeasurementPointSet::Eight, phases.clone());
} }
if gui_logging_enabled_clone.load(Ordering::Relaxed) { 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); 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()); bode_plot.update_phases(MeasurementPointSet::Eighteen, phases.clone());
} }
if gui_logging_enabled_clone.load(Ordering::Relaxed) { 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); 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) => { StartStopSignal::StartSweep(lead_mode, num_points) => {
match workbook_client.start_impedancemeter_multi(lead_mode, num_points).await { match workbook_client.start_impedancemeter_sweep(lead_mode, num_points).await {
Ok(Ok(periods)) => { Ok(Ok(periods)) => {
settings.lock().unwrap().frequency = Some(StartStopSignal::StartMulti(lead_mode, num_points)); settings.lock().unwrap().frequency = Some(StartStopSignal::StartSweep(lead_mode, num_points));
info!("Multi-point Impedancemeter started."); info!("Sweep Impedancemeter started.");
match num_points { match num_points {
MeasurementPointSet::Eight => { 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 => { 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)) => { Ok(Err(e)) => {
error!("Failed to multi-init on hardware: {:?}", e); error!("Failed to sweep-init on hardware: {:?}", 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);
}, },
Err(e) => { Err(e) => {
error!("Communication error when starting impedancemeter: {:?}", 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 { } else {
settings.lock().unwrap().frequency = Some(StartStopSignal::Stop); settings.lock().unwrap().frequency = Some(StartStopSignal::Stop);
*periods_per_dft.lock().unwrap() = None; *periods_per_dft.lock().unwrap() = None;
let (freq, _) = periods_per_dft_multi.lock().unwrap().clone(); let (freq, _) = periods_per_dft_sweep.lock().unwrap().clone();
*periods_per_dft_multi.lock().unwrap() = (freq, None); *periods_per_dft_sweep.lock().unwrap() = (freq, None);
info!("Impedancemeter stopped."); info!("Impedancemeter stopped.");
} }
}, },

View File

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

View File

@@ -5,13 +5,13 @@ use crate::icd::{BioImpedanceLeadMode, IcdDftNum, MeasurementPointSet};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum StartStopSignal { pub enum StartStopSignal {
StartSingle(u32, BioImpedanceLeadMode, IcdDftNum), // frequency in Hz, lead mode, DFT number 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, Stop,
} }
pub enum LoggingSignal { pub enum LoggingSignal {
SingleImpedance(SystemTime, u32, f32, f32), // frequency, magnitude, phase 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 StartFileLogging(String), // e.g. filename
StopFileLogging, StopFileLogging,
} }