Add ADC Measurements with moving average
- remove analog reference - output I, Q, TE11, TE21 - add ADC Reference voltage (VDDA)
This commit is contained in:
+66
-29
@@ -4,7 +4,10 @@
|
||||
use pid_control as _; // global logger + panicking-behavior + memory layout
|
||||
|
||||
// TODO
|
||||
// - look into adc hold capacity
|
||||
// - atomic reference for te11 value -> done
|
||||
// - embedded-cli
|
||||
// -> this would also make the adc stuff less ugly
|
||||
// - average adc samples -> done?
|
||||
// - uart configurable reference -> done
|
||||
// - fix analog reference -> done
|
||||
@@ -17,6 +20,8 @@ use pid_control as _; // global logger + panicking-behavior + memory layout
|
||||
mod app {
|
||||
use defmt::info;
|
||||
|
||||
use core::fmt::Write;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use embedded_cli::{Command, cli::CliBuilder, writer::Writer};
|
||||
use pid_control::ringbuffer::Ringbuffer;
|
||||
use pid_control::uart_parser::Parser;
|
||||
@@ -39,8 +44,12 @@ mod app {
|
||||
const KI: f32 = 0.5;
|
||||
const KD: f32 = 0f32;
|
||||
|
||||
const VDDA: f32 = 3.313;
|
||||
|
||||
const AVGBUFSIZE: usize = 5000;
|
||||
|
||||
static TE11_AVG: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
// Shared resources go here
|
||||
#[shared]
|
||||
struct Shared {
|
||||
@@ -57,14 +66,19 @@ mod app {
|
||||
p: f32,
|
||||
i: f32,
|
||||
d: f32,
|
||||
reference: Pin<'C', 2, Analog>,
|
||||
adc_te21: Pin<'C', 0, Analog>,
|
||||
adc_q: Pin<'C', 1, Analog>,
|
||||
adc_i: Pin<'C', 2, Analog>,
|
||||
input: Pin<'C', 3, Analog>,
|
||||
adc1: Adc<ADC1, adc::Enabled>,
|
||||
adc2: Adc<ADC2, adc::Enabled>,
|
||||
dac: C1<DAC, dac::Enabled>,
|
||||
parser: Parser,
|
||||
freq: hal::time::Hertz,
|
||||
avgbuffer: Ringbuffer<AVGBUFSIZE>,
|
||||
avgbuffer_i: Ringbuffer<33>,
|
||||
avgbuffer_q: Ringbuffer<33>,
|
||||
avgbuffer_te21: Ringbuffer<33>,
|
||||
avgbuffer_te11: Ringbuffer<AVGBUFSIZE>,
|
||||
}
|
||||
|
||||
#[init]
|
||||
@@ -91,18 +105,15 @@ mod app {
|
||||
let gpioa = ctx.device.GPIOA.split(ccdr.peripheral.GPIOA);
|
||||
let gpioc = ctx.device.GPIOC.split(ccdr.peripheral.GPIOC);
|
||||
|
||||
let reference = gpioc.pc2.into_analog();
|
||||
let adc_i = gpioc.pc2.into_analog();
|
||||
let adc_q = gpioc.pc1.into_analog();
|
||||
let adc_te21 = gpioc.pc0.into_analog();
|
||||
let input = gpioc.pc3.into_analog();
|
||||
let output = gpioa.pa4;
|
||||
|
||||
let tx = gpioa.pa9.into_alternate();
|
||||
let rx = gpioa.pa10.into_alternate();
|
||||
|
||||
info!(
|
||||
"reference input: P{}{}",
|
||||
(reference.port_id() + b'A') as char,
|
||||
reference.pin_id()
|
||||
);
|
||||
info!(
|
||||
"controller input: P{}{}",
|
||||
(input.port_id() + b'A') as char,
|
||||
@@ -150,18 +161,20 @@ mod app {
|
||||
);
|
||||
|
||||
let mut adc1 = adc1.enable();
|
||||
adc1.set_resolution(adc::Resolution::TwelveBit);
|
||||
adc1.set_resolution(adc::Resolution::SixteenBit);
|
||||
adc1.set_sample_time(hal::adc::AdcSampleTime::T_810);
|
||||
|
||||
let mut adc2 = adc2.enable();
|
||||
adc2.set_resolution(adc::Resolution::TwelveBit);
|
||||
adc2.set_resolution(adc::Resolution::SixteenBit);
|
||||
// adc2.set_resolution(adc::Resolution::TwelveBit);
|
||||
|
||||
info!("----------Setup TIM----------");
|
||||
|
||||
let freq = 10.Hz();
|
||||
let freq = 10.kHz();
|
||||
info!("TIM3:");
|
||||
info!("\tfreq: {} Hz", freq.to_Hz());
|
||||
info!("\tfreq: {} kHz", freq.to_kHz());
|
||||
|
||||
let timer3 = ctx
|
||||
let mut timer3 = ctx
|
||||
.device
|
||||
.TIM3
|
||||
.timer(freq, ccdr.peripheral.TIM3, &ccdr.clocks);
|
||||
@@ -178,7 +191,7 @@ mod app {
|
||||
info!("===========init complete==========");
|
||||
|
||||
// Enable interrupts
|
||||
// timer3.listen(Event::TimeOut); // NOTE: comment for digital reference via uart
|
||||
timer3.listen(Event::TimeOut);
|
||||
timer2.listen(Event::TimeOut);
|
||||
serial.listen(serial::Event::Rxne);
|
||||
|
||||
@@ -199,11 +212,14 @@ mod app {
|
||||
// .build()
|
||||
// .ok()?;
|
||||
|
||||
let target = 0.7 / 3.3 * 4095f32;
|
||||
let target = 0.7 / VDDA * 4095f32;
|
||||
|
||||
let averaging = 50;
|
||||
let config = PIDConfig { averaging };
|
||||
let avgbuffer = Ringbuffer::new(averaging);
|
||||
let avgbuffer_i = Ringbuffer::<33>::new(32);
|
||||
let avgbuffer_q = Ringbuffer::<33>::new(32);
|
||||
let avgbuffer_te21 = Ringbuffer::<33>::new(32);
|
||||
let avgbuffer_te11 = Ringbuffer::new(averaging);
|
||||
|
||||
(
|
||||
Shared {
|
||||
@@ -212,13 +228,18 @@ mod app {
|
||||
config,
|
||||
},
|
||||
Local {
|
||||
avgbuffer,
|
||||
avgbuffer_te11,
|
||||
avgbuffer_i,
|
||||
avgbuffer_q,
|
||||
avgbuffer_te21,
|
||||
timer3,
|
||||
timer2,
|
||||
p: 0f32,
|
||||
i: 0f32,
|
||||
d: 0f32,
|
||||
reference,
|
||||
adc_te21,
|
||||
adc_q,
|
||||
adc_i,
|
||||
input,
|
||||
adc1,
|
||||
adc2,
|
||||
@@ -256,11 +277,9 @@ mod app {
|
||||
let parser = ctx.local.parser;
|
||||
|
||||
ctx.shared.serial.lock(|serial| {
|
||||
use core::fmt::Write;
|
||||
while serial.is_rxne() {
|
||||
if let Ok(data) = serial.read() {
|
||||
// echo back
|
||||
let _ = write!(serial, "{}", data as char);
|
||||
|
||||
// parse incoming byte
|
||||
if let Some(target) = parser.input_byte(data) {
|
||||
@@ -273,31 +292,49 @@ mod app {
|
||||
});
|
||||
}
|
||||
|
||||
#[task(binds = TIM3, local = [timer3, adc1, reference], shared = [target])]
|
||||
fn adc_target(mut ctx: adc_target::Context) {
|
||||
#[task(binds = TIM3, local = [timer3, adc1, adc_i, adc_q, adc_te21, avgbuffer_i, avgbuffer_q, avgbuffer_te21], shared = [target, serial])]
|
||||
fn adc_print(mut ctx: adc_print::Context) {
|
||||
// Clear interrupt flag
|
||||
ctx.local.timer3.clear_irq();
|
||||
let target: u32 = ctx.local.adc1.read(ctx.local.reference).unwrap(); // WHY COMPILER WHY
|
||||
ctx.shared.target.lock(|t| {
|
||||
*t = target as f32;
|
||||
ctx.local
|
||||
.avgbuffer_i
|
||||
.push(ctx.local.adc1.read(ctx.local.adc_i).unwrap());
|
||||
ctx.local
|
||||
.avgbuffer_q
|
||||
.push(ctx.local.adc1.read(ctx.local.adc_q).unwrap());
|
||||
ctx.local
|
||||
.avgbuffer_te21
|
||||
.push(ctx.local.adc1.read(ctx.local.adc_te21).unwrap());
|
||||
|
||||
ctx.shared.serial.lock(|serial| {
|
||||
let _ = writeln!(
|
||||
serial,
|
||||
"I: {},\tQ: {},\tTE11: {},\tTE21: {}\r",
|
||||
ctx.local.avgbuffer_i.average() as f32 * VDDA / u16::MAX as f32,
|
||||
ctx.local.avgbuffer_q.average() as f32 * VDDA / u16::MAX as f32,
|
||||
TE11_AVG.load(Ordering::SeqCst) as f32 * VDDA / u16::MAX as f32,
|
||||
ctx.local.avgbuffer_te21.average() as f32 * VDDA / u16::MAX as f32,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// #[task(binds = TIM2, local = [timer2, p, i, d, input, adc2, dac, freq], shared = [target, serial], priority = 1)]
|
||||
#[task(binds = TIM2, local = [timer2, p, i, d, input, adc2, dac, freq, avgbuffer], shared = [target, config], priority = 1)]
|
||||
#[task(binds = TIM2, local = [timer2, p, i, d, input, adc2, dac, freq, avgbuffer_te11], shared = [target, config], priority = 1)]
|
||||
fn pid(mut ctx: pid::Context) {
|
||||
// Clear interrupt flag
|
||||
ctx.local.timer2.clear_irq();
|
||||
|
||||
// let config: PIDConfig = ctx.shared.config.lock(|c| *c);
|
||||
let avgbuffer = ctx.local.avgbuffer;
|
||||
|
||||
let avgbuffer = ctx.local.avgbuffer_te11;
|
||||
let t = 1f32 / (ctx.local.freq.to_kHz() as f32);
|
||||
|
||||
let input: u32 = ctx.local.adc2.read(ctx.local.input).unwrap();
|
||||
avgbuffer.push(input);
|
||||
// let input: f32 = input as f32;
|
||||
let input: f32 = avgbuffer.average() as f32;
|
||||
let input: u32 = avgbuffer.average();
|
||||
TE11_AVG.store(input, Ordering::SeqCst);
|
||||
|
||||
let input: f32 = (input >> 4) as f32;
|
||||
|
||||
let p = ctx.local.p;
|
||||
let i = ctx.local.i;
|
||||
|
||||
Reference in New Issue
Block a user