Store distances in the TARGET structure always in micrometers.
This is a intrusive patch and for now, it's done for the X axis only. To make comparison with the former approach easier ... The advantages of this change: - Converting from mm to steps in gcode_parse.c and back in dda.c wastes cycles and accuracy. - In dda.c, UM_PER_STEP simply goes away, so distance calculations work now with STEPS_PER_MM > 500 just fine. 1/16 microstepping on threaded rods (Z axis) becomes possible. - Distance calculations (feedrate, acceleration, ...) become much simpler. - A wide range of STEPS_PER_M can now be handled at reasonable (4 decimal digit) accuracy with a simple macro. Formerly, we were limited to 500 steps/mm, now we can do 4'096 steps/mm and could easily raise this another digit. Disadvantages: - STEPS_PER_MM is gone in config.h, using STEPS_PER_M is required, because the preprocessor refuses to compare numbers with decimal points in them. - The DDA has to store the position in steps anyways to avoid rounding errors.
This commit is contained in:
parent
22a5b428c6
commit
c96ea0c773
|
|
@ -48,12 +48,22 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
/// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
/// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
/// half-stepping doubles the number, quarter stepping requires * 4, etc.
|
calculate these values appropriate for your machine
|
||||||
/// valid range = 0.020 to 4194.303
|
|
||||||
#define STEPS_PER_MM_X 320.000
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
|
#define STEPS_PER_M_X 320000
|
||||||
#define STEPS_PER_MM_Y 320.000
|
#define STEPS_PER_MM_Y 320.000
|
||||||
#define STEPS_PER_MM_Z 320.000
|
#define STEPS_PER_MM_Z 320.000
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,16 +45,22 @@
|
||||||
*/
|
*/
|
||||||
#define HOST
|
#define HOST
|
||||||
|
|
||||||
/*
|
/** \def STEPS_PER_M
|
||||||
Values reflecting the gearing of your machine.
|
steps per meter ( = steps per mm * 1000 )
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
|
||||||
|
|
||||||
calculate these values appropriate for your machine
|
calculate these values appropriate for your machine
|
||||||
for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
|
||||||
for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
*/
|
*/
|
||||||
#define STEPS_PER_MM_X 320.000
|
#define STEPS_PER_M_X 320000
|
||||||
#define STEPS_PER_MM_Y 320.000
|
#define STEPS_PER_MM_Y 320.000
|
||||||
#define STEPS_PER_MM_Z 200.000
|
#define STEPS_PER_MM_Z 200.000
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,22 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
// The GEN6 board uses 1/8 microstepping, so multiply your values by 8.
|
calculate these values appropriate for your machine
|
||||||
#define STEPS_PER_MM_X (320.000*8)
|
|
||||||
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
|
#define STEPS_PER_M_X (5000*8)
|
||||||
#define STEPS_PER_MM_Y (320.000*8)
|
#define STEPS_PER_MM_Y (320.000*8)
|
||||||
#define STEPS_PER_MM_Z (200.000*8)
|
#define STEPS_PER_MM_Z (200.000*8)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,22 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
/// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
/// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
/// half-stepping doubles the number, quarter stepping requires * 4, etc.
|
calculate these values appropriate for your machine
|
||||||
/// valid range = 0.020 to 4194.303
|
|
||||||
#define STEPS_PER_MM_X 40.000
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
|
#define STEPS_PER_M_X 40000
|
||||||
#define STEPS_PER_MM_Y 40.000
|
#define STEPS_PER_MM_Y 40.000
|
||||||
#define STEPS_PER_MM_Z 320.000
|
#define STEPS_PER_MM_Z 320.000
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,27 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
// half-stepping doubles the number, quarter stepping requires * 4, etc.
|
calculate these values appropriate for your machine
|
||||||
|
|
||||||
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
#define MICROSTEPPING_X 16.0
|
#define MICROSTEPPING_X 16.0
|
||||||
#define MICROSTEPPING_Y 16.0
|
#define MICROSTEPPING_Y 16.0
|
||||||
#define MICROSTEPPING_Z 16.0
|
#define MICROSTEPPING_Z 16.0
|
||||||
#define MICROSTEPPING_E 4.0
|
#define MICROSTEPPING_E 4.0
|
||||||
|
|
||||||
#define STEPS_PER_MM_X (5.023*MICROSTEPPING_X)
|
#define STEPS_PER_M_X (5023*MICROSTEPPING_X)
|
||||||
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
||||||
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,27 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
// half-stepping doubles the number, quarter stepping requires * 4, etc.
|
calculate these values appropriate for your machine
|
||||||
|
|
||||||
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
#define MICROSTEPPING_X 16.0
|
#define MICROSTEPPING_X 16.0
|
||||||
#define MICROSTEPPING_Y 16.0
|
#define MICROSTEPPING_Y 16.0
|
||||||
#define MICROSTEPPING_Z 16.0
|
#define MICROSTEPPING_Z 16.0
|
||||||
#define MICROSTEPPING_E 4.0
|
#define MICROSTEPPING_E 4.0
|
||||||
|
|
||||||
#define STEPS_PER_MM_X (5.023*MICROSTEPPING_X)
|
#define STEPS_PER_M_X (5023*MICROSTEPPING_X)
|
||||||
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
||||||
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,27 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
/// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
/// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
|
calculate these values appropriate for your machine
|
||||||
|
|
||||||
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
#define MICROSTEPPING_X 16.0
|
#define MICROSTEPPING_X 16.0
|
||||||
#define MICROSTEPPING_Y 16.0
|
#define MICROSTEPPING_Y 16.0
|
||||||
#define MICROSTEPPING_Z 16.0
|
#define MICROSTEPPING_Z 16.0
|
||||||
#define MICROSTEPPING_E 4.0
|
#define MICROSTEPPING_E 4.0
|
||||||
|
|
||||||
#define STEPS_PER_MM_X (5.023*MICROSTEPPING_X)
|
#define STEPS_PER_M_X (5023*MICROSTEPPING_X)
|
||||||
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
||||||
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,27 @@
|
||||||
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// calculate these values appropriate for your machine
|
/** \def STEPS_PER_M
|
||||||
/// for threaded rods, this is (steps motor per turn) / (pitch of the thread)
|
steps per meter ( = steps per mm * 1000 )
|
||||||
/// for belts, this is (steps per motor turn) / (number of gear teeth) / (belt module)
|
|
||||||
|
calculate these values appropriate for your machine
|
||||||
|
|
||||||
|
for threaded rods, this is
|
||||||
|
(steps motor per turn) / (pitch of the thread) * 1000
|
||||||
|
|
||||||
|
for belts, this is
|
||||||
|
(steps per motor turn) / (number of gear teeth) / (belt module) * 1000
|
||||||
|
|
||||||
|
half-stepping doubles the number, quarter stepping requires * 4, etc.
|
||||||
|
|
||||||
|
valid range = 20 to 4'0960'000 (0.02 to 40960 steps/mm)
|
||||||
|
*/
|
||||||
#define MICROSTEPPING_X 16.0
|
#define MICROSTEPPING_X 16.0
|
||||||
#define MICROSTEPPING_Y 16.0
|
#define MICROSTEPPING_Y 16.0
|
||||||
#define MICROSTEPPING_Z 16.0
|
#define MICROSTEPPING_Z 16.0
|
||||||
#define MICROSTEPPING_E 4.0
|
#define MICROSTEPPING_E 4.0
|
||||||
|
|
||||||
#define STEPS_PER_MM_X (5.023*MICROSTEPPING_X)
|
#define STEPS_PER_M_X (5023*MICROSTEPPING_X)
|
||||||
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
#define STEPS_PER_MM_Y (5.023*MICROSTEPPING_Y)
|
||||||
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
#define STEPS_PER_MM_Z (416.699*MICROSTEPPING_Z)
|
||||||
|
|
||||||
|
|
|
||||||
62
dda.c
62
dda.c
|
|
@ -24,6 +24,10 @@
|
||||||
#include "heater.h"
|
#include "heater.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef STEPS_PER_MM_X
|
||||||
|
#error STEPS_PER_MM_X is gone, review your config.h and use STEPS_PER_M_X
|
||||||
|
#endif
|
||||||
|
|
||||||
/// step timeout
|
/// step timeout
|
||||||
volatile uint8_t steptimeout = 0;
|
volatile uint8_t steptimeout = 0;
|
||||||
|
|
||||||
|
|
@ -35,6 +39,10 @@ volatile uint8_t steptimeout = 0;
|
||||||
/// \brief target position of last move in queue
|
/// \brief target position of last move in queue
|
||||||
TARGET startpoint __attribute__ ((__section__ (".bss")));
|
TARGET startpoint __attribute__ ((__section__ (".bss")));
|
||||||
|
|
||||||
|
/// \var startpoint_steps
|
||||||
|
/// \brief target position of last move in queue, expressed in steps
|
||||||
|
TARGET startpoint_steps __attribute__ ((__section__ (".bss")));
|
||||||
|
|
||||||
/// \var current_position
|
/// \var current_position
|
||||||
/// \brief actual position of extruder head
|
/// \brief actual position of extruder head
|
||||||
/// \todo make current_position = real_position (from endstops) + offset from G28 and friends
|
/// \todo make current_position = real_position (from endstops) + offset from G28 and friends
|
||||||
|
|
@ -174,10 +182,18 @@ void dda_init(void) {
|
||||||
|
|
||||||
#ifdef ACCELERATION_RAMPING
|
#ifdef ACCELERATION_RAMPING
|
||||||
move_state.n = 1;
|
move_state.n = 1;
|
||||||
move_state.c = ((uint32_t)((double)F_CPU / sqrt((double)(STEPS_PER_MM_X * ACCELERATION)))) << 8;
|
move_state.c = ((uint32_t)((double)F_CPU / sqrt((double)(STEPS_PER_M_X * ACCELERATION / 1000.)))) << 8;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Distribute a new startpoint to DDA's internal structures without any movement.
|
||||||
|
|
||||||
|
This is needed for example after homing or a G92. The new location must be in startpoint already.
|
||||||
|
*/
|
||||||
|
void dda_new_startpoint(void) {
|
||||||
|
um_to_steps_x(startpoint_steps.X, startpoint.X);
|
||||||
|
}
|
||||||
|
|
||||||
/*! CREATE a dda given current_position and a target, save to passed location so we can write directly into the queue
|
/*! CREATE a dda given current_position and a target, save to passed location so we can write directly into the queue
|
||||||
\param *dda pointer to a dda_queue entry to overwrite
|
\param *dda pointer to a dda_queue entry to overwrite
|
||||||
\param *target the target position of this move
|
\param *target the target position of this move
|
||||||
|
|
@ -191,6 +207,7 @@ void dda_init(void) {
|
||||||
This algorithm is probably the main limiting factor to print speed in terms of firmware limitations
|
This algorithm is probably the main limiting factor to print speed in terms of firmware limitations
|
||||||
*/
|
*/
|
||||||
void dda_create(DDA *dda, TARGET *target) {
|
void dda_create(DDA *dda, TARGET *target) {
|
||||||
|
uint32_t steps, x_delta_um /*, y_delta_um, z_delta_um, e_delta_um */;
|
||||||
uint32_t distance, c_limit, c_limit_calc;
|
uint32_t distance, c_limit, c_limit_calc;
|
||||||
|
|
||||||
// initialise DDA to a known state
|
// initialise DDA to a known state
|
||||||
|
|
@ -202,7 +219,12 @@ void dda_create(DDA *dda, TARGET *target) {
|
||||||
// we end at the passed target
|
// we end at the passed target
|
||||||
memcpy(&(dda->endpoint), target, sizeof(TARGET));
|
memcpy(&(dda->endpoint), target, sizeof(TARGET));
|
||||||
|
|
||||||
dda->x_delta = labs(target->X - startpoint.X);
|
x_delta_um = (uint32_t)labs(target->X - startpoint.X);
|
||||||
|
|
||||||
|
um_to_steps_x(steps, target->X);
|
||||||
|
dda->x_delta = labs(steps - startpoint_steps.X);
|
||||||
|
startpoint_steps.X = steps;
|
||||||
|
|
||||||
dda->y_delta = labs(target->Y - startpoint.Y);
|
dda->y_delta = labs(target->Y - startpoint.Y);
|
||||||
dda->z_delta = labs(target->Z - startpoint.Z);
|
dda->z_delta = labs(target->Z - startpoint.Z);
|
||||||
dda->e_delta = labs(target->E - startpoint.E);
|
dda->e_delta = labs(target->E - startpoint.E);
|
||||||
|
|
@ -241,11 +263,11 @@ void dda_create(DDA *dda, TARGET *target) {
|
||||||
|
|
||||||
// since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation.
|
// since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation.
|
||||||
if (dda->z_delta == 0)
|
if (dda->z_delta == 0)
|
||||||
distance = approx_distance(dda->x_delta * UM_PER_STEP_X, dda->y_delta * UM_PER_STEP_Y);
|
distance = approx_distance(x_delta_um, dda->y_delta * UM_PER_STEP_Y);
|
||||||
else if (dda->x_delta == 0 && dda->y_delta == 0)
|
else if (dda->x_delta == 0 && dda->y_delta == 0)
|
||||||
distance = dda->z_delta * UM_PER_STEP_Z;
|
distance = dda->z_delta * UM_PER_STEP_Z;
|
||||||
else
|
else
|
||||||
distance = approx_distance_3(dda->x_delta * UM_PER_STEP_X, dda->y_delta * UM_PER_STEP_Y, dda->z_delta * UM_PER_STEP_Z);
|
distance = approx_distance_3(x_delta_um, dda->y_delta * UM_PER_STEP_Y, dda->z_delta * UM_PER_STEP_Z);
|
||||||
|
|
||||||
if (distance < 2)
|
if (distance < 2)
|
||||||
distance = dda->e_delta * UM_PER_STEP_E;
|
distance = dda->e_delta * UM_PER_STEP_E;
|
||||||
|
|
@ -279,7 +301,7 @@ void dda_create(DDA *dda, TARGET *target) {
|
||||||
// do this for each axis individually, as the combined speed of two or more axes can be higher than the capabilities of a single one.
|
// do this for each axis individually, as the combined speed of two or more axes can be higher than the capabilities of a single one.
|
||||||
c_limit = 0;
|
c_limit = 0;
|
||||||
// check X axis
|
// check X axis
|
||||||
c_limit_calc = ( (dda->x_delta * (UM_PER_STEP_X * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8;
|
c_limit_calc = ((x_delta_um * 2400L) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8;
|
||||||
if (c_limit_calc > c_limit)
|
if (c_limit_calc > c_limit)
|
||||||
c_limit = c_limit_calc;
|
c_limit = c_limit_calc;
|
||||||
// check Y axis
|
// check Y axis
|
||||||
|
|
@ -357,8 +379,12 @@ void dda_create(DDA *dda, TARGET *target) {
|
||||||
dda->c_min = (move_duration / target->F) << 8;
|
dda->c_min = (move_duration / target->F) << 8;
|
||||||
if (dda->c_min < c_limit)
|
if (dda->c_min < c_limit)
|
||||||
dda->c_min = c_limit;
|
dda->c_min = c_limit;
|
||||||
|
// This section is plain wrong, like in it's only half of what we need. This factor 960000 is dependant on STEPS_PER_MM.
|
||||||
// overflows at target->F > 65535; factor 16. found by try-and-error; will overshoot target speed a bit
|
// overflows at target->F > 65535; factor 16. found by try-and-error; will overshoot target speed a bit
|
||||||
dda->rampup_steps = target->F * target->F / (uint32_t)(STEPS_PER_MM_X * ACCELERATION / 16.);
|
dda->rampup_steps = target->F * target->F / (uint32_t)(STEPS_PER_M_X * ACCELERATION / 960000.);
|
||||||
|
//sersendf_P(PSTR("rampup calc %lu\n"), dda->rampup_steps);
|
||||||
|
dda->rampup_steps = 100000; // replace mis-calculation by a safe value
|
||||||
|
// End of wrong section.
|
||||||
if (dda->rampup_steps > dda->total_steps / 2)
|
if (dda->rampup_steps > dda->total_steps / 2)
|
||||||
dda->rampup_steps = dda->total_steps / 2;
|
dda->rampup_steps = dda->total_steps / 2;
|
||||||
dda->rampdown_steps = dda->total_steps - dda->rampup_steps;
|
dda->rampdown_steps = dda->total_steps - dda->rampup_steps;
|
||||||
|
|
@ -627,11 +653,20 @@ void dda_step(DDA *dda) {
|
||||||
move_state.c = (int32_t)move_state.c - ((int32_t)(move_state.c * 2) / (int32_t)move_state.n);
|
move_state.c = (int32_t)move_state.c - ((int32_t)(move_state.c * 2) / (int32_t)move_state.n);
|
||||||
}
|
}
|
||||||
move_state.step_no++;
|
move_state.step_no++;
|
||||||
|
// Print the number of steps actually needed for ramping up
|
||||||
|
// Needed for comparing the number with the one calculated in dda_create()
|
||||||
|
//static char printed = 0;
|
||||||
|
//if (printed == 0 && dda->c_min >= move_state.c) {
|
||||||
|
// sersendf_P(PSTR("speedup %lu steps\n"), move_state.step_no);
|
||||||
|
// printed = 1;
|
||||||
|
//}
|
||||||
|
//if (move_state.step_no < 3) printed = 0;
|
||||||
|
|
||||||
// debug ramping algorithm
|
// debug ramping algorithm
|
||||||
// for very low speeds like 10 mm/min, only
|
// raise this 10 for higher speeds to avoid flooding the serial line
|
||||||
//if (move_state.step_no % 10 /* 10, 100, ...*/ == 0)
|
//if (move_state.step_no % 10 /* 10, 50, 100, ...*/ == 0)
|
||||||
// sersendf_P(PSTR("\r\nc %lu c_min %lu n %d"), dda->c, dda->c_min, move_state.n);
|
// sersendf_P(PSTR("\r\nc %lu c_min %lu n %ld"),
|
||||||
|
// move_state.c, dda->c_min, move_state.n);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: If we stop axes individually, could we home two or more axes at the same time?
|
// TODO: If we stop axes individually, could we home two or more axes at the same time?
|
||||||
|
|
@ -690,9 +725,14 @@ void update_current_position() {
|
||||||
}
|
}
|
||||||
else if (dda->live) {
|
else if (dda->live) {
|
||||||
if (dda->x_direction)
|
if (dda->x_direction)
|
||||||
current_position.X = dda->endpoint.X - move_state.x_steps;
|
// (STEPS_PER_M_X / 1000) is a bit inaccurate for low STEPS_PER_M numbers
|
||||||
|
current_position.X = dda->endpoint.X -
|
||||||
|
// should be: move_state.x_steps * 1000000 / STEPS_PER_M_X)
|
||||||
|
// but x_steps can be like 1000000 already, so we'd overflow
|
||||||
|
move_state.x_steps * 1000 / ((STEPS_PER_M_X + 500) / 1000);
|
||||||
else
|
else
|
||||||
current_position.X = dda->endpoint.X + move_state.x_steps;
|
current_position.X = dda->endpoint.X +
|
||||||
|
move_state.x_steps * 1000 / ((STEPS_PER_M_X + 500) / 1000);
|
||||||
|
|
||||||
if (dda->y_direction)
|
if (dda->y_direction)
|
||||||
current_position.Y = dda->endpoint.Y - move_state.y_steps;
|
current_position.Y = dda->endpoint.Y - move_state.y_steps;
|
||||||
|
|
|
||||||
40
dda.h
40
dda.h
|
|
@ -5,9 +5,30 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
micrometer to steps conversion
|
||||||
|
|
||||||
|
handle a few cases to avoid overflow while keeping reasonable accuracy
|
||||||
|
input is up to 20 bits, so we can multiply by 4096 at most
|
||||||
|
*/
|
||||||
|
#if STEPS_PER_M_X >= 4096000
|
||||||
|
#define um_to_steps_x(dest, src) \
|
||||||
|
do { dest = (src * (STEPS_PER_M_X / 10000L) + 50L) / 100L; } while (0)
|
||||||
|
#elif STEPS_PER_M_X >= 409600
|
||||||
|
#define um_to_steps_x(dest, src) \
|
||||||
|
do { dest = (src * (STEPS_PER_M_X / 1000L) + 500L) / 1000L; } while (0)
|
||||||
|
#elif STEPS_PER_M_X >= 40960
|
||||||
|
#define um_to_steps_x(dest, src) \
|
||||||
|
do { dest = (src * (STEPS_PER_M_X / 100L) + 5000L) / 10000L; } while (0)
|
||||||
|
#elif STEPS_PER_M_X >= 4096
|
||||||
|
#define um_to_steps_x(dest, src) \
|
||||||
|
do { dest = (src * (STEPS_PER_M_X / 10L) + 50000L) / 100000L; } while (0)
|
||||||
|
#else
|
||||||
|
#define um_to_steps_x(dest, src) \
|
||||||
|
do { dest = (src * (STEPS_PER_M_X / 1L) + 500000L) / 1000000L; } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Used in distance calculation during DDA setup
|
// Used in distance calculation during DDA setup
|
||||||
/// micrometers per step X
|
|
||||||
#define UM_PER_STEP_X 1000L / ((uint32_t) STEPS_PER_MM_X)
|
|
||||||
/// micrometers per step Y
|
/// micrometers per step Y
|
||||||
#define UM_PER_STEP_Y 1000L / ((uint32_t) STEPS_PER_MM_Y)
|
#define UM_PER_STEP_Y 1000L / ((uint32_t) STEPS_PER_MM_Y)
|
||||||
/// micrometers per step Z
|
/// micrometers per step Z
|
||||||
|
|
@ -25,7 +46,12 @@
|
||||||
types
|
types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// target is simply a point in space/time
|
/**
|
||||||
|
\struct TARGET
|
||||||
|
\brief target is simply a point in space/time
|
||||||
|
|
||||||
|
X, Y, Z and E are in micrometers unless explcitely stated. F is in mm/min.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t X;
|
int32_t X;
|
||||||
int32_t Y;
|
int32_t Y;
|
||||||
|
|
@ -59,7 +85,7 @@ typedef struct {
|
||||||
/// time until next step
|
/// time until next step
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
/// tracking variable
|
/// tracking variable
|
||||||
int16_t n;
|
int32_t n;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Endstop debouncing
|
/// Endstop debouncing
|
||||||
|
|
@ -139,6 +165,9 @@ extern volatile uint8_t steptimeout;
|
||||||
/// startpoint holds the endpoint of the most recently created DDA, so we know where the next one created starts. could also be called last_endpoint
|
/// startpoint holds the endpoint of the most recently created DDA, so we know where the next one created starts. could also be called last_endpoint
|
||||||
extern TARGET startpoint;
|
extern TARGET startpoint;
|
||||||
|
|
||||||
|
/// the same as above, counted in motor steps
|
||||||
|
extern TARGET startpoint_steps;
|
||||||
|
|
||||||
/// current_position holds the machine's current position. this is only updated when we step, or when G92 (set home) is received.
|
/// current_position holds the machine's current position. this is only updated when we step, or when G92 (set home) is received.
|
||||||
extern TARGET current_position;
|
extern TARGET current_position;
|
||||||
|
|
||||||
|
|
@ -155,6 +184,9 @@ const uint8_t msbloc (uint32_t v) __attribute__ ((const));
|
||||||
// initialize dda structures
|
// initialize dda structures
|
||||||
void dda_init(void);
|
void dda_init(void);
|
||||||
|
|
||||||
|
// distribute a new startpoint
|
||||||
|
void dda_new_startpoint(void);
|
||||||
|
|
||||||
// create a DDA
|
// create a DDA
|
||||||
void dda_create(DDA *dda, TARGET *target);
|
void dda_create(DDA *dda, TARGET *target);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) {
|
||||||
MEMORY_BARRIER();
|
MEMORY_BARRIER();
|
||||||
SREG = save_reg;
|
SREG = save_reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// go to the next move.
|
/// go to the next move.
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
which is about the worst case we have. All other machines have a bigger build volume.
|
which is about the worst case we have. All other machines have a bigger build volume.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STEPS_PER_M_X ((uint32_t) ((STEPS_PER_MM_X * 1000.0) + 0.5))
|
|
||||||
#define STEPS_PER_M_Y ((uint32_t) ((STEPS_PER_MM_Y * 1000.0) + 0.5))
|
#define STEPS_PER_M_Y ((uint32_t) ((STEPS_PER_MM_Y * 1000.0) + 0.5))
|
||||||
#define STEPS_PER_M_Z ((uint32_t) ((STEPS_PER_MM_Z * 1000.0) + 0.5))
|
#define STEPS_PER_M_Z ((uint32_t) ((STEPS_PER_MM_Z * 1000.0) + 0.5))
|
||||||
#define STEPS_PER_M_E ((uint32_t) ((STEPS_PER_MM_E * 1000.0) + 0.5))
|
#define STEPS_PER_M_E ((uint32_t) ((STEPS_PER_MM_E * 1000.0) + 0.5))
|
||||||
|
|
@ -38,7 +37,6 @@
|
||||||
mm -> inch conversion
|
mm -> inch conversion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STEPS_PER_IN_X ((uint32_t) ((25.4 * STEPS_PER_MM_X) + 0.5))
|
|
||||||
#define STEPS_PER_IN_Y ((uint32_t) ((25.4 * STEPS_PER_MM_Y) + 0.5))
|
#define STEPS_PER_IN_Y ((uint32_t) ((25.4 * STEPS_PER_MM_Y) + 0.5))
|
||||||
#define STEPS_PER_IN_Z ((uint32_t) ((25.4 * STEPS_PER_MM_Z) + 0.5))
|
#define STEPS_PER_IN_Z ((uint32_t) ((25.4 * STEPS_PER_MM_Z) + 0.5))
|
||||||
#define STEPS_PER_IN_E ((uint32_t) ((25.4 * STEPS_PER_MM_E) + 0.5))
|
#define STEPS_PER_IN_E ((uint32_t) ((25.4 * STEPS_PER_MM_E) + 0.5))
|
||||||
|
|
@ -81,6 +79,8 @@ GCODE_COMMAND next_target __attribute__ ((__section__ (".bss")));
|
||||||
*/
|
*/
|
||||||
extern const uint32_t powers[]; // defined in sermsg.c
|
extern const uint32_t powers[]; // defined in sermsg.c
|
||||||
|
|
||||||
|
// TODO: When the new approach to pass distances in micrometers instead of step
|
||||||
|
// numbers stays, this should be replaced by a simplified version.
|
||||||
/// convert a floating point input value into an integer with appropriate scaling.
|
/// convert a floating point input value into an integer with appropriate scaling.
|
||||||
/// \param *df pointer to floating point structure that holds fp value to convert
|
/// \param *df pointer to floating point structure that holds fp value to convert
|
||||||
/// \param multiplicand multiply by this amount during conversion to integer
|
/// \param multiplicand multiply by this amount during conversion to integer
|
||||||
|
|
@ -137,9 +137,9 @@ void gcode_parse_char(uint8_t c) {
|
||||||
break;
|
break;
|
||||||
case 'X':
|
case 'X':
|
||||||
if (next_target.option_inches)
|
if (next_target.option_inches)
|
||||||
next_target.target.X = decfloat_to_int(&read_digit, STEPS_PER_IN_X, 0);
|
next_target.target.X = decfloat_to_int(&read_digit, 25400, 1);
|
||||||
else
|
else
|
||||||
next_target.target.X = decfloat_to_int(&read_digit, STEPS_PER_M_X, 1);
|
next_target.target.X = decfloat_to_int(&read_digit, 1000, 0);
|
||||||
if (DEBUG_ECHO && (debug_flags & DEBUG_ECHO))
|
if (DEBUG_ECHO && (debug_flags & DEBUG_ECHO))
|
||||||
serwrite_int32(next_target.target.X);
|
serwrite_int32(next_target.target.X);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "gcode_parse.h"
|
#include "gcode_parse.h"
|
||||||
|
|
||||||
|
#include "dda.h"
|
||||||
#include "dda_queue.h"
|
#include "dda_queue.h"
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
@ -77,12 +78,12 @@ void process_gcode_command() {
|
||||||
|
|
||||||
// implement axis limits
|
// implement axis limits
|
||||||
#ifdef X_MIN
|
#ifdef X_MIN
|
||||||
if (next_target.target.X < (X_MIN * STEPS_PER_MM_X))
|
if (next_target.target.X < X_MIN * 1000.)
|
||||||
next_target.target.X = X_MIN * STEPS_PER_MM_X;
|
next_target.target.X = X_MIN * 1000.;
|
||||||
#endif
|
#endif
|
||||||
#ifdef X_MAX
|
#ifdef X_MAX
|
||||||
if (next_target.target.X > (X_MAX * STEPS_PER_MM_X))
|
if (next_target.target.X > X_MAX * 1000.))
|
||||||
next_target.target.X = X_MAX * STEPS_PER_MM_X;
|
next_target.target.X = X_MAX * 1000.;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Y_MIN
|
#ifdef Y_MIN
|
||||||
if (next_target.target.Y < (Y_MIN * STEPS_PER_MM_Y))
|
if (next_target.target.Y < (Y_MIN * STEPS_PER_MM_Y))
|
||||||
|
|
@ -301,6 +302,8 @@ void process_gcode_command() {
|
||||||
startpoint.Y = next_target.target.Y =
|
startpoint.Y = next_target.target.Y =
|
||||||
startpoint.Z = next_target.target.Z = 0;
|
startpoint.Z = next_target.target.Z = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dda_new_startpoint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 161:
|
case 161:
|
||||||
|
|
@ -575,7 +578,7 @@ void process_gcode_command() {
|
||||||
queue_wait();
|
queue_wait();
|
||||||
#endif
|
#endif
|
||||||
update_current_position();
|
update_current_position();
|
||||||
sersendf_P(PSTR("X:%lq,Y:%lq,Z:%lq,E:%lq,F:%ld"), current_position.X * ((int32_t) UM_PER_STEP_X), current_position.Y * ((int32_t) UM_PER_STEP_Y), current_position.Z * ((int32_t) UM_PER_STEP_Z), current_position.E * ((int32_t) UM_PER_STEP_E), current_position.F);
|
sersendf_P(PSTR("X:%lq,Y:%lq,Z:%lq,E:%lq,F:%ld"), current_position.X, current_position.Y * ((int32_t) UM_PER_STEP_Y), current_position.Z * ((int32_t) UM_PER_STEP_Z), current_position.E * ((int32_t) UM_PER_STEP_E), current_position.F);
|
||||||
// newline is sent from gcode_parse after we return
|
// newline is sent from gcode_parse after we return
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
18
home.c
18
home.c
|
|
@ -36,7 +36,7 @@ void home_x_negative() {
|
||||||
#if defined X_MIN_PIN
|
#if defined X_MIN_PIN
|
||||||
TARGET t = startpoint;
|
TARGET t = startpoint;
|
||||||
|
|
||||||
t.X = -1000*STEPS_PER_MM_X;
|
t.X = -1000000;
|
||||||
#ifdef SLOW_HOMING
|
#ifdef SLOW_HOMING
|
||||||
// hit home soft
|
// hit home soft
|
||||||
t.F = SEARCH_FEEDRATE_X;
|
t.F = SEARCH_FEEDRATE_X;
|
||||||
|
|
@ -48,7 +48,7 @@ void home_x_negative() {
|
||||||
|
|
||||||
#ifndef SLOW_HOMING
|
#ifndef SLOW_HOMING
|
||||||
// back off slowly
|
// back off slowly
|
||||||
t.X = +1000*STEPS_PER_MM_X;
|
t.X = +1000000;
|
||||||
t.F = SEARCH_FEEDRATE_X;
|
t.F = SEARCH_FEEDRATE_X;
|
||||||
enqueue_home(&t, 0x1, 0);
|
enqueue_home(&t, 0x1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -56,10 +56,11 @@ void home_x_negative() {
|
||||||
// set X home
|
// set X home
|
||||||
queue_wait(); // we have to wait here, see G92
|
queue_wait(); // we have to wait here, see G92
|
||||||
#ifdef X_MIN
|
#ifdef X_MIN
|
||||||
startpoint.X = next_target.target.X = (int32_t)(X_MIN * STEPS_PER_MM_X);
|
startpoint.X = next_target.target.X = (int32_t)(X_MIN * 1000.0);
|
||||||
#else
|
#else
|
||||||
startpoint.X = next_target.target.X = 0;
|
startpoint.X = next_target.target.X = 0;
|
||||||
#endif
|
#endif
|
||||||
|
dda_new_startpoint();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +72,7 @@ void home_x_positive() {
|
||||||
#if defined X_MAX_PIN && defined X_MAX
|
#if defined X_MAX_PIN && defined X_MAX
|
||||||
TARGET t = startpoint;
|
TARGET t = startpoint;
|
||||||
|
|
||||||
t.X = +1000*STEPS_PER_MM_X;
|
t.X = +1000000;
|
||||||
#ifdef SLOW_HOMING
|
#ifdef SLOW_HOMING
|
||||||
// hit home soft
|
// hit home soft
|
||||||
t.F = SEARCH_FEEDRATE_X;
|
t.F = SEARCH_FEEDRATE_X;
|
||||||
|
|
@ -83,7 +84,7 @@ void home_x_positive() {
|
||||||
|
|
||||||
#ifndef SLOW_HOMING
|
#ifndef SLOW_HOMING
|
||||||
// back off slowly
|
// back off slowly
|
||||||
t.X = -1000*STEPS_PER_MM_X;
|
t.X = -1000000;
|
||||||
t.F = SEARCH_FEEDRATE_X;
|
t.F = SEARCH_FEEDRATE_X;
|
||||||
enqueue_home(&t, 0x1, 0);
|
enqueue_home(&t, 0x1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -91,7 +92,8 @@ void home_x_positive() {
|
||||||
// set X home
|
// set X home
|
||||||
queue_wait();
|
queue_wait();
|
||||||
// set position to MAX
|
// set position to MAX
|
||||||
startpoint.X = next_target.target.X = (int32_t)(X_MAX * STEPS_PER_MM_X);
|
startpoint.X = next_target.target.X = (int32_t)(X_MAX * 1000.0);
|
||||||
|
dda_new_startpoint();
|
||||||
// go to zero
|
// go to zero
|
||||||
t.X = 0;
|
t.X = 0;
|
||||||
t.F = MAXIMUM_FEEDRATE_X;
|
t.F = MAXIMUM_FEEDRATE_X;
|
||||||
|
|
@ -128,6 +130,7 @@ void home_y_negative() {
|
||||||
#else
|
#else
|
||||||
startpoint.Y = next_target.target.Y = 0;
|
startpoint.Y = next_target.target.Y = 0;
|
||||||
#endif
|
#endif
|
||||||
|
dda_new_startpoint();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +163,7 @@ void home_y_positive() {
|
||||||
queue_wait();
|
queue_wait();
|
||||||
// set position to MAX
|
// set position to MAX
|
||||||
startpoint.Y = next_target.target.Y = (int32_t)(Y_MAX * STEPS_PER_MM_Y);
|
startpoint.Y = next_target.target.Y = (int32_t)(Y_MAX * STEPS_PER_MM_Y);
|
||||||
|
new_startpoint();
|
||||||
// go to zero
|
// go to zero
|
||||||
t.Y = 0;
|
t.Y = 0;
|
||||||
t.F = MAXIMUM_FEEDRATE_Y;
|
t.F = MAXIMUM_FEEDRATE_Y;
|
||||||
|
|
@ -196,6 +200,7 @@ void home_z_negative() {
|
||||||
#else
|
#else
|
||||||
startpoint.Z = next_target.target.Z = 0;
|
startpoint.Z = next_target.target.Z = 0;
|
||||||
#endif
|
#endif
|
||||||
|
dda_new_startpoint();
|
||||||
z_disable();
|
z_disable();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -229,6 +234,7 @@ void home_z_positive() {
|
||||||
queue_wait();
|
queue_wait();
|
||||||
// set position to MAX
|
// set position to MAX
|
||||||
startpoint.Z = next_target.target.Z = (int32_t)(Z_MAX * STEPS_PER_MM_Z);
|
startpoint.Z = next_target.target.Z = (int32_t)(Z_MAX * STEPS_PER_MM_Z);
|
||||||
|
dda_new_startpoint();
|
||||||
// go to zero
|
// go to zero
|
||||||
t.Z = 0;
|
t.Z = 0;
|
||||||
t.F = MAXIMUM_FEEDRATE_Z;
|
t.F = MAXIMUM_FEEDRATE_Z;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue