Added pwm plot

This commit is contained in:
Sebastian 2023-12-24 23:06:03 +01:00
parent c5bec82d59
commit 3673c14cdb
4 changed files with 99 additions and 75 deletions

View File

@ -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),
};

View File

@ -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)
}

View File

@ -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()

View File

@ -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,
}
}
}
}