2017-05-09 19:07:59 +08:00
|
|
|
use core::num::Float;
|
|
|
|
|
2017-05-09 15:57:54 +08:00
|
|
|
use board;
|
|
|
|
use pid;
|
|
|
|
|
|
|
|
const PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
|
|
|
kp: 0.004,
|
|
|
|
ki: 0.002,
|
|
|
|
kd: 0.0,
|
|
|
|
output_min: 0.0,
|
|
|
|
output_max: 30.0,
|
|
|
|
integral_min: -5000.0,
|
|
|
|
integral_max: 5000.0
|
|
|
|
};
|
|
|
|
|
|
|
|
pub struct Controller {
|
2017-05-10 00:10:52 +08:00
|
|
|
fbi_target: f32,
|
|
|
|
fbi_range: board::EmissionRange,
|
2017-05-10 00:29:52 +08:00
|
|
|
fbi_buffer: [f32; 16],
|
|
|
|
fbi_buffer_count: usize,
|
2017-05-10 00:10:52 +08:00
|
|
|
last_fbi: Option<f32>,
|
2017-05-09 19:07:59 +08:00
|
|
|
pid: pid::Controller,
|
2017-05-10 00:10:52 +08:00
|
|
|
|
2017-05-09 19:07:59 +08:00
|
|
|
last_fv: Option<f32>,
|
2017-05-10 00:10:52 +08:00
|
|
|
|
|
|
|
fbv_target: f32,
|
2017-05-09 19:07:59 +08:00
|
|
|
last_fbv: Option<f32>
|
2017-05-09 15:57:54 +08:00
|
|
|
}
|
|
|
|
|
2017-05-11 23:15:01 +08:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub struct ControllerStatus {
|
|
|
|
pub ready: bool,
|
|
|
|
pub fbi: Option<f32>,
|
|
|
|
pub fv: Option<f32>,
|
|
|
|
pub fbv: Option<f32>
|
|
|
|
}
|
|
|
|
|
2017-05-09 15:57:54 +08:00
|
|
|
|
|
|
|
impl Controller {
|
|
|
|
pub const fn new() -> Controller {
|
|
|
|
Controller {
|
2017-05-10 00:10:52 +08:00
|
|
|
fbi_target: 0.0,
|
2017-05-11 23:15:01 +08:00
|
|
|
fbi_range: board::EmissionRange::Med,
|
2017-05-10 00:29:52 +08:00
|
|
|
fbi_buffer: [0.0; 16],
|
|
|
|
fbi_buffer_count: 0,
|
2017-05-10 00:10:52 +08:00
|
|
|
last_fbi: None,
|
2017-05-09 19:07:59 +08:00
|
|
|
pid: pid::Controller::new(PID_PARAMETERS),
|
2017-05-10 00:10:52 +08:00
|
|
|
|
2017-05-09 19:07:59 +08:00
|
|
|
last_fv: None,
|
2017-05-10 00:10:52 +08:00
|
|
|
|
|
|
|
fbv_target: 0.0,
|
2017-05-09 19:07:59 +08:00
|
|
|
last_fbv: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:10:52 +08:00
|
|
|
pub fn adc_input(&mut self, fbi_sample: u16, fd_sample: u16, fv_sample: u16, fbv_sample: u16) {
|
|
|
|
let fbi_voltage = ((fbi_sample as f32) - board::FBI_ADC_OFFSET)/board::FBI_ADC_GAIN;
|
|
|
|
let fbi_r225 = fbi_voltage/board::FBI_R225;
|
2017-05-10 00:29:52 +08:00
|
|
|
let fbi = match self.fbi_range {
|
2017-05-10 00:10:52 +08:00
|
|
|
board::EmissionRange::Low => fbi_r225,
|
|
|
|
board::EmissionRange::Med => {
|
|
|
|
let fd_voltage = ((fd_sample as f32) - board::FD_ADC_OFFSET)/board::FD_ADC_GAIN;
|
|
|
|
fbi_r225 + (fbi_voltage - fd_voltage)/board::FBI_R223
|
|
|
|
},
|
|
|
|
board::EmissionRange::High => {
|
2017-05-11 14:55:00 +08:00
|
|
|
let fd_voltage = 0.9;
|
2017-05-10 00:10:52 +08:00
|
|
|
fbi_r225 + (fbi_voltage - fd_voltage)/board::FBI_R224
|
|
|
|
}
|
2017-05-10 00:29:52 +08:00
|
|
|
};
|
|
|
|
self.fbi_buffer[self.fbi_buffer_count] = fbi;
|
|
|
|
self.fbi_buffer_count += 1;
|
|
|
|
if self.fbi_buffer_count == self.fbi_buffer.len() {
|
|
|
|
let mut fbi_avg: f32 = 0.0;
|
|
|
|
for fbi in self.fbi_buffer.iter() {
|
|
|
|
fbi_avg += *fbi;
|
|
|
|
}
|
|
|
|
self.last_fbi = Some(fbi_avg/(self.fbi_buffer.len() as f32));
|
|
|
|
self.fbi_buffer_count = 0;
|
|
|
|
}
|
|
|
|
|
2017-05-09 19:07:59 +08:00
|
|
|
self.last_fv = Some(fv_sample as f32/board::FV_ADC_GAIN);
|
2017-05-10 00:10:52 +08:00
|
|
|
self.last_fbv = Some(fbv_sample as f32/board::FBV_ADC_GAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_emission_target(&mut self, amperes: f32) {
|
|
|
|
self.fbi_target = amperes;
|
|
|
|
self.fbi_range = board::EmissionRange::Low;
|
|
|
|
if amperes > 120e-6 {
|
|
|
|
self.fbi_range = board::EmissionRange::Med;
|
|
|
|
}
|
|
|
|
if amperes > 8e-3 {
|
|
|
|
self.fbi_range = board::EmissionRange::High;
|
|
|
|
}
|
|
|
|
board::set_emission_range(self.fbi_range);
|
2017-05-09 19:07:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_bias_target(&mut self, volts: f32) {
|
|
|
|
self.fbv_target = volts;
|
|
|
|
board::set_fbv_pwm((volts/board::FBV_PWM_GAIN) as u16);
|
|
|
|
}
|
|
|
|
|
2017-05-11 23:15:01 +08:00
|
|
|
fn emission_ready(&self) -> bool {
|
2017-05-10 00:29:52 +08:00
|
|
|
match self.last_fbi {
|
|
|
|
None => false,
|
2017-05-11 23:15:01 +08:00
|
|
|
Some(last_fbi) => (self.fbi_target - last_fbi).abs()/self.fbi_target < 0.02
|
2017-05-10 00:29:52 +08:00
|
|
|
}
|
2017-05-09 19:07:59 +08:00
|
|
|
}
|
|
|
|
|
2017-05-11 23:15:01 +08:00
|
|
|
fn bias_ready(&self) -> bool {
|
2017-05-09 19:07:59 +08:00
|
|
|
match self.last_fbv {
|
|
|
|
None => false,
|
|
|
|
Some(last_fbv) => (self.fbv_target - last_fbv).abs() < 1.0
|
2017-05-09 15:57:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-11 14:55:00 +08:00
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.pid.reset();
|
|
|
|
self.fbi_buffer_count = 0;
|
|
|
|
self.last_fbi = None;
|
|
|
|
self.last_fv = None;
|
|
|
|
self.last_fbv = None;
|
|
|
|
}
|
|
|
|
|
2017-05-11 23:15:01 +08:00
|
|
|
pub fn get_status(&self) -> ControllerStatus {
|
|
|
|
ControllerStatus {
|
|
|
|
ready: self.emission_ready() & self.bias_ready(),
|
|
|
|
fbi: self.last_fbi,
|
|
|
|
fv: self.last_fv,
|
|
|
|
fbv: self.last_fbv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ControllerStatus {
|
2017-05-11 14:55:00 +08:00
|
|
|
pub fn debug_print(&self) {
|
2017-05-11 23:15:01 +08:00
|
|
|
println!("cathode ready: {}", self.ready);
|
|
|
|
if self.fbi.is_some() {
|
|
|
|
println!("emission: {}mA", 1000.0*self.fbi.unwrap());
|
2017-05-11 14:55:00 +08:00
|
|
|
}
|
2017-05-11 23:15:01 +08:00
|
|
|
if self.fv.is_some() {
|
|
|
|
println!("fil voltage: {}V", self.fv.unwrap());
|
2017-05-11 14:55:00 +08:00
|
|
|
}
|
2017-05-11 23:15:01 +08:00
|
|
|
if self.fbv.is_some() {
|
|
|
|
println!("bias voltage: {}V", self.fbv.unwrap());
|
2017-05-11 14:55:00 +08:00
|
|
|
}
|
|
|
|
}
|
2017-05-09 15:57:54 +08:00
|
|
|
}
|