Add ADC Measurements with moving average

- remove analog reference
- output I, Q, TE11, TE21
- add ADC Reference voltage (VDDA)
This commit is contained in:
2026-06-12 16:22:54 +02:00
parent e01ce0a570
commit ee3343e47f
+66 -29
View File
@@ -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;