Impl fns on printer
This commit is contained in:
parent
8f8d2ffaa2
commit
eaab62ab88
|
@ -1,5 +1,4 @@
|
|||
use crate::gamepad::Gamepad;
|
||||
use crate::printer::gcode::{G0Command, G91Command};
|
||||
use crate::printer::Printer;
|
||||
use euclid::{vec3, Vector3D};
|
||||
use futures::never::Never;
|
||||
|
@ -34,8 +33,8 @@ pub type PrinterVec = Vector3D<f64, PrinterUnits>;
|
|||
|
||||
/// Jog the gantry by pumping loads of gcode into the printer board
|
||||
pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
|
||||
printer.send_gcode(G91Command).await.unwrap();
|
||||
println!("Sent G91Command");
|
||||
printer.use_relative_movements().await.unwrap();
|
||||
println!("Using relative movements");
|
||||
loop {
|
||||
let (setpoint_x, setpoint_y, setpoint_z) = gamepad.speed_setpoint();
|
||||
|
||||
|
@ -49,15 +48,8 @@ pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
|
|||
continue;
|
||||
}
|
||||
let velocity = distance.length() / (TIME_PER_MOVEMENT.as_secs_f64() / 60.0);
|
||||
let command = G0Command {
|
||||
x: distance.x.into(),
|
||||
y: distance.y.into(),
|
||||
z: distance.z.into(),
|
||||
e: None,
|
||||
velocity: velocity.into(),
|
||||
};
|
||||
printer
|
||||
.send_gcode(command)
|
||||
.move_relative(distance.x, distance.y, distance.z, velocity.into())
|
||||
.await
|
||||
.expect("Failed to send movement command!");
|
||||
|
||||
|
@ -66,10 +58,12 @@ pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
|
|||
let fill_level = printer.maximum_capacity() - printer.remaining_capacity();
|
||||
println!("remaining capacity: {}", printer.remaining_capacity());
|
||||
println!("fill level: {}", fill_level);
|
||||
if fill_level > TARGET_BUFER_FILL_LEVEL {
|
||||
sleep(LONG_COMMAND_DELAY).await;
|
||||
} else if fill_level == TARGET_BUFER_FILL_LEVEL {
|
||||
sleep(LONG_COMMAND_DELAY / SHORT_COMMAND_DELAY_DIVIDER).await;
|
||||
match fill_level.cmp(&TARGET_BUFER_FILL_LEVEL) {
|
||||
std::cmp::Ordering::Equal => {
|
||||
sleep(LONG_COMMAND_DELAY / SHORT_COMMAND_DELAY_DIVIDER).await
|
||||
}
|
||||
std::cmp::Ordering::Greater => sleep(LONG_COMMAND_DELAY).await,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use futures::never::Never;
|
|||
use i2c_linux::I2c;
|
||||
use red::gamepad;
|
||||
use red::jogger;
|
||||
use red::printer::gcode::*;
|
||||
use red::printer::Printer;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
@ -33,6 +32,7 @@ const I2C_REGISTER_SPINDLE_SPEED: u8 = 0;
|
|||
// SMBUS_WORD_DATA
|
||||
// SMBUS_I2C_BLOCK
|
||||
// SMBUS_EMUL
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Never {
|
||||
println!("Entering App");
|
||||
|
@ -73,34 +73,12 @@ async fn write_to_spindle() -> Never {
|
|||
|
||||
async fn write_to_printer() -> Never {
|
||||
let mut printer = Printer::connect(DEFAULT_TTY).await.unwrap();
|
||||
printer.send_gcode(M114Command::new()).await.unwrap();
|
||||
printer
|
||||
.send_gcode(G28Command::new(true, true, true))
|
||||
.await
|
||||
.unwrap();
|
||||
printer.auto_home(true, true, true).await.unwrap();
|
||||
loop {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
printer
|
||||
.send_gcode(G0Command {
|
||||
x: Some(50.0),
|
||||
y: Some(50.0),
|
||||
z: Some(5.0),
|
||||
e: None,
|
||||
velocity: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
printer.move_relative(50.0, 50.0, 5.0, None).await.unwrap();
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
printer
|
||||
.send_gcode(G0Command {
|
||||
x: Some(25.0),
|
||||
y: Some(25.0),
|
||||
z: Some(5.0),
|
||||
e: None,
|
||||
velocity: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
printer.move_relative(25.0, 25.0, 5.0, None).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use futures::sink::SinkExt;
|
|||
use futures::stream::{SplitSink, SplitStream, StreamExt};
|
||||
use regex::Regex;
|
||||
use std::time::Duration;
|
||||
use std::{fmt::Write, io, rc::Rc, str};
|
||||
use std::{fmt::Write, io, str};
|
||||
use tokio;
|
||||
use tokio::time::timeout;
|
||||
use tokio_serial::{SerialPortBuilderExt, SerialStream};
|
||||
|
@ -16,7 +16,7 @@ pub use gcode::{GcodeCommand, GcodeReply};
|
|||
|
||||
use crate::printer::gcode::{G91Command, M114Command};
|
||||
|
||||
use self::gcode::GcodeReplyError;
|
||||
use self::gcode::{G0Command, G28Command, G90Command, GcodeReplyError};
|
||||
|
||||
/// Recv buffer string will be initialized with this capacity.
|
||||
/// This should fit a simple "OK Pnn Bn" reply for GCODE commands that
|
||||
|
@ -40,12 +40,18 @@ pub struct PrinterPosition {
|
|||
z: f64,
|
||||
}
|
||||
|
||||
pub enum MovementMode {
|
||||
AbsoluteMovements,
|
||||
RelativeMovements,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
position: (f64, f64, f64, f64),
|
||||
position: PrinterPosition,
|
||||
movement_mode: MovementMode,
|
||||
}
|
||||
|
||||
pub struct Printer {
|
||||
pub state: Rc<State>,
|
||||
pub state: State,
|
||||
serial_tx: SplitSink<Framed<SerialStream, LineCodec>, String>,
|
||||
serial_rx: SplitStream<Framed<SerialStream, LineCodec>>,
|
||||
last_buffer_capacity: usize,
|
||||
|
@ -54,10 +60,7 @@ pub struct Printer {
|
|||
|
||||
impl Printer {
|
||||
/// Send gcode to the printer and parse its reply
|
||||
pub async fn send_gcode<T: GcodeCommand>(
|
||||
&mut self,
|
||||
command: T,
|
||||
) -> Result<T::Reply, PrinterError> {
|
||||
async fn send_gcode<T: GcodeCommand>(&mut self, command: T) -> Result<T::Reply, PrinterError> {
|
||||
let command_text = format!("{}\n", command.command());
|
||||
self.serial_tx.send(command_text.clone()).await.unwrap();
|
||||
let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY);
|
||||
|
@ -94,7 +97,7 @@ impl Printer {
|
|||
.expect("Unable to set serial port exclusive to false");
|
||||
|
||||
let connection = LineCodec.framed(port);
|
||||
let (mut serial_tx, mut serial_rx) = connection.split();
|
||||
let (serial_tx, mut serial_rx) = connection.split();
|
||||
|
||||
// The printer will send some info after connecting for the first time. We need to wait for this
|
||||
// to be received as it will otherwise stop responding for some reason:
|
||||
|
@ -126,9 +129,14 @@ impl Printer {
|
|||
let mut res = Printer {
|
||||
serial_rx,
|
||||
serial_tx,
|
||||
state: Rc::new(State {
|
||||
position: (0.0, 0.0, 0.0, 0.0),
|
||||
}),
|
||||
state: State {
|
||||
position: PrinterPosition {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
}, // TODO: Fill this value through sending a command below
|
||||
movement_mode: MovementMode::AbsoluteMovements, // TODO: Fill this value through sending a command below
|
||||
},
|
||||
last_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
|
||||
maximum_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
|
||||
};
|
||||
|
@ -171,6 +179,109 @@ impl Printer {
|
|||
.parse()
|
||||
.map_err(|_| make_err())
|
||||
}
|
||||
|
||||
pub async fn use_absolute_movements(&mut self) -> Result<(), PrinterError> {
|
||||
self.state.movement_mode = MovementMode::AbsoluteMovements;
|
||||
self.send_gcode(G90Command).await
|
||||
}
|
||||
|
||||
pub async fn use_relative_movements(&mut self) -> Result<(), PrinterError> {
|
||||
self.state.movement_mode = MovementMode::RelativeMovements;
|
||||
self.send_gcode(G91Command).await
|
||||
}
|
||||
|
||||
/// Home the printer using the hardware endstops
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `x, y, z` - Whether the axis should be homed. Axis that are set to `false` will not be
|
||||
/// homed.
|
||||
pub async fn auto_home(&mut self, x: bool, y: bool, z: bool) -> Result<(), PrinterError> {
|
||||
let res = self.send_gcode(G28Command::new(x, y, z)).await?;
|
||||
self.state.position = PrinterPosition {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Move the printer by a specific distance
|
||||
///
|
||||
/// If the printer is set to absolute movement mode, this function will switch it to relative
|
||||
/// movement mode, perform the move, and then reset to absolute movement mode.
|
||||
/// As this will introduce considerable overhead, consider calling
|
||||
/// `self.use_relative_movements()` before doing multiple relative movements.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `x, y, z` - Position offset in printer units (mm)
|
||||
/// * `velocity` - Velocity that the printer should move at (mm/min)
|
||||
pub async fn move_relative(
|
||||
&mut self,
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
velocity: Option<f64>,
|
||||
) -> Result<(), PrinterError> {
|
||||
let command = G0Command {
|
||||
x: Some(x),
|
||||
y: Some(y),
|
||||
z: Some(z),
|
||||
e: None, // Machine has no e
|
||||
velocity,
|
||||
};
|
||||
let reply = if let MovementMode::AbsoluteMovements = self.state.movement_mode {
|
||||
self.use_relative_movements().await?;
|
||||
let res = self.send_gcode(command).await;
|
||||
self.use_absolute_movements().await?;
|
||||
res
|
||||
} else {
|
||||
self.send_gcode(command).await
|
||||
}?;
|
||||
|
||||
self.state.position.x += x;
|
||||
self.state.position.y += y;
|
||||
self.state.position.z += z;
|
||||
|
||||
Ok(reply)
|
||||
}
|
||||
/// Move the printer to a specific position
|
||||
///
|
||||
/// If the printer is set to relative movement mode, this function will switch it to absolute
|
||||
/// movement mode, perform the move, and then reset to relative movement mode.
|
||||
/// As this will introduce considerable overhead, consider calling
|
||||
/// `self.use_absolute_movements()` before doing multiple absolute movements.
|
||||
///
|
||||
/// * `x, y, z` - New position in printer units (mm)
|
||||
/// * `velocity` - Velocity that the printer should move at (mm/min)
|
||||
pub async fn move_absolute(
|
||||
&mut self,
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
velocity: f64,
|
||||
) -> Result<(), PrinterError> {
|
||||
let command = G0Command {
|
||||
x: Some(x),
|
||||
y: Some(y),
|
||||
z: Some(z),
|
||||
e: None, // Machine has no e
|
||||
velocity: Some(velocity),
|
||||
};
|
||||
let reply = if let MovementMode::RelativeMovements = self.state.movement_mode {
|
||||
self.use_absolute_movements().await?;
|
||||
let res = self.send_gcode(command).await;
|
||||
self.use_relative_movements().await?;
|
||||
res
|
||||
} else {
|
||||
self.send_gcode(command).await
|
||||
}?;
|
||||
|
||||
self.state.position.x = x;
|
||||
self.state.position.y = y;
|
||||
self.state.position.z = z;
|
||||
|
||||
Ok(reply)
|
||||
}
|
||||
}
|
||||
|
||||
struct LineCodec;
|
||||
|
|
Loading…
Reference in a new issue