Added pwm plot
This commit is contained in:
parent
c5bec82d59
commit
3673c14cdb
|
@ -37,9 +37,9 @@ mod app {
|
|||
use heapless::Vec;
|
||||
use postcard::{from_bytes_cobs, to_vec_cobs};
|
||||
|
||||
use cheapsdo_protocol::{*, DeviceMessage};
|
||||
use cheapsdo_protocol::{DeviceMessage, HostMessage, StatusMessage};
|
||||
|
||||
const USB_BUFFER_SIZE : usize = 64;
|
||||
const USB_BUFFER_SIZE: usize = 64;
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
|
@ -53,8 +53,7 @@ mod app {
|
|||
struct Shared {
|
||||
usb_dev: UsbDevice<'static, UsbBusType>,
|
||||
serial: usbd_serial::SerialPort<'static, UsbBusType>,
|
||||
current_freq: f64,
|
||||
short_avg: f64,
|
||||
device_status: StatusMessage,
|
||||
buffer: Vec<u8, USB_BUFFER_SIZE>,
|
||||
}
|
||||
|
||||
|
@ -204,8 +203,7 @@ mod app {
|
|||
Shared {
|
||||
serial,
|
||||
usb_dev,
|
||||
current_freq: 0.0f64,
|
||||
short_avg: 0.0f64,
|
||||
device_status: StatusMessage::default(),
|
||||
buffer: Vec::new(),
|
||||
},
|
||||
Local {
|
||||
|
@ -217,10 +215,9 @@ mod app {
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
const WINDOW_LEN: usize = 100;
|
||||
|
||||
#[task(local=[tim2, tim3, pwm, board_led], shared=[current_freq, short_avg])]
|
||||
#[task(local=[tim2, tim3, pwm, board_led], shared=[device_status])]
|
||||
async fn update_pwm(mut cx: update_pwm::Context) {
|
||||
defmt::info!("Update Task started");
|
||||
|
||||
|
@ -278,8 +275,8 @@ mod app {
|
|||
continue;
|
||||
}
|
||||
|
||||
cx.shared.current_freq.lock(|current_freq| {
|
||||
*current_freq = freq;
|
||||
cx.shared.device_status.lock(|device_status| {
|
||||
device_status.measured_frequency = freq;
|
||||
});
|
||||
|
||||
short_avg += freq / WINDOW_LEN as f64;
|
||||
|
@ -289,8 +286,8 @@ mod app {
|
|||
}
|
||||
|
||||
defmt::info!("short_avg:\t{} MHz", short_avg);
|
||||
cx.shared.short_avg.lock(|avg| {
|
||||
*avg = short_avg;
|
||||
cx.shared.device_status.lock(|device_status| {
|
||||
device_status.average_frequency = short_avg;
|
||||
});
|
||||
|
||||
let diff = (TARGET_FREQ - short_avg) * 1_000_000.0;
|
||||
|
@ -305,6 +302,10 @@ mod app {
|
|||
cur_pwm = if cur_pwm < 0 { 0 } else { cur_pwm };
|
||||
cur_pwm = if cur_pwm > max_pwm { max_pwm } else { cur_pwm };
|
||||
|
||||
cx.shared.device_status.lock(|device_status| {
|
||||
device_status.pwm = cur_pwm as u16;
|
||||
});
|
||||
|
||||
pwm.set_duty(Channel::C1, cur_pwm as u16);
|
||||
defmt::info!("pwm:\t{}", cur_pwm);
|
||||
|
||||
|
@ -312,52 +313,39 @@ mod app {
|
|||
}
|
||||
}
|
||||
|
||||
#[task(binds = USB_HP_CAN_TX, shared = [usb_dev, serial, buffer, current_freq, short_avg])]
|
||||
#[task(binds = USB_HP_CAN_TX, shared = [usb_dev, serial, buffer, device_status])]
|
||||
fn usb_tx(cx: usb_tx::Context) {
|
||||
let mut usb_dev = cx.shared.usb_dev;
|
||||
let mut serial = cx.shared.serial;
|
||||
let mut buffer = cx.shared.buffer;
|
||||
let mut current_freq = cx.shared.current_freq;
|
||||
let mut short_avg = cx.shared.short_avg;
|
||||
let mut device_status = cx.shared.device_status;
|
||||
|
||||
(
|
||||
&mut usb_dev,
|
||||
&mut serial,
|
||||
&mut buffer,
|
||||
&mut current_freq,
|
||||
&mut short_avg,
|
||||
)
|
||||
.lock(|usb_dev, serial, buffer, current_freq, short_avg| {
|
||||
usb_poll(usb_dev, serial, buffer, current_freq, short_avg);
|
||||
});
|
||||
(&mut usb_dev, &mut serial, &mut buffer, &mut device_status).lock(
|
||||
|usb_dev, serial, buffer, device_status| {
|
||||
usb_poll(usb_dev, serial, buffer, device_status);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, serial, buffer, current_freq, short_avg])]
|
||||
#[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, serial, buffer, device_status])]
|
||||
fn usb_rx0(cx: usb_rx0::Context) {
|
||||
let mut usb_dev = cx.shared.usb_dev;
|
||||
let mut serial = cx.shared.serial;
|
||||
let mut buffer = cx.shared.buffer;
|
||||
let mut current_freq = cx.shared.current_freq;
|
||||
let mut short_avg = cx.shared.short_avg;
|
||||
let mut device_status = cx.shared.device_status;
|
||||
|
||||
(
|
||||
&mut usb_dev,
|
||||
&mut serial,
|
||||
&mut buffer,
|
||||
&mut current_freq,
|
||||
&mut short_avg,
|
||||
)
|
||||
.lock(|usb_dev, serial, buffer, current_freq, short_avg| {
|
||||
usb_poll(usb_dev, serial, buffer, current_freq, short_avg);
|
||||
});
|
||||
(&mut usb_dev, &mut serial, &mut buffer, &mut device_status).lock(
|
||||
|usb_dev, serial, buffer, device_status| {
|
||||
usb_poll(usb_dev, serial, buffer, device_status);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn usb_poll<B: usb_device::bus::UsbBus>(
|
||||
usb_dev: &mut usb_device::prelude::UsbDevice<'static, B>,
|
||||
serial: &mut usbd_serial::SerialPort<'static, B>,
|
||||
buffer: &mut Vec<u8, USB_BUFFER_SIZE>,
|
||||
current_freq: &mut f64,
|
||||
short_avg: &mut f64,
|
||||
device_status: &StatusMessage,
|
||||
) {
|
||||
if !usb_dev.poll(&mut [serial]) {
|
||||
return;
|
||||
|
@ -376,7 +364,7 @@ mod app {
|
|||
|
||||
loop {
|
||||
if let Some(idx) = buffer.iter().position(|&x| x == 0) {
|
||||
let (msg, rest) = buffer.split_at(idx+1);
|
||||
let (msg, rest) = buffer.split_at(idx + 1);
|
||||
|
||||
let mut message = [0u8; 128];
|
||||
message[0..msg.len()].clone_from_slice(msg);
|
||||
|
@ -385,19 +373,15 @@ mod app {
|
|||
match host_msg {
|
||||
Ok(host_msg) => match host_msg {
|
||||
HostMessage::RequestStatus => {
|
||||
let device_msg = DeviceMessage::Status(StatusMessage{
|
||||
measured_frequency: *current_freq,
|
||||
average_frequency: *short_avg,
|
||||
pwm: 0,
|
||||
});
|
||||
|
||||
let bytes = to_vec_cobs::<DeviceMessage, USB_BUFFER_SIZE>(&device_msg).unwrap();
|
||||
let device_msg = DeviceMessage::Status(device_status.clone());
|
||||
let bytes =
|
||||
to_vec_cobs::<DeviceMessage, USB_BUFFER_SIZE>(&device_msg).unwrap();
|
||||
serial.write(bytes.as_slice()).unwrap();
|
||||
},
|
||||
HostMessage::SetPLLOutputs => {
|
||||
defmt::error!("PLL output is not implemented yet")
|
||||
}
|
||||
}
|
||||
HostMessage::SetPLLOutputs => {
|
||||
defmt::error!("PLL output is not implemented yet")
|
||||
}
|
||||
},
|
||||
Err(err) => defmt::error!("Unable to parse host message: {}", err),
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
pub fn frequency(freq: f64) -> String {
|
||||
let rest = (freq * 1_000_000_000.0) as u64;
|
||||
let milli_hz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let hz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let khz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let mhz = rest % 1000;
|
||||
|
||||
format!("{:02}.{:03} {:03} {:03} MHz", mhz, khz, hz, milli_hz)
|
||||
}
|
|
@ -11,6 +11,8 @@ use egui_plot::{Line, Plot, PlotBounds, PlotPoints};
|
|||
use cheapsdo_protocol::*;
|
||||
use postcard::{from_bytes_cobs, to_stdvec_cobs};
|
||||
|
||||
mod formatters;
|
||||
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default(),
|
||||
|
@ -27,6 +29,7 @@ struct SharedState {
|
|||
device_state: StatusMessage,
|
||||
average_points: Vec<[f64; 2]>,
|
||||
measured_points: Vec<[f64; 2]>,
|
||||
pwm_points: Vec<[f64; 2]>,
|
||||
}
|
||||
|
||||
impl Default for SharedState {
|
||||
|
@ -35,6 +38,7 @@ impl Default for SharedState {
|
|||
device_state: StatusMessage::default(),
|
||||
average_points: Vec::<[f64; 2]>::new(),
|
||||
measured_points: Vec::<[f64; 2]>::new(),
|
||||
pwm_points: Vec::<[f64; 2]>::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,38 +104,62 @@ impl eframe::App for CheapsdoControl {
|
|||
{
|
||||
let mut state = self.shared_state.lock().unwrap();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!(
|
||||
"Measured: {}",
|
||||
state.device_state.measured_frequency
|
||||
));
|
||||
ui.label(format!("Average: {}", state.device_state.average_frequency));
|
||||
ui.label(
|
||||
egui::RichText::new(format!(
|
||||
"Measured: {}",
|
||||
formatters::frequency(state.device_state.measured_frequency)
|
||||
))
|
||||
.family(egui::FontFamily::Monospace)
|
||||
.size(20.0),
|
||||
);
|
||||
|
||||
ui.add_space(100.0);
|
||||
|
||||
ui.label(
|
||||
egui::RichText::new(format!(
|
||||
"Average: {}",
|
||||
formatters::frequency(state.device_state.average_frequency)
|
||||
))
|
||||
.family(egui::FontFamily::Monospace)
|
||||
.size(20.0),
|
||||
);
|
||||
});
|
||||
|
||||
ui.add_space(20.0);
|
||||
|
||||
let average_line = Line::new(PlotPoints::new(state.average_points.clone()));
|
||||
let measured_line = Line::new(PlotPoints::new(state.measured_points.clone()));
|
||||
Plot::new("my_plot")
|
||||
Plot::new("frequency_plot")
|
||||
.view_aspect(4.0)
|
||||
.allow_zoom(false)
|
||||
.allow_scroll(false)
|
||||
.allow_drag(false)
|
||||
.allow_boxed_zoom(false)
|
||||
.y_axis_width(20)
|
||||
.y_axis_formatter(|val, _, _| {
|
||||
let rest = (val * 1_000_000_000.0) as u64;
|
||||
let milli_hz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let hz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let khz = rest % 1000;
|
||||
let rest = rest / 1000;
|
||||
let mhz = rest % 1000;
|
||||
|
||||
format!("{:02}.{:03} {:03} {:03}", mhz, khz, hz, milli_hz)
|
||||
.y_axis_width(12)
|
||||
.y_axis_formatter(|val, _, _| formatters::frequency(val))
|
||||
.label_formatter(|name, value| {
|
||||
format!("{}: {}", name, formatters::frequency(value.y))
|
||||
})
|
||||
.show(ui, |plot_ui| {
|
||||
plot_ui.set_auto_bounds([true, true].into());
|
||||
plot_ui.line(average_line);
|
||||
//plot_ui.line(measured_line);
|
||||
})
|
||||
});
|
||||
|
||||
ui.add_space(20.0);
|
||||
|
||||
let pwm_line = Line::new(PlotPoints::new(state.pwm_points.clone()));
|
||||
Plot::new("pwm_plot")
|
||||
.view_aspect(4.0)
|
||||
.allow_zoom(false)
|
||||
.allow_scroll(false)
|
||||
.allow_drag(false)
|
||||
.allow_boxed_zoom(false)
|
||||
.y_axis_width(12)
|
||||
.show(ui, |plot_ui| {
|
||||
plot_ui.set_auto_bounds([true, true].into());
|
||||
plot_ui.line(pwm_line);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -165,6 +193,7 @@ fn poll_device(port: String, state: Arc<Mutex<SharedState>>, ctx: egui::Context)
|
|||
state
|
||||
.measured_points
|
||||
.push([x, status_msg.measured_frequency]);
|
||||
state.pwm_points.push([x, status_msg.pwm as f64]);
|
||||
|
||||
state.device_state = status_msg;
|
||||
ctx.request_repaint()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![no_std]
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
pub enum DeviceMessage {
|
||||
|
@ -13,14 +13,13 @@ pub enum HostMessage {
|
|||
SetPLLOutputs,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
pub struct StatusMessage {
|
||||
pub measured_frequency: f64,
|
||||
pub average_frequency: f64,
|
||||
pub pwm: u16,
|
||||
}
|
||||
|
||||
|
||||
impl Default for StatusMessage {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -29,4 +28,4 @@ impl Default for StatusMessage {
|
|||
pwm: 0u16,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue