corexz: Add CoreXZ kinematics (#3129)
Add a CoreXZ kinematics Signed-off-by: Maks Zolin <mzolin@vorondesign.com>
This commit is contained in:
parent
f3b980c1b2
commit
9213646c63
|
@ -0,0 +1,81 @@
|
||||||
|
# This file serves as documentation for config parameters of corexz
|
||||||
|
# style printers. One may copy and edit this file to configure a new
|
||||||
|
# corexz printer. Only parameters unique to corexz printers are
|
||||||
|
# described here - see the "example.cfg" file for description of common
|
||||||
|
# config parameters.
|
||||||
|
|
||||||
|
# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT
|
||||||
|
# FIRST. Incorrectly configured parameters may cause damage.
|
||||||
|
|
||||||
|
# The stepper_x section is used to describe the X axis as well as the
|
||||||
|
# stepper controlling the X+Z movement.
|
||||||
|
[stepper_x]
|
||||||
|
step_pin: ar54
|
||||||
|
dir_pin: ar55
|
||||||
|
enable_pin: !ar38
|
||||||
|
step_distance: .01
|
||||||
|
endstop_pin: ^ar3
|
||||||
|
position_endstop: 0
|
||||||
|
position_max: 200
|
||||||
|
homing_speed: 50
|
||||||
|
|
||||||
|
[stepper_y]
|
||||||
|
step_pin: ar60
|
||||||
|
dir_pin: ar61
|
||||||
|
enable_pin: !ar56
|
||||||
|
step_distance: .01
|
||||||
|
endstop_pin: ^ar14
|
||||||
|
position_endstop: 0
|
||||||
|
position_max: 200
|
||||||
|
homing_speed: 50
|
||||||
|
|
||||||
|
# The stepper_z section is used to describe the Z axis as well as the
|
||||||
|
# stepper controlling the X-Z movement.
|
||||||
|
[stepper_z]
|
||||||
|
step_pin: ar46
|
||||||
|
dir_pin: ar48
|
||||||
|
enable_pin: !ar62
|
||||||
|
step_distance: .0025
|
||||||
|
endstop_pin: ^ar18
|
||||||
|
position_endstop: 0.5
|
||||||
|
position_max: 200
|
||||||
|
|
||||||
|
[extruder]
|
||||||
|
step_pin: ar26
|
||||||
|
dir_pin: ar28
|
||||||
|
enable_pin: !ar24
|
||||||
|
step_distance: .0022
|
||||||
|
nozzle_diameter: 0.400
|
||||||
|
filament_diameter: 1.750
|
||||||
|
heater_pin: ar10
|
||||||
|
sensor_type: ATC Semitec 104GT-2
|
||||||
|
sensor_pin: analog13
|
||||||
|
control: pid
|
||||||
|
pid_Kp: 22.2
|
||||||
|
pid_Ki: 1.08
|
||||||
|
pid_Kd: 114
|
||||||
|
min_temp: 0
|
||||||
|
max_temp: 250
|
||||||
|
|
||||||
|
[heater_bed]
|
||||||
|
heater_pin: ar8
|
||||||
|
sensor_type: EPCOS 100K B57560G104F
|
||||||
|
sensor_pin: analog14
|
||||||
|
control: watermark
|
||||||
|
min_temp: 0
|
||||||
|
max_temp: 130
|
||||||
|
|
||||||
|
[fan]
|
||||||
|
pin: ar9
|
||||||
|
|
||||||
|
[mcu]
|
||||||
|
serial: /dev/ttyACM0
|
||||||
|
pin_map: arduino
|
||||||
|
|
||||||
|
[printer]
|
||||||
|
kinematics: corexz
|
||||||
|
# This option must be "corexz" for corexz printers.
|
||||||
|
max_velocity: 300
|
||||||
|
max_accel: 3000
|
||||||
|
max_z_velocity: 50
|
||||||
|
max_z_accel: 30
|
|
@ -16,8 +16,9 @@ COMPILE_CMD = ("gcc -Wall -g -O2 -shared -fPIC"
|
||||||
" -o %s %s")
|
" -o %s %s")
|
||||||
SOURCE_FILES = [
|
SOURCE_FILES = [
|
||||||
'pyhelper.c', 'serialqueue.c', 'stepcompress.c', 'itersolve.c', 'trapq.c',
|
'pyhelper.c', 'serialqueue.c', 'stepcompress.c', 'itersolve.c', 'trapq.c',
|
||||||
'kin_cartesian.c', 'kin_corexy.c', 'kin_delta.c', 'kin_polar.c',
|
'kin_cartesian.c', 'kin_corexy.c', 'kin_corexz.c', 'kin_delta.c',
|
||||||
'kin_rotary_delta.c', 'kin_winch.c', 'kin_extruder.c', 'kin_shaper.c',
|
'kin_polar.c', 'kin_rotary_delta.c', 'kin_winch.c', 'kin_extruder.c',
|
||||||
|
'kin_shaper.c',
|
||||||
]
|
]
|
||||||
DEST_LIB = "c_helper.so"
|
DEST_LIB = "c_helper.so"
|
||||||
OTHER_FILES = [
|
OTHER_FILES = [
|
||||||
|
@ -78,6 +79,10 @@ defs_kin_corexy = """
|
||||||
struct stepper_kinematics *corexy_stepper_alloc(char type);
|
struct stepper_kinematics *corexy_stepper_alloc(char type);
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
defs_kin_corexz = """
|
||||||
|
struct stepper_kinematics *corexz_stepper_alloc(char type);
|
||||||
|
"""
|
||||||
|
|
||||||
defs_kin_delta = """
|
defs_kin_delta = """
|
||||||
struct stepper_kinematics *delta_stepper_alloc(double arm2
|
struct stepper_kinematics *delta_stepper_alloc(double arm2
|
||||||
, double tower_x, double tower_y);
|
, double tower_x, double tower_y);
|
||||||
|
@ -165,11 +170,10 @@ defs_std = """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defs_all = [
|
defs_all = [
|
||||||
defs_pyhelper, defs_serialqueue, defs_std,
|
defs_pyhelper, defs_serialqueue, defs_std, defs_stepcompress,
|
||||||
defs_stepcompress, defs_itersolve, defs_trapq,
|
defs_itersolve, defs_trapq, defs_kin_cartesian, defs_kin_corexy,
|
||||||
defs_kin_cartesian, defs_kin_corexy, defs_kin_delta, defs_kin_polar,
|
defs_kin_corexz, defs_kin_delta, defs_kin_polar, defs_kin_rotary_delta,
|
||||||
defs_kin_rotary_delta, defs_kin_winch, defs_kin_extruder,
|
defs_kin_winch, defs_kin_extruder, defs_kin_shaper,
|
||||||
defs_kin_shaper,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Return the list of file modification times
|
# Return the list of file modification times
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// CoreXZ kinematics stepper pulse time generation
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Maks Zolin <mzolin@vorondesign.com>
|
||||||
|
//
|
||||||
|
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc
|
||||||
|
#include <string.h> // memset
|
||||||
|
#include "compiler.h" // __visible
|
||||||
|
#include "itersolve.h" // struct stepper_kinematics
|
||||||
|
#include "trapq.h" // move_get_coord
|
||||||
|
|
||||||
|
static double
|
||||||
|
corexz_stepper_plus_calc_position(struct stepper_kinematics *sk, struct move *m
|
||||||
|
, double move_time)
|
||||||
|
{
|
||||||
|
struct coord c = move_get_coord(m, move_time);
|
||||||
|
return c.x + c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
corexz_stepper_minus_calc_position(struct stepper_kinematics *sk, struct move *m
|
||||||
|
, double move_time)
|
||||||
|
{
|
||||||
|
struct coord c = move_get_coord(m, move_time);
|
||||||
|
return c.x - c.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stepper_kinematics * __visible
|
||||||
|
corexz_stepper_alloc(char type)
|
||||||
|
{
|
||||||
|
struct stepper_kinematics *sk = malloc(sizeof(*sk));
|
||||||
|
memset(sk, 0, sizeof(*sk));
|
||||||
|
if (type == '+')
|
||||||
|
sk->calc_position_cb = corexz_stepper_plus_calc_position;
|
||||||
|
else if (type == '-')
|
||||||
|
sk->calc_position_cb = corexz_stepper_minus_calc_position;
|
||||||
|
sk->active_flags = AF_X | AF_Z;
|
||||||
|
return sk;
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Code for handling the kinematics of corexz robots
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 Maks Zolin <mzolin@vorondesign.com>
|
||||||
|
#
|
||||||
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
import logging, math
|
||||||
|
import stepper, homing
|
||||||
|
|
||||||
|
class CoreXZKinematics:
|
||||||
|
def __init__(self, toolhead, config):
|
||||||
|
# Setup axis rails
|
||||||
|
self.rails = [ stepper.PrinterRail(config.getsection('stepper_x')),
|
||||||
|
stepper.PrinterRail(config.getsection('stepper_y')),
|
||||||
|
stepper.PrinterRail(config.getsection('stepper_z')) ]
|
||||||
|
self.rails[0].get_endstops()[0][0].add_stepper(
|
||||||
|
self.rails[2].get_steppers()[0])
|
||||||
|
self.rails[2].get_endstops()[0][0].add_stepper(
|
||||||
|
self.rails[0].get_steppers()[0])
|
||||||
|
self.rails[0].setup_itersolve('corexz_stepper_alloc', '+')
|
||||||
|
self.rails[1].setup_itersolve('cartesian_stepper_alloc', 'y')
|
||||||
|
self.rails[2].setup_itersolve('corexz_stepper_alloc', '-')
|
||||||
|
for s in self.get_steppers():
|
||||||
|
s.set_trapq(toolhead.get_trapq())
|
||||||
|
toolhead.register_step_generator(s.generate_steps)
|
||||||
|
config.get_printer().register_event_handler("stepper_enable:motor_off",
|
||||||
|
self._motor_off)
|
||||||
|
# Setup boundary checks
|
||||||
|
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||||
|
self.max_z_velocity = config.getfloat(
|
||||||
|
'max_z_velocity', max_velocity, above=0., maxval=max_velocity)
|
||||||
|
self.max_z_accel = config.getfloat(
|
||||||
|
'max_z_accel', max_accel, above=0., maxval=max_accel)
|
||||||
|
self.limits = [(1.0, -1.0)] * 3
|
||||||
|
# Setup stepper max halt velocity
|
||||||
|
max_halt_velocity = toolhead.get_max_axis_halt()
|
||||||
|
max_xy_halt_velocity = max_halt_velocity * math.sqrt(2.)
|
||||||
|
max_xy_accel = max_accel * math.sqrt(2.)
|
||||||
|
self.rails[0].set_max_jerk(max_xy_halt_velocity, max_xy_accel)
|
||||||
|
self.rails[1].set_max_jerk(max_xy_halt_velocity, max_xy_accel)
|
||||||
|
self.rails[2].set_max_jerk(max_xy_halt_velocity, max_xy_accel)
|
||||||
|
def get_steppers(self):
|
||||||
|
return [s for rail in self.rails for s in rail.get_steppers()]
|
||||||
|
def calc_tag_position(self):
|
||||||
|
pos = [rail.get_tag_position() for rail in self.rails]
|
||||||
|
return [0.5 * (pos[0] + pos[2]), pos[1], 0.5 * (pos[0] - pos[2])]
|
||||||
|
def set_position(self, newpos, homing_axes):
|
||||||
|
for i, rail in enumerate(self.rails):
|
||||||
|
rail.set_position(newpos)
|
||||||
|
if i in homing_axes:
|
||||||
|
self.limits[i] = rail.get_range()
|
||||||
|
def note_z_not_homed(self):
|
||||||
|
# Helper for Safe Z Home
|
||||||
|
self.limits[2] = (1.0, -1.0)
|
||||||
|
def home(self, homing_state):
|
||||||
|
# Each axis is homed independently and in order
|
||||||
|
for axis in homing_state.get_axes():
|
||||||
|
rail = self.rails[axis]
|
||||||
|
# Determine movement
|
||||||
|
position_min, position_max = rail.get_range()
|
||||||
|
hi = rail.get_homing_info()
|
||||||
|
homepos = [None, None, None, None]
|
||||||
|
homepos[axis] = hi.position_endstop
|
||||||
|
forcepos = list(homepos)
|
||||||
|
if hi.positive_dir:
|
||||||
|
forcepos[axis] -= 1.5 * (hi.position_endstop - position_min)
|
||||||
|
else:
|
||||||
|
forcepos[axis] += 1.5 * (position_max - hi.position_endstop)
|
||||||
|
# Perform homing
|
||||||
|
homing_state.home_rails([rail], forcepos, homepos)
|
||||||
|
def _motor_off(self, print_time):
|
||||||
|
self.limits = [(1.0, -1.0)] * 3
|
||||||
|
def _check_endstops(self, move):
|
||||||
|
end_pos = move.end_pos
|
||||||
|
for i in (0, 1, 2):
|
||||||
|
if (move.axes_d[i]
|
||||||
|
and (end_pos[i] < self.limits[i][0]
|
||||||
|
or end_pos[i] > self.limits[i][1])):
|
||||||
|
if self.limits[i][0] > self.limits[i][1]:
|
||||||
|
raise homing.EndstopMoveError(
|
||||||
|
end_pos, "Must home axis first")
|
||||||
|
raise homing.EndstopMoveError(end_pos)
|
||||||
|
def check_move(self, move):
|
||||||
|
limits = self.limits
|
||||||
|
xpos, ypos = move.end_pos[:2]
|
||||||
|
if (xpos < limits[0][0] or xpos > limits[0][1]
|
||||||
|
or ypos < limits[1][0] or ypos > limits[1][1]):
|
||||||
|
self._check_endstops(move)
|
||||||
|
if not move.axes_d[2]:
|
||||||
|
# Normal XY move - use defaults
|
||||||
|
return
|
||||||
|
# Move with Z - update velocity and accel for slower Z axis
|
||||||
|
self._check_endstops(move)
|
||||||
|
z_ratio = move.move_d / abs(move.axes_d[2])
|
||||||
|
move.limit_speed(
|
||||||
|
self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio)
|
||||||
|
def get_status(self, eventtime):
|
||||||
|
axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h]
|
||||||
|
return {'homed_axes': "".join(axes)}
|
||||||
|
|
||||||
|
def load_kinematics(toolhead, config):
|
||||||
|
return CoreXZKinematics(toolhead, config)
|
|
@ -5,6 +5,7 @@ GCODE move.gcode
|
||||||
DICTIONARY atmega2560.dict
|
DICTIONARY atmega2560.dict
|
||||||
CONFIG ../../config/example.cfg
|
CONFIG ../../config/example.cfg
|
||||||
CONFIG ../../config/example-corexy.cfg
|
CONFIG ../../config/example-corexy.cfg
|
||||||
|
CONFIG ../../config/example-corexz.cfg
|
||||||
CONFIG ../../config/example-delta.cfg
|
CONFIG ../../config/example-delta.cfg
|
||||||
CONFIG ../../config/example-rotary-delta.cfg
|
CONFIG ../../config/example-rotary-delta.cfg
|
||||||
CONFIG ../../config/example-winch.cfg
|
CONFIG ../../config/example-winch.cfg
|
||||||
|
|
Loading…
Reference in New Issue