forked from fafo/microscope-control
Implement simple GCode stage.
Easy experimenting with 3D printer or other CNC if open flexure is not available. Signed-off-by: Henner Zeller <h.zeller@acm.org>
This commit is contained in:
parent
4f620ad899
commit
ad9b1cb8c2
4 changed files with 72 additions and 9 deletions
45
hostcontrol/src/gcode_stage.rs
Normal file
45
hostcontrol/src/gcode_stage.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
use crate::stage_io::StageIO;
|
||||||
|
use crate::xy_stage::{Result, XYStage};
|
||||||
|
|
||||||
|
pub struct GCodeStage {
|
||||||
|
stage_io: StageIO,
|
||||||
|
max_range_μm: nalgebra::Vector3<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GCodeStage {
|
||||||
|
pub fn new(stage_io: StageIO) -> Result<Self> {
|
||||||
|
let mut res = Self {
|
||||||
|
stage_io,
|
||||||
|
// TODO: determine max range with some M-code ?
|
||||||
|
max_range_μm: nalgebra::vector![100.0 * 1000.0, 100.0 * 1000.0, 50.0 * 1000.0],
|
||||||
|
};
|
||||||
|
res.stage_io.send_request("G28\n")?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XYStage for GCodeStage {
|
||||||
|
/// Move to absolute coordinates (x,y,z) in micrometers.
|
||||||
|
fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3<f64>) -> Result<()> {
|
||||||
|
// TODO: check range
|
||||||
|
self.stage_io.send_request(format!(
|
||||||
|
"G1 X{} Y{} Z{}\n",
|
||||||
|
a[0] / 1000.0,
|
||||||
|
a[1] / 1000.0,
|
||||||
|
a[2] / 1000.0
|
||||||
|
))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get range of valid cartesian coordinates box. For now, assuming one
|
||||||
|
/// corner is fixed at (0,0,0), the other remote corner is this range.
|
||||||
|
fn get_range(&self) -> nalgebra::Vector3<f64> {
|
||||||
|
self.max_range_μm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for GCodeStage {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.stage_io.send_request("M84\n").unwrap(); // switch off motors.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use clap::Parser;
|
use clap::{Parser, ValueEnum};
|
||||||
use std::{thread::sleep, time::Duration};
|
use std::{thread::sleep, time::Duration};
|
||||||
|
|
||||||
|
mod gcode_stage;
|
||||||
mod openflexure_stage;
|
mod openflexure_stage;
|
||||||
|
|
||||||
mod stage_io;
|
mod stage_io;
|
||||||
|
|
@ -19,19 +20,37 @@ struct CliArgs {
|
||||||
/// Speed of the stage device (bps)
|
/// Speed of the stage device (bps)
|
||||||
#[arg(long, default_value = "115200")]
|
#[arg(long, default_value = "115200")]
|
||||||
tty_speed: u32,
|
tty_speed: u32,
|
||||||
|
|
||||||
|
#[arg(long, value_enum)]
|
||||||
|
backend: Backend,
|
||||||
|
}
|
||||||
|
|
||||||
|
// [derive(DebugCopy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||||
|
#[derive(Debug, Clone, ValueEnum)]
|
||||||
|
enum Backend {
|
||||||
|
/// OpenFlexure stage
|
||||||
|
OpenFlexure,
|
||||||
|
|
||||||
|
/// GCode stage
|
||||||
|
GCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = CliArgs::parse();
|
let args = CliArgs::parse();
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let stage_io = StageIO::new(&args.stage_device, args.tty_speed).unwrap();
|
let stage_io = StageIO::new(&args.stage_device, args.tty_speed).unwrap();
|
||||||
let mut s = openflexure_stage::OpenFlexureStage::new(stage_io, 1.12).unwrap();
|
let mut stage: Box<dyn XYStage> = match args.backend {
|
||||||
|
Backend::GCode => Box::new(gcode_stage::GCodeStage::new(stage_io).unwrap()),
|
||||||
|
Backend::OpenFlexure => {
|
||||||
|
Box::new(openflexure_stage::OpenFlexureStage::new(stage_io, 1.12).unwrap())
|
||||||
|
}
|
||||||
|
};
|
||||||
let origin = nalgebra::vector![0.0, 0.0, 0.0];
|
let origin = nalgebra::vector![0.0, 0.0, 0.0];
|
||||||
s.move_absolute_cartesian(origin).unwrap();
|
stage.move_absolute_cartesian(origin).unwrap();
|
||||||
sleep(Duration::from_secs(1));
|
sleep(Duration::from_secs(1));
|
||||||
let mut max_xy = s.get_range();
|
let mut max_xy = stage.get_range();
|
||||||
max_xy[2] = 0.0;
|
max_xy[2] = 0.0;
|
||||||
s.move_absolute_cartesian(max_xy).unwrap();
|
stage.move_absolute_cartesian(max_xy).unwrap();
|
||||||
sleep(Duration::from_secs(5));
|
sleep(Duration::from_secs(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Stage controller for openflexure-delta like stage controllers.
|
//! Stage controller for openflexure-delta like stage controllers.
|
||||||
|
|
||||||
use crate::stage_io::StageIO;
|
use crate::stage_io::StageIO;
|
||||||
use crate::xy_stage::{XYStage, StageError,Result};
|
use crate::xy_stage::{Result, StageError, XYStage};
|
||||||
|
|
||||||
fn new_camera_rotation(theta: f64) -> nalgebra::Matrix3<f64> {
|
fn new_camera_rotation(theta: f64) -> nalgebra::Matrix3<f64> {
|
||||||
nalgebra::matrix![
|
nalgebra::matrix![
|
||||||
|
|
@ -93,7 +93,7 @@ impl OpenFlexureStage {
|
||||||
|
|
||||||
impl XYStage for OpenFlexureStage {
|
impl XYStage for OpenFlexureStage {
|
||||||
fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3<f64>) -> Result<()> {
|
fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3<f64>) -> Result<()> {
|
||||||
// TODO: check range with get_movement_box()
|
// TODO: check range with get_movement_box()
|
||||||
let current = self.get_position_delta();
|
let current = self.get_position_delta();
|
||||||
let target = self.cartesian_to_delta * a;
|
let target = self.cartesian_to_delta * a;
|
||||||
let target = nalgebra::vector![target[0] as i32, target[1] as i32, target[2] as i32];
|
let target = nalgebra::vector![target[0] as i32, target[1] as i32, target[2] as i32];
|
||||||
|
|
@ -114,6 +114,6 @@ impl XYStage for OpenFlexureStage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_range(&self) -> nalgebra::Vector3<f64> {
|
fn get_range(&self) -> nalgebra::Vector3<f64> {
|
||||||
nalgebra::vector![10000.0, 10000.0, 5000.0]
|
nalgebra::vector![10000.0, 10000.0, 5000.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
use crate::stage_io::StageIOError;
|
use crate::stage_io::StageIOError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue