Add parameter selection

This commit is contained in:
2023-01-29 14:57:57 +01:00
parent ce2919580d
commit 63534c7e05
4 changed files with 151 additions and 16 deletions

View File

@ -143,6 +143,10 @@ fn draw_setting(
font: &Font,
) {
let text_scale = Scale::uniform(screen.yres() as f32 / 4.0 - 8.0);
let value_scale = Scale {
x: screen.xres() as f32 / 10.0,
y: screen.yres() as f32 / 4.0 - 8.0,
};
let x = screen.xres() as i32 / 8 + screen.xres() as i32 * i32::from(index) / 4;
draw_centered_text(
screen,
@ -156,9 +160,9 @@ fn draw_setting(
screen,
x,
screen.yres() as i32 * 5 / 8 + 4,
text_scale,
value_scale,
font,
format!("{value}").as_str(),
format!("{value:.2}").as_str(),
);
let top_triangle = [
Point::new(x, screen.yres() as i32 / 2),

View File

@ -2,17 +2,17 @@ mod buttons;
mod display;
use buttons::SmartEv3Buttons;
use display::{draw_calibration, draw_cycles, draw_driving, draw_finished, font};
use display::{draw_calibration, draw_driving, draw_finished, draw_settings, font, Parameter};
use ev3dev_lang_rust::{
motors::{LargeMotor, MotorPort},
sensors::{ColorSensor, SensorPort},
Ev3Error, Ev3Result, Screen,
};
use pid::Pid;
use rand::{thread_rng, Rng};
use rusttype::Font;
use std::{
error::Error,
hint,
thread::sleep,
time::{Duration, Instant},
};
@ -37,6 +37,8 @@ fn main() -> Result<(), Box<dyn Error>> {
let white = calibrate_gray(&mut screen, &sensor, &mut buttons, "Weiß", &font)?;
let setpoint = (black + white) / 2.0;
let (k_p, k_i, k_d, v) = select_values(&mut screen, &mut buttons, &font);
draw_driving(&mut screen, &font);
let result = follow_line(
@ -44,13 +46,13 @@ fn main() -> Result<(), Box<dyn Error>> {
&sensor,
&mut buttons,
setpoint,
(0.3, 0.0, 0.0),
20,
(k_p / 10.0, k_i, k_d),
v,
);
left_motor.stop().and(right_motor.stop())?;
let time = match result {
Ok(time) => time,
Err(LineFollowError::UserAbort) => return Ok(()),
Err(ProgramError::UserAbort) => return Ok(()),
e => e?,
};
@ -63,6 +65,103 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
fn select_values(
screen: &mut Screen,
buttons: &mut SmartEv3Buttons,
font: &Font,
) -> (f32, f32, f32, i32) {
use Parameter::{Kd, Ki, Kp, Speed};
let mut k_p = thread_rng().gen_range(0.01..=10.0);
let mut k_i = thread_rng().gen_range(0.01..=10.0);
let mut k_d = thread_rng().gen_range(0.01..=10.0);
let mut v = thread_rng().gen_range(1..=100);
let mut selected = Kp;
draw_settings(screen, k_p, k_i, k_d, v, selected, font);
loop {
buttons.process();
if buttons.is_enter_pressed() {
break;
}
if buttons.is_right_pressed() {
selected = match selected {
Kp => Ki,
Ki => Kd,
Kd => Speed,
Speed => Kp,
};
}
if buttons.is_left_pressed() {
selected = match selected {
Kp => Speed,
Ki => Kp,
Kd => Ki,
Speed => Kd,
};
}
match selected {
Speed => {
if buttons.is_up() {
v = (v + 1).min(100);
}
if buttons.is_down() {
v = (v - 1).max(0);
}
}
p => {
let param = match p {
Kp => &mut k_p,
Ki => &mut k_i,
Kd => &mut k_d,
Speed => unreachable!(),
};
if buttons.is_up() {
*param = (*param
+ if buttons.is_up_pressed() {
0.01f32
} else {
0.1f32
})
.min(99.99);
}
if buttons.is_down() {
*param = (*param
- if buttons.is_down_pressed() {
0.01f32
} else {
0.1f32
})
.max(0.0);
}
}
}
if buttons.is_left_pressed()
|| buttons.is_right_pressed()
|| buttons.is_up()
|| buttons.is_down()
{
draw_settings(screen, k_p, k_i, k_d, v, selected, font);
}
if buttons.is_up_pressed() || buttons.is_down_pressed() {
sleep(Duration::from_millis(200));
} else {
sleep(Duration::from_millis(10));
}
}
(k_p, k_i, k_d, v)
}
fn increase(parameter: &mut f32) {
let change = 0.01;
*parameter = (*parameter + change).min(99.99);
}
fn decrease(parameter: &mut f32) {
let change = 0.01;
*parameter = (*parameter - change).max(0.0);
}
fn calibrate_gray(
screen: &mut Screen,
sensor: &ColorSensor,
@ -81,7 +180,7 @@ fn calibrate_gray(
}
#[derive(Error, Debug)]
enum LineFollowError {
enum ProgramError {
#[error("working with EV3 peripheral")]
Ev3(#[from] Ev3Error),
#[error("the user abortet the run")]
@ -102,7 +201,7 @@ fn follow_line(
setpoint: f32,
(k_p, k_i, k_d): (f32, f32, f32),
v: i32,
) -> Result<Duration, LineFollowError> {
) -> Result<Duration, ProgramError> {
let mut controller = Pid::new(setpoint, f32::INFINITY);
controller
.p(k_p, f32::INFINITY)
@ -140,7 +239,7 @@ fn follow_line(
if let LineFollowState::Finish(time) = state {
Ok(time)
} else {
Err(LineFollowError::UserAbort)
Err(ProgramError::UserAbort)
}
}