let pid control pwm

This commit is contained in:
Astro 2019-09-17 19:09:47 +02:00
parent 393c276bda
commit 42a9b89db1
3 changed files with 67 additions and 26 deletions

View File

@ -18,17 +18,18 @@ The scope of this setting is per TCP session.
### Commands ### Commands
| Syntax | Function | | Syntax | Function |
| --- | --- | | --- | --- |
| `report` | Show current input | | `report` | Show current input |
| `report mode` | Show current report mode | | `report mode` | Show current report mode |
| `report mode <off or on>` | Set report mode | | `report mode <off or on>` | Set report mode |
| `pwm <width> <total>` | Set PWM duty cycle to width / total | | `pwm <width> <total>` | Set PWM duty cycle to manual *width / total* |
| `pid target <value>` | | | `pwm pid` | Set PWM to be controlled by PID |
| `pid kp <value>` | | | `pid target <value>` | |
| `pid ki <value>` | | | `pid kp <value>` | |
| `pid kd <value>` | | | `pid ki <value>` | |
| `pid output_min <value>` | | | `pid kd <value>` | |
| `pid output_max <value>` | | | `pid output_min <value>` | |
| `pid integral_min <value>` | | | `pid output_max <value>` | |
| `pid integral_max <value>` | | | `pid integral_min <value>` | |
| `pid integral_max <value>` | |

View File

@ -64,6 +64,7 @@ impl fmt::Display for Error {
pub enum ShowCommand { pub enum ShowCommand {
Input, Input,
Reporting, Reporting,
Pwm,
Pid, Pid,
} }
@ -79,15 +80,21 @@ pub enum PidParameter {
IntegralMax, IntegralMax,
} }
#[derive(Debug, Clone)]
pub enum PwmMode {
Manual {
width: u32,
total: u32,
},
Pid,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Command { pub enum Command {
Quit, Quit,
Show(ShowCommand), Show(ShowCommand),
Reporting(bool), Reporting(bool),
Pwm { Pwm(PwmMode),
width: u32,
total: u32,
},
Pid { Pid {
parameter: PidParameter, parameter: PidParameter,
value: f32, value: f32,
@ -147,9 +154,7 @@ fn report(input: &[u8]) -> IResult<&[u8], Command> {
} }
/// `pwm <width> <total>` - Set pwm duty cycle /// `pwm <width> <total>` - Set pwm duty cycle
fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> { fn pwm_manual(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
let (input, _) = tag("pwm")(input)?;
let (input, _) = whitespace(input)?;
let (input, width) = unsigned(input)?; let (input, width) = unsigned(input)?;
let width = match width { let width = match width {
Ok(width) => width, Ok(width) => width,
@ -161,7 +166,25 @@ fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
Ok(total) => total, Ok(total) => total,
Err(e) => return Ok((input, Err(e.into()))), Err(e) => return Ok((input, Err(e.into()))),
}; };
Ok((input, Ok(Command::Pwm { width, total }))) Ok((input, Ok(Command::Pwm(PwmMode::Manual { width, total }))))
}
/// `pwm pid` - Set PWM to be controlled by PID
fn pwm_pid(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
value(Ok(Command::Pwm(PwmMode::Pid)), tag("pid"))(input)
}
fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
let (input, _) = tag("pwm")(input)?;
alt((
preceded(
whitespace,
alt((
pwm_pid,
pwm_manual,
))),
|input| Ok((input, Ok(Command::Show(ShowCommand::Pwm))))
))(input)
} }
fn pid_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> { fn pid_parameter(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {

View File

@ -37,7 +37,7 @@ mod board;
use self::board::{gpio::Gpio, systick::get_time}; use self::board::{gpio::Gpio, systick::get_time};
mod ethmac; mod ethmac;
mod command_parser; mod command_parser;
use command_parser::{Command, ShowCommand}; use command_parser::{Command, ShowCommand, PwmMode};
mod session; mod session;
use self::session::{Session, SessionOutput}; use self::session::{Session, SessionOutput};
mod ad7172; mod ad7172;
@ -155,6 +155,8 @@ fn main() -> ! {
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap(); adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
let mut pid = pid::Controller::new(DEFAULT_PID_PARAMETERS.clone()); let mut pid = pid::Controller::new(DEFAULT_PID_PARAMETERS.clone());
// Start with disengaged PID to let user setup parameters first
let mut pid_enabled = false;
let mut hardware_addr = EthernetAddress(board::get_mac_address()); let mut hardware_addr = EthernetAddress(board::get_mac_address());
if hardware_addr.is_multicast() { if hardware_addr.is_multicast() {
@ -214,8 +216,13 @@ fn main() -> ! {
}).map(|channel| { }).map(|channel| {
let now = get_time(); let now = get_time();
let data = adc.read_data().unwrap(); let data = adc.read_data().unwrap();
report[usize::from(channel)] = Some((now, data));
if channel == 0 && pid_enabled {
let width = pid.update(data as f32) as u32;
board::set_timer_pwm(width as u32, 0xffff);
}
report[usize::from(channel)] = Some((now, data));
for (session, _) in sessions_handles.iter_mut() { for (session, _) in sessions_handles.iter_mut() {
session.set_report_pending(channel.into()); session.set_report_pending(channel.into());
} }
@ -270,9 +277,19 @@ fn main() -> ! {
out!(integral_min); out!(integral_min);
out!(integral_max); out!(integral_max);
} }
Command::Pwm { width, total } => { Command::Show(ShowCommand::Pwm) => {
let _ = writeln!(socket, "PWM: PID {}",
if pid_enabled { "engaged" } else { "disengaged" }
);
}
Command::Pwm(PwmMode::Manual { width, total }) => {
pid_enabled = false;
board::set_timer_pwm(width, total); board::set_timer_pwm(width, total);
let _ = writeln!(socket, "PWM duty cycle: {}/{}", width, total); let _ = writeln!(socket, "PWM duty cycle manually set to {}/{}", width, total);
}
Command::Pwm(PwmMode::Pid) => {
pid_enabled = true;
let _ = writeln!(socket, "PID enabled to control PWM");
} }
Command::Pid { parameter, value } => { Command::Pid { parameter, value } => {
use command_parser::PidParameter::*; use command_parser::PidParameter::*;