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