Added PoC serial interface and host application
This commit is contained in:
parent
87f84d5254
commit
2cc6651aca
|
@ -8,16 +8,19 @@ version = "0.1.0"
|
|||
[dependencies]
|
||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
defmt = { version = "0.3", features = ["encoding-rzcobs"] }
|
||||
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
rtic = { version = "2.0.1", features = [ "thumbv7-backend" ] }
|
||||
defmt-rtt = "0.4"
|
||||
embedded-hal = {version = "0.2.3"}
|
||||
embedded-hal = "0.2.3"
|
||||
stm32f1xx-hal = { version = "0.10.0", features = ["stm32f103", "rt", "medium"] }
|
||||
nb = "1.0.0"
|
||||
arrayvec = {version = "0.7.0", default-features = false}
|
||||
arrayvec = { version = "0.7.0", default-features = false }
|
||||
systick-monotonic = "1.0.0"
|
||||
rtic-monotonics = {version = "1.4.1", features = ["cortex-m-systick"] }
|
||||
usb-device = "0.2.8"
|
||||
usbd-serial = "0.1.1"
|
||||
rtic-sync = {version = "1.1.1"}
|
||||
ufmt = "0.2.0"
|
||||
|
||||
# cargo build/run
|
||||
[profile.dev]
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import time
|
||||
import serial
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def main():
|
||||
ser = serial.Serial(sys.argv[1])
|
||||
|
||||
|
||||
short_term = []
|
||||
long_term = []
|
||||
|
||||
while True:
|
||||
ser.write(b"?")
|
||||
|
||||
line = ser.readline()
|
||||
line = line.strip()
|
||||
|
||||
f1, f2 = line.split(b'|')
|
||||
short_term += [float(f1)]
|
||||
long_term += [float(f2)]
|
||||
|
||||
print(float(f2))
|
||||
|
||||
plt.clf()
|
||||
plt.ylim((10 - 0.000_001, 10 + 0.000_001))
|
||||
plt.plot(short_term)
|
||||
plt.plot(long_term)
|
||||
plt.draw()
|
||||
plt.pause(1.0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
141
src/main.rs
141
src/main.rs
|
@ -18,9 +18,12 @@ use rtic::app;
|
|||
#[app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI3])]
|
||||
mod app {
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use cortex_m::asm::delay;
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use rtic_monotonics::systick::*;
|
||||
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use stm32f1xx_hal::{
|
||||
gpio::{self, gpioa, gpioc, Alternate, Output, PushPull},
|
||||
pac,
|
||||
|
@ -31,6 +34,9 @@ mod app {
|
|||
timer::{self, Channel, PwmHz, Tim4NoRemap},
|
||||
};
|
||||
|
||||
use stm32f1xx_hal::usb::{Peripheral, UsbBus, UsbBusType};
|
||||
use usb_device::prelude::*;
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
board_led: gpioc::PC13<Output<PushPull>>,
|
||||
|
@ -40,13 +46,18 @@ mod app {
|
|||
}
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
struct Shared {
|
||||
usb_dev: UsbDevice<'static, UsbBusType>,
|
||||
serial: usbd_serial::SerialPort<'static, UsbBusType>,
|
||||
current_freq: f64,
|
||||
short_avg: f64,
|
||||
}
|
||||
|
||||
const target_freq: f64 = 10.0f64;
|
||||
const TARGET_FREQ: f64 = 10.0f64;
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let mut rcc = cx.device.RCC.constrain();
|
||||
let rcc = cx.device.RCC.constrain();
|
||||
let mut flash = cx.device.FLASH.constrain();
|
||||
|
||||
let clocks = rcc
|
||||
|
@ -56,6 +67,7 @@ mod app {
|
|||
.pclk1(24.MHz())
|
||||
.freeze(&mut flash.acr);
|
||||
|
||||
assert!(clocks.usbclk_valid());
|
||||
defmt::info!("Clock Setup done");
|
||||
|
||||
// Initialize the systick interrupt & obtain the token to prove that we did
|
||||
|
@ -148,10 +160,49 @@ mod app {
|
|||
|
||||
defmt::info!("Timer Setup done");
|
||||
|
||||
static mut USB_BUS: Option<usb_device::bus::UsbBusAllocator<UsbBusType>> = None;
|
||||
|
||||
let mut gpioa = cx.device.GPIOA.split();
|
||||
|
||||
let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
|
||||
usb_dp.set_low();
|
||||
delay(clocks.sysclk().raw() / 100);
|
||||
|
||||
let usb_dm = gpioa.pa11;
|
||||
let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh);
|
||||
|
||||
let usb = Peripheral {
|
||||
usb: cx.device.USB,
|
||||
pin_dm: usb_dm,
|
||||
pin_dp: usb_dp,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
USB_BUS.replace(UsbBus::new(usb));
|
||||
}
|
||||
|
||||
let serial = usbd_serial::SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() });
|
||||
|
||||
let usb_dev = UsbDeviceBuilder::new(
|
||||
unsafe { USB_BUS.as_ref().unwrap() },
|
||||
UsbVidPid(0x16c0, 0x27dd),
|
||||
)
|
||||
.manufacturer("Arbitrary Precision Instruments")
|
||||
.product("cheapsdo")
|
||||
.serial_number("1337")
|
||||
.device_class(usbd_serial::USB_CLASS_CDC)
|
||||
.build();
|
||||
|
||||
|
||||
update_pwm::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {},
|
||||
Shared {
|
||||
serial,
|
||||
usb_dev,
|
||||
current_freq: 0.0f64,
|
||||
short_avg: 0.0f64,
|
||||
},
|
||||
Local {
|
||||
board_led,
|
||||
tim2,
|
||||
|
@ -161,10 +212,10 @@ mod app {
|
|||
)
|
||||
}
|
||||
|
||||
const WINDOW_LEN : usize = 60;
|
||||
const WINDOW_LEN: usize = 100;
|
||||
|
||||
#[task(local=[tim2, tim3, pwm, board_led])]
|
||||
async fn update_pwm(cx: update_pwm::Context) {
|
||||
#[task(local=[tim2, tim3, pwm, board_led], shared=[current_freq, short_avg])]
|
||||
async fn update_pwm(mut cx: update_pwm::Context) {
|
||||
defmt::info!("Update Task started");
|
||||
|
||||
let tim2 = cx.local.tim2;
|
||||
|
@ -172,7 +223,6 @@ mod app {
|
|||
let pwm = cx.local.pwm;
|
||||
let board_led = cx.local.board_led;
|
||||
|
||||
let mut avg = 10f64;
|
||||
let max_pwm = pwm.get_max_duty() as i32;
|
||||
let mut cur_pwm = max_pwm / 2;
|
||||
|
||||
|
@ -187,6 +237,7 @@ mod app {
|
|||
|
||||
loop {
|
||||
let mut short_avg = 0.0f64;
|
||||
let mut last_freq = 10.0f64;
|
||||
|
||||
let mut count = 0;
|
||||
while count < WINDOW_LEN {
|
||||
|
@ -214,28 +265,35 @@ mod app {
|
|||
let freq = (diff_ic as f64) / 1_000_000f64;
|
||||
defmt::info!("freq:\t{} MHz", freq);
|
||||
|
||||
let diff = freq - avg;
|
||||
let diff = freq - last_freq;
|
||||
last_freq = freq;
|
||||
if diff > 0.000_100 || diff < -0.000_100 {
|
||||
defmt::info!("Out of range, dropping sample.");
|
||||
continue;
|
||||
}
|
||||
|
||||
short_avg += freq / WINDOW_LEN as f64;
|
||||
avg = avg * 0.999 + freq * 0.001;
|
||||
cx.shared.current_freq.lock(|current_freq| {
|
||||
*current_freq = freq;
|
||||
});
|
||||
|
||||
short_avg += freq / WINDOW_LEN as f64;
|
||||
|
||||
count += 1;
|
||||
board_led.toggle();
|
||||
}
|
||||
|
||||
defmt::info!("short_avg:\t{} MHz", short_avg);
|
||||
cx.shared.short_avg.lock(|avg| {
|
||||
*avg = short_avg;
|
||||
});
|
||||
|
||||
let diff = (10.0 - short_avg) * 1_000_000.0;
|
||||
|
||||
let diff = (TARGET_FREQ - short_avg) * 1_000_000.0;
|
||||
if diff > 1.0 || diff < -1.0 {
|
||||
cur_pwm += diff as i32 * 10;
|
||||
} else if short_avg > 10.0 {
|
||||
cur_pwm += diff as i32 * 15;
|
||||
} else if diff < -0.001 {
|
||||
cur_pwm -= 1;
|
||||
} else if short_avg < 10.0 {
|
||||
} else if diff > 0.001 {
|
||||
cur_pwm += 1;
|
||||
}
|
||||
|
||||
|
@ -243,11 +301,58 @@ mod app {
|
|||
cur_pwm = if cur_pwm > max_pwm { max_pwm } else { cur_pwm };
|
||||
|
||||
pwm.set_duty(Channel::C1, cur_pwm as u16);
|
||||
|
||||
defmt::info!("avg:\t{} MHz", avg);
|
||||
defmt::info!("pwm:\t{}", cur_pwm);
|
||||
|
||||
Systick::delay(500.millis()).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = USB_HP_CAN_TX, shared = [usb_dev, serial, current_freq, short_avg])]
|
||||
fn usb_tx(cx: usb_tx::Context) {
|
||||
let mut usb_dev = cx.shared.usb_dev;
|
||||
let mut serial = cx.shared.serial;
|
||||
let mut current_freq = cx.shared.current_freq;
|
||||
let mut short_avg = cx.shared.short_avg;
|
||||
|
||||
(&mut usb_dev, &mut serial, &mut current_freq, &mut short_avg).lock(|usb_dev, serial, current_freq, short_avg| {
|
||||
usb_poll(usb_dev, serial, current_freq, short_avg);
|
||||
});
|
||||
}
|
||||
|
||||
#[task(binds = USB_LP_CAN_RX0, shared = [usb_dev, serial, current_freq, short_avg])]
|
||||
fn usb_rx0(cx: usb_rx0::Context) {
|
||||
let mut usb_dev = cx.shared.usb_dev;
|
||||
let mut serial = cx.shared.serial;
|
||||
let mut current_freq = cx.shared.current_freq;
|
||||
let mut short_avg = cx.shared.short_avg;
|
||||
|
||||
(&mut usb_dev, &mut serial, &mut current_freq, &mut short_avg).lock(|usb_dev, serial, current_freq, short_avg| {
|
||||
usb_poll(usb_dev, serial, current_freq, short_avg);
|
||||
});
|
||||
}
|
||||
|
||||
fn usb_poll<B: usb_device::bus::UsbBus>(
|
||||
usb_dev: &mut usb_device::prelude::UsbDevice<'static, B>,
|
||||
serial: &mut usbd_serial::SerialPort<'static, B>,
|
||||
current_freq: &mut f64,
|
||||
short_avg: &mut f64,
|
||||
) {
|
||||
if !usb_dev.poll(&mut [serial]) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut buf = [0u8; 8];
|
||||
|
||||
match serial.read(&mut buf) {
|
||||
Ok(count) if count > 0 => {
|
||||
if buf[0] == b'?' {
|
||||
|
||||
let mut data = arrayvec::ArrayString::<32>::new();
|
||||
write!(data, "{}|{}\n\r", current_freq, short_avg).unwrap();
|
||||
serial.write(data.as_bytes()).unwrap();
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue