iir: tweak, add offset

master
Robert Jördens 2019-03-29 18:33:32 +00:00
parent 9fc6868fdf
commit 293520e26e
3 changed files with 44 additions and 34 deletions

View File

@ -19,10 +19,11 @@ load
# monitor reset halt # monitor reset halt
# cycle counter delta tool, place two bkpts around the section # cycle counter delta tool, place two bkpts around the section
set var $cc=0xe0001004
define qq define qq
print *0xe0001004-$t0 print *$cc-$t0
set var $t0=*0xe0001004 set var $t0=*$cc
continue continue
end end
set var $t0=0xe0001004 set var $t0=*$cc
continue continue

View File

@ -2,12 +2,12 @@ use core::f32;
pub type IIRState = [f32; 5]; pub type IIRState = [f32; 5];
#[derive(Default,Copy,Clone,Debug)] #[derive(Copy,Clone)]
pub struct IIR { pub struct IIR {
pub x_offset: f32,
pub y_offset: f32,
pub ba: IIRState, pub ba: IIRState,
pub scale: f32, pub y_offset: f32,
pub y_min: f32,
pub y_max: f32,
} }
fn abs(x: f32) -> f32 { fn abs(x: f32) -> f32 {
@ -15,23 +15,27 @@ fn abs(x: f32) -> f32 {
} }
fn copysign(x: f32, y: f32) -> f32 { fn copysign(x: f32, y: f32) -> f32 {
match () { if (x >= 0. && y >= 0.) || (x <= 0. && y <= 0.) {
_ if (x >= 0. && y >= 0.) || (x <= 0. && y <= 0.) => y, x
_ => -y } else {
-x
} }
} }
fn macc(y0: f32, x: &[f32], a: &[f32]) -> f32 {
y0 + x.iter().zip(a.iter()) .map(|(&i, &j)| i * j).sum::<f32>()
}
impl IIR { impl IIR {
pub fn pi(&mut self, kp: f32, ki: f32, g: f32) -> Result<(), &str> { pub fn set_pi(&mut self, kp: f32, ki: f32, g: f32) -> Result<(), &'static str> {
let ki = copysign(kp, ki); let ki = copysign(ki, kp);
let g = copysign(kp, g); let g = copysign(g, kp);
let (a1, b0, b1) = match () { let (a1, b0, b1) =
_ if abs(ki) < f32::EPSILON => (0., kp, 0.), if abs(ki) < f32::EPSILON {
_ => { (0., kp, 0.)
let c = match () { } else {
_ if abs(g) < f32::EPSILON => 1., let c = if abs(g) < f32::EPSILON { 1. }
_ => 1./(1. + ki/g) else { 1./(1. + ki/g) };
};
let a1 = 2.*c - 1.; let a1 = 2.*c - 1.;
let b0 = ki*c + kp; let b0 = ki*c + kp;
let b1 = ki*c - a1*kp; let b1 = ki*c - a1*kp;
@ -39,8 +43,7 @@ impl IIR {
return Err("low integrator gain and/or gain limit") return Err("low integrator gain and/or gain limit")
} }
(a1, b0, b1) (a1, b0, b1)
} };
};
self.ba[0] = b0; self.ba[0] = b0;
self.ba[1] = b1; self.ba[1] = b1;
self.ba[2] = 0.; self.ba[2] = 0.;
@ -49,17 +52,17 @@ impl IIR {
Ok(()) Ok(())
} }
pub fn set_x_offset(&mut self, xo: f32) {
let b: f32 = self.ba[..3].iter().sum();
self.y_offset = xo*b;
}
pub fn update(&self, xy: &mut IIRState, x0: f32) -> f32 { pub fn update(&self, xy: &mut IIRState, x0: f32) -> f32 {
xy.rotate_right(1); xy.rotate_right(1);
xy[0] = x0 + self.x_offset; xy[0] = x0;
let y0 = macc(self.y_offset, xy, &self.ba) let y0 = macc(self.y_offset, xy, &self.ba)
.min(self.scale).max(-self.scale); .max(self.y_min).min(self.y_max);
xy[xy.len()/2] = y0; xy[xy.len()/2] = y0;
y0 y0
} }
} }
fn macc(y0: f32, x: &[f32], a: &[f32]) -> f32 {
y0 + x.iter().zip(a.iter())
.map(|(&i, &j)| i * j).sum::<f32>()
}

View File

@ -556,8 +556,14 @@ fn main() -> ! {
rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit()); rcc.apb1lenr.modify(|_, w| w.tim2en().set_bit());
tim2_setup(&dp.TIM2); tim2_setup(&dp.TIM2);
unsafe { IIR_CH[0].pi(0.1, 10.*2e-6/2., 0.).expect("bad coefficients"); } unsafe {
unsafe { IIR_CH[1].pi(-0.1, 10.*2e-6/2., 0.).expect("bad coefficients"); } let t = 2e-6*2.;
IIR_CH[0].set_pi(1., 0., 0.).expect("bad coefficients");
IIR_CH[0].set_x_offset(0.*SCALE);
IIR_CH[1].set_pi(-0.1, -10.*t, 0.).expect("bad coefficients");
IIR_CH[1].set_x_offset(0.1*SCALE);
}
cortex_m::interrupt::free(|cs| { cortex_m::interrupt::free(|cs| {
cp.NVIC.enable(stm32::Interrupt::SPI1); cp.NVIC.enable(stm32::Interrupt::SPI1);
@ -584,8 +590,8 @@ fn TIM2() { // FIXME
const SCALE: f32 = ((1 << 15) - 1) as f32; const SCALE: f32 = ((1 << 15) - 1) as f32;
static mut IIR_STATE: [IIRState; 2] = [[0.; 5]; 2]; static mut IIR_STATE: [IIRState; 2] = [[0.; 5]; 2];
static mut IIR_CH: [IIR; 2] = [ static mut IIR_CH: [IIR; 2] = [
IIR{ y_offset: 0., x_offset: 0., ba: [0., 0., 0., 0., 0.], scale: SCALE }, IIR{ ba: [0., 0., 0., 0., 0.], y_offset: 0.,
IIR{ y_offset: 0., x_offset: 0., ba: [0., 0., 0., 0., 0.], scale: SCALE }]; y_min: -SCALE, y_max: SCALE }; 2];
#[interrupt] #[interrupt]
fn SPI1() { fn SPI1() {
@ -594,8 +600,8 @@ fn SPI1() {
cortex_m::interrupt::free(|cs| { cortex_m::interrupt::free(|cs| {
let spip = SPIP.borrow(cs).borrow(); let spip = SPIP.borrow(cs).borrow();
let (spi1, spi2, spi4, spi5) = spip.as_ref().unwrap(); let (spi1, spi2, spi4, spi5) = spip.as_ref().unwrap();
let sr = spi1.sr.read();
let sr = spi1.sr.read();
if sr.eot().bit_is_set() { if sr.eot().bit_is_set() {
spi1.ifcr.write(|w| w.eotc().set_bit()); spi1.ifcr.write(|w| w.eotc().set_bit());
} }