Impl fns on printer
This commit is contained in:
parent
8f8d2ffaa2
commit
eaab62ab88
|
@ -1,5 +1,4 @@
|
||||||
use crate::gamepad::Gamepad;
|
use crate::gamepad::Gamepad;
|
||||||
use crate::printer::gcode::{G0Command, G91Command};
|
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
use euclid::{vec3, Vector3D};
|
use euclid::{vec3, Vector3D};
|
||||||
use futures::never::Never;
|
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
|
/// Jog the gantry by pumping loads of gcode into the printer board
|
||||||
pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
|
pub async fn jog(gamepad: Arc<Gamepad>, mut printer: Printer) -> Never {
|
||||||
printer.send_gcode(G91Command).await.unwrap();
|
printer.use_relative_movements().await.unwrap();
|
||||||
println!("Sent G91Command");
|
println!("Using relative movements");
|
||||||
loop {
|
loop {
|
||||||
let (setpoint_x, setpoint_y, setpoint_z) = gamepad.speed_setpoint();
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
let velocity = distance.length() / (TIME_PER_MOVEMENT.as_secs_f64() / 60.0);
|
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
|
printer
|
||||||
.send_gcode(command)
|
.move_relative(distance.x, distance.y, distance.z, velocity.into())
|
||||||
.await
|
.await
|
||||||
.expect("Failed to send movement command!");
|
.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();
|
let fill_level = printer.maximum_capacity() - printer.remaining_capacity();
|
||||||
println!("remaining capacity: {}", printer.remaining_capacity());
|
println!("remaining capacity: {}", printer.remaining_capacity());
|
||||||
println!("fill level: {}", fill_level);
|
println!("fill level: {}", fill_level);
|
||||||
if fill_level > TARGET_BUFER_FILL_LEVEL {
|
match fill_level.cmp(&TARGET_BUFER_FILL_LEVEL) {
|
||||||
sleep(LONG_COMMAND_DELAY).await;
|
std::cmp::Ordering::Equal => {
|
||||||
} else if fill_level == TARGET_BUFER_FILL_LEVEL {
|
sleep(LONG_COMMAND_DELAY / SHORT_COMMAND_DELAY_DIVIDER).await
|
||||||
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 i2c_linux::I2c;
|
||||||
use red::gamepad;
|
use red::gamepad;
|
||||||
use red::jogger;
|
use red::jogger;
|
||||||
use red::printer::gcode::*;
|
|
||||||
use red::printer::Printer;
|
use red::printer::Printer;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -33,6 +32,7 @@ const I2C_REGISTER_SPINDLE_SPEED: u8 = 0;
|
||||||
// SMBUS_WORD_DATA
|
// SMBUS_WORD_DATA
|
||||||
// SMBUS_I2C_BLOCK
|
// SMBUS_I2C_BLOCK
|
||||||
// SMBUS_EMUL
|
// SMBUS_EMUL
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Never {
|
async fn main() -> Never {
|
||||||
println!("Entering App");
|
println!("Entering App");
|
||||||
|
@ -73,34 +73,12 @@ async fn write_to_spindle() -> Never {
|
||||||
|
|
||||||
async fn write_to_printer() -> Never {
|
async fn write_to_printer() -> Never {
|
||||||
let mut printer = Printer::connect(DEFAULT_TTY).await.unwrap();
|
let mut printer = Printer::connect(DEFAULT_TTY).await.unwrap();
|
||||||
printer.send_gcode(M114Command::new()).await.unwrap();
|
printer.auto_home(true, true, true).await.unwrap();
|
||||||
printer
|
|
||||||
.send_gcode(G28Command::new(true, true, true))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
printer
|
printer.move_relative(50.0, 50.0, 5.0, None).await.unwrap();
|
||||||
.send_gcode(G0Command {
|
|
||||||
x: Some(50.0),
|
|
||||||
y: Some(50.0),
|
|
||||||
z: Some(5.0),
|
|
||||||
e: None,
|
|
||||||
velocity: None,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
printer
|
printer.move_relative(25.0, 25.0, 5.0, None).await.unwrap();
|
||||||
.send_gcode(G0Command {
|
|
||||||
x: Some(25.0),
|
|
||||||
y: Some(25.0),
|
|
||||||
z: Some(5.0),
|
|
||||||
e: None,
|
|
||||||
velocity: None,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use futures::sink::SinkExt;
|
||||||
use futures::stream::{SplitSink, SplitStream, StreamExt};
|
use futures::stream::{SplitSink, SplitStream, StreamExt};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{fmt::Write, io, rc::Rc, str};
|
use std::{fmt::Write, io, str};
|
||||||
use tokio;
|
use tokio;
|
||||||
use tokio::time::timeout;
|
use tokio::time::timeout;
|
||||||
use tokio_serial::{SerialPortBuilderExt, SerialStream};
|
use tokio_serial::{SerialPortBuilderExt, SerialStream};
|
||||||
|
@ -16,7 +16,7 @@ pub use gcode::{GcodeCommand, GcodeReply};
|
||||||
|
|
||||||
use crate::printer::gcode::{G91Command, M114Command};
|
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.
|
/// Recv buffer string will be initialized with this capacity.
|
||||||
/// This should fit a simple "OK Pnn Bn" reply for GCODE commands that
|
/// This should fit a simple "OK Pnn Bn" reply for GCODE commands that
|
||||||
|
@ -40,12 +40,18 @@ pub struct PrinterPosition {
|
||||||
z: f64,
|
z: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum MovementMode {
|
||||||
|
AbsoluteMovements,
|
||||||
|
RelativeMovements,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
position: (f64, f64, f64, f64),
|
position: PrinterPosition,
|
||||||
|
movement_mode: MovementMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Printer {
|
pub struct Printer {
|
||||||
pub state: Rc<State>,
|
pub state: State,
|
||||||
serial_tx: SplitSink<Framed<SerialStream, LineCodec>, String>,
|
serial_tx: SplitSink<Framed<SerialStream, LineCodec>, String>,
|
||||||
serial_rx: SplitStream<Framed<SerialStream, LineCodec>>,
|
serial_rx: SplitStream<Framed<SerialStream, LineCodec>>,
|
||||||
last_buffer_capacity: usize,
|
last_buffer_capacity: usize,
|
||||||
|
@ -54,10 +60,7 @@ pub struct Printer {
|
||||||
|
|
||||||
impl Printer {
|
impl Printer {
|
||||||
/// Send gcode to the printer and parse its reply
|
/// Send gcode to the printer and parse its reply
|
||||||
pub async fn send_gcode<T: GcodeCommand>(
|
async fn send_gcode<T: GcodeCommand>(&mut self, command: T) -> Result<T::Reply, PrinterError> {
|
||||||
&mut self,
|
|
||||||
command: T,
|
|
||||||
) -> Result<T::Reply, PrinterError> {
|
|
||||||
let command_text = format!("{}\n", command.command());
|
let command_text = format!("{}\n", command.command());
|
||||||
self.serial_tx.send(command_text.clone()).await.unwrap();
|
self.serial_tx.send(command_text.clone()).await.unwrap();
|
||||||
let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY);
|
let mut reply = String::with_capacity(RECV_BUFFER_CAPACITY);
|
||||||
|
@ -94,7 +97,7 @@ impl Printer {
|
||||||
.expect("Unable to set serial port exclusive to false");
|
.expect("Unable to set serial port exclusive to false");
|
||||||
|
|
||||||
let connection = LineCodec.framed(port);
|
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
|
// 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:
|
// to be received as it will otherwise stop responding for some reason:
|
||||||
|
@ -126,9 +129,14 @@ impl Printer {
|
||||||
let mut res = Printer {
|
let mut res = Printer {
|
||||||
serial_rx,
|
serial_rx,
|
||||||
serial_tx,
|
serial_tx,
|
||||||
state: Rc::new(State {
|
state: State {
|
||||||
position: (0.0, 0.0, 0.0, 0.0),
|
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()`
|
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()`
|
maximum_buffer_capacity: 0, // this is updated on the next call to `send_gcode()`
|
||||||
};
|
};
|
||||||
|
@ -171,6 +179,109 @@ impl Printer {
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| make_err())
|
.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;
|
struct LineCodec;
|
||||||
|
|
Loading…
Reference in a new issue