Added in seperate plots.

This commit is contained in:
2025-08-15 22:48:37 +02:00
parent 5537a991d3
commit 57ca3e313f
4 changed files with 57 additions and 25 deletions

View File

@@ -9,6 +9,7 @@ eframe = { version = "0.32.0"}
egui_plot = "0.33.0" egui_plot = "0.33.0"
log = "0.4.27" log = "0.4.27"
simple_logger = "5.0.0" simple_logger = "5.0.0"
atomic_float = "1.1.0"
[dependencies.bioz-icd-rs] [dependencies.bioz-icd-rs]
path = "../bioz-icd-rs" path = "../bioz-icd-rs"

View File

@@ -1,8 +1,7 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::RangeInclusive; use atomic_float::AtomicF32;
use tokio::{sync::mpsc::{Sender}}; use tokio::{sync::mpsc::{Sender}};
use eframe::egui::{self, Color32, DragValue, Key, Layout, Modifiers, }; use eframe::egui::{self, Color32, DragValue, Key, Layout, Modifiers, };
@@ -13,7 +12,6 @@ use crate::plot::TimeSeriesPlot;
use crate::signals::FrequencySignal; use crate::signals::FrequencySignal;
pub struct App { pub struct App {
frequency: f32,
run_impedancemeter_tx: Sender<FrequencySignal>, run_impedancemeter_tx: Sender<FrequencySignal>,
pub magnitude: Arc<Mutex<f32>>, pub magnitude: Arc<Mutex<f32>>,
pub phase: Arc<Mutex<f32>>, pub phase: Arc<Mutex<f32>>,
@@ -21,12 +19,12 @@ pub struct App {
pub phase_series: Arc<Mutex<TimeSeriesPlot>>, pub phase_series: Arc<Mutex<TimeSeriesPlot>>,
pub connected: Arc<AtomicBool>, pub connected: Arc<AtomicBool>,
pub on: bool, pub on: bool,
pub data_frequency: Arc<AtomicF32>,
} }
impl App { impl App {
pub fn new(run_impedancemeter_tx: Sender<FrequencySignal>) -> Self { pub fn new(run_impedancemeter_tx: Sender<FrequencySignal>) -> Self {
let app = App { let app = App {
frequency: 2.0, // Default frequency
run_impedancemeter_tx, run_impedancemeter_tx,
magnitude: Arc::new(Mutex::new(0.0)), magnitude: Arc::new(Mutex::new(0.0)),
phase: Arc::new(Mutex::new(0.0)), phase: Arc::new(Mutex::new(0.0)),
@@ -34,6 +32,7 @@ impl App {
phase_series: Arc::new(Mutex::new(TimeSeriesPlot::new())), phase_series: Arc::new(Mutex::new(TimeSeriesPlot::new())),
connected: Arc::new(AtomicBool::new(false)), connected: Arc::new(AtomicBool::new(false)),
on: true, on: true,
data_frequency: Arc::new(AtomicF32::new(0.0)),
}; };
app.update_start_stop(); app.update_start_stop();
app app
@@ -42,7 +41,7 @@ impl App {
pub fn update_start_stop(&self) { pub fn update_start_stop(&self) {
match self.on { match self.on {
true => { true => {
if let Err(e) = self.run_impedancemeter_tx.try_send(FrequencySignal::Start(self.frequency)) { if let Err(e) = self.run_impedancemeter_tx.try_send(FrequencySignal::Start(0.0)) {
eprintln!("Failed to send start command: {:?}", e); eprintln!("Failed to send start command: {:?}", e);
} }
}, },
@@ -65,11 +64,7 @@ impl eframe::App for App {
egui::widgets::global_theme_preference_switch(ui); egui::widgets::global_theme_preference_switch(ui);
ui.separator(); ui.separator();
let response = ui.add_enabled(connected, DragValue::new(&mut self.frequency).speed(0.1).update_while_editing(false).range(RangeInclusive::new(0, 50))); ui.label(format!("{} Hz", self.data_frequency.load(Ordering::Relaxed)));
if response.changed() && response.lost_focus() {
self.update_start_stop();
}
ui.separator(); ui.separator();
@@ -104,7 +99,7 @@ impl eframe::App for App {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
let available_height = ui.available_height(); let available_height = ui.available_height();
let half_height = available_height / 4.0; let half_height = available_height / 2.0;
let point_pos = vec![[*self.magnitude.lock().unwrap() as f64, *self.phase.lock().unwrap() as f64]]; let point_pos = vec![[*self.magnitude.lock().unwrap() as f64, *self.phase.lock().unwrap() as f64]];
@@ -125,7 +120,7 @@ impl eframe::App for App {
// Magnitude and phase // Magnitude and phase
let magnitude = self.magnitude_series.lock().unwrap(); let magnitude = self.magnitude_series.lock().unwrap();
let phase = self.phase_series.lock().unwrap(); let phase = self.phase_series.lock().unwrap();
Plot::new("magnitude_phase") Plot::new("magnitude")
.allow_scroll(false) .allow_scroll(false)
.allow_drag(false) .allow_drag(false)
// .center_y_axis(true) // .center_y_axis(true)
@@ -133,29 +128,47 @@ impl eframe::App for App {
.y_axis_label("Value [...]") .y_axis_label("Value [...]")
.y_axis_min_width(2.0) .y_axis_min_width(2.0)
.show(ui, |plot_ui| { .show(ui, |plot_ui| {
plot_ui.line( plot_ui.line(
Line::new("Magnitude", magnitude.plot_values()) Line::new("Magnitude", magnitude.plot_values())
.color(Color32::LIGHT_GREEN) .color(Color32::BLUE)
); );
});
},
);
// Plot pressure
ui.allocate_ui_with_layout(
egui::vec2(ui.available_width(), half_height),
Layout::top_down(egui::Align::Min),
|ui| {
// Magnitude and phase
let magnitude = self.magnitude_series.lock().unwrap();
let phase = self.phase_series.lock().unwrap();
Plot::new("phase")
.allow_scroll(false)
.allow_drag(false)
// .center_y_axis(true)
.legend(Legend::default().position(Corner::LeftTop))
.y_axis_label("Value [...]")
.y_axis_min_width(2.0)
.show(ui, |plot_ui| {
plot_ui.line( plot_ui.line(
Line::new("Phase", phase.plot_values()) Line::new("Phase", phase.plot_values())
.color(Color32::LIGHT_RED) .color(Color32::RED)
); );
}); });
}, },
); );
}); });
Plot::new("State") // Plot::new("State")
.allow_scroll(false) // .allow_scroll(false)
.allow_drag(false) // .allow_drag(false)
.data_aspect(1.0) // .data_aspect(1.0)
.center_y_axis(true) // .center_y_axis(true)
.show(ui, |plot_ui| { // .show(ui, |plot_ui| {
plot_ui.points(point_pos); // plot_ui.points(point_pos);
plot_ui.set_plot_bounds(bounds); // plot_ui.set_plot_bounds(bounds);
}); // });
}); });
// CMD- or control-W to close window // CMD- or control-W to close window

View File

@@ -29,6 +29,7 @@ fn main() {
let magnitude_series_clone = app.magnitude_series.clone(); let magnitude_series_clone = app.magnitude_series.clone();
let phase_series_clone = app.phase_series.clone(); let phase_series_clone = app.phase_series.clone();
let connected_clone = app.connected.clone(); let connected_clone = app.connected.clone();
let data_frequency_clone = app.data_frequency.clone();
// Execute the runtime in its own thread. // Execute the runtime in its own thread.
std::thread::spawn(move || { std::thread::spawn(move || {
@@ -40,6 +41,7 @@ fn main() {
magnitude_series_clone, magnitude_series_clone,
phase_series_clone, phase_series_clone,
connected_clone, connected_clone,
data_frequency_clone,
)); ));
}); });

View File

@@ -3,7 +3,9 @@ use log::{error, info};
use tokio::select; use tokio::select;
use tokio::sync::mpsc::{Sender, Receiver}; use tokio::sync::mpsc::{Sender, Receiver};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use atomic_float::AtomicF32;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::icd; use crate::icd;
@@ -21,7 +23,18 @@ pub async fn communicate_with_hardware(
magnitude_series: Arc<Mutex<TimeSeriesPlot>>, magnitude_series: Arc<Mutex<TimeSeriesPlot>>,
phase_series: Arc<Mutex<TimeSeriesPlot>>, phase_series: Arc<Mutex<TimeSeriesPlot>>,
connected: Arc<AtomicBool>, connected: Arc<AtomicBool>,
data_frequency: Arc<AtomicF32>,
) { ) {
let data_counter = Arc::new(AtomicU32::new(0));
let data_counter_clone = data_counter.clone();
tokio::spawn(async move {
loop {
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
data_frequency.store(data_counter.load(Ordering::Relaxed) as f32, Ordering::Relaxed);
data_counter.store(0, Ordering::Relaxed);
}
});
#[derive(Default)] #[derive(Default)]
struct Settings { struct Settings {
frequency: Option<FrequencySignal>, frequency: Option<FrequencySignal>,
@@ -52,6 +65,7 @@ pub async fn communicate_with_hardware(
.unwrap(); .unwrap();
let data = (magnitude_series.clone(), phase_series.clone(), magnitude.clone(), phase.clone()); let data = (magnitude_series.clone(), phase_series.clone(), magnitude.clone(), phase.clone());
let data_counter_clone = data_counter_clone.clone();
tokio::spawn(async move { tokio::spawn(async move {
while let Ok(val) = sub.recv().await { while let Ok(val) = sub.recv().await {
@@ -65,6 +79,8 @@ pub async fn communicate_with_hardware(
mag_plot.add(val.magnitude as f64); mag_plot.add(val.magnitude as f64);
phase_plot.add(val.phase as f64); phase_plot.add(val.phase as f64);
data_counter_clone.fetch_add(1, Ordering::Relaxed);
} }
info!("ImpedanceTopic subscription ended."); info!("ImpedanceTopic subscription ended.");