Module conreg::control::pid [−][src]
Expand description
PID and PID-T1 Controller
The PID controller implementation is capable to run als PID controller or as PID-T1 controller (with a t1 delay)
Requirements
- The PID controller should run on MCU (32 bit, w/o FPU)
- The PID controller should also run as simulator on any arbitrary host including plotting of response diagrams
Design Decision
- Control loop is implemented as iterator
- Ease of simulator integration
- Ease of integration into ISR
- Iterator end (None returned) allows switch of of actuator and stop simulation
- Use of
no_std
environment to meet limited MCU capabilities - Fixed type on Iterator as i32 and fixed point arithmetics fast and appropriate for any 32-bit MCU; optimized for ISR’s with minimal operations can go up to 50 kHz ISR triggering rate
- Fixed and little sampling interval allows to pre-compute processing
constants and speeds up sample processing
- Allows to implementing difference quotients instead of more computing intensive z-transformation
Simulation example
In an std environment simulate the step response as and plot it
use std::iter; use conreg::control::pid::PidController; use conreg::control::pid_parameter::{PidParameterAdditive}; let mut actual = iter::repeat(0.0_f32); // This is what we measure // This composes a step response input as target, i.e. what we want let mut target_pre = iter::repeat(0.0_f32).take(10); // 10 samples before step let mut target_post = iter::repeat(1.0_f32); // samples after the step let mut target = target_pre.chain(target_post); let p = PidParameterAdditive::new(1.0).set_integral(1.0); let mut pid = PidController::<f32>::new(0.000_01).set(p); println!("PidController: {:?}", pid); let output = actual.zip(target) // provide input tupel (actual, target) .map(|x| pid.control(x)) // run the controller .take(1000) // Stop processing after 1000 samples // .plot() // Plot the step response .collect::<Vec<f32>>(); println!("Result {:?}", output);
MCU example
On an embedded micro controller integrate the controller in a everlasting loop.
The example shows a PID-T1 controller as 32-bit fixed point implementation. It runs as at a sample rate of 20 kHz and the delay is 1 millisecond.
ⓘ
use std::iter; use conreg::control::pid::PidController; use conreg::control::pid_parameter::{PidParameterAdditive}; // Sensor that measures actual value - implements an iterator let process = Sensor::new(); // does not compile let setpoint = iter::repeat(500); // Setpoint desired value is injected as iterator let input = process.zip(setpoint); let p = PidParameterAdditive::new(1.0).set_integral(0.2).set_differential(0.4); let mut pid = PidController::<i32>::new_with_t1(0.000_01, 0.000_1).set(p); // Output device - consumes iterator let mut actuator = Actuator::new(); // does not compile let mut output = input.map(|x| pid.control(x)); // configure the controller processing for value in output { // run ad infinitum actuator.set(value); }
Structs
PidController |