fixed buffering of pace changes and general cleaning
This commit is contained in:
parent
8a0c9fd180
commit
c07a322589
20
gcode.c
20
gcode.c
@ -126,6 +126,7 @@ void select_plane(uint8_t axis_0, uint8_t axis_1)
|
|||||||
// characters and signed floats (no whitespace).
|
// characters and signed floats (no whitespace).
|
||||||
uint8_t gc_execute_line(char *line) {
|
uint8_t gc_execute_line(char *line) {
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
int requires_nudge = false;
|
||||||
char letter;
|
char letter;
|
||||||
double value;
|
double value;
|
||||||
double unit_converted_value;
|
double unit_converted_value;
|
||||||
@ -376,17 +377,24 @@ uint8_t gc_execute_line(char *line) {
|
|||||||
// Find the radius
|
// Find the radius
|
||||||
double radius = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]);
|
double radius = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]);
|
||||||
// Prepare the arc
|
// Prepare the arc
|
||||||
printString("mc_arc(");
|
// printString("mc_arc(");
|
||||||
printInteger(trunc(theta_start/M_PI*180)); printByte(',');
|
// printInteger(trunc(theta_start/M_PI*180)); printByte(',');
|
||||||
printInteger(trunc(angular_travel/M_PI*180)); printByte(',');
|
// printInteger(trunc(angular_travel/M_PI*180)); printByte(',');
|
||||||
printInteger(trunc(radius));
|
// printInteger(trunc(radius));
|
||||||
printByte(')');
|
// printByte(')');
|
||||||
mc_arc(theta_start, angular_travel, radius, gc.plane_axis_0, gc.plane_axis_1, gc.feed_rate);
|
mc_arc(theta_start, angular_travel, radius, gc.plane_axis_0, gc.plane_axis_1, gc.feed_rate);
|
||||||
break;
|
// Rounding errors means the arcing might not land us exactly where we wanted. Thats why this
|
||||||
|
// operation must be finalized with a linear nudge to the exact target spot.
|
||||||
|
requires_nudge = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mc_execute();
|
mc_execute();
|
||||||
|
if (requires_nudge) {
|
||||||
|
mc_linear_motion(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.feed_rate, false);
|
||||||
|
mc_execute();
|
||||||
|
}
|
||||||
|
|
||||||
// As far as the parser is concerned, the position is now == target. In reality the
|
// As far as the parser is concerned, the position is now == target. In reality the
|
||||||
// motion control system might still be processing the action and the real tool position
|
// motion control system might still be processing the action and the real tool position
|
||||||
|
2
main.c
2
main.c
@ -40,7 +40,7 @@ int main(void)
|
|||||||
sp_init(); // initialize the serial protocol
|
sp_init(); // initialize the serial protocol
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
// sleep_mode();
|
sleep_mode();
|
||||||
sp_process(); // process the serial protocol
|
sp_process(); // process the serial protocol
|
||||||
}
|
}
|
||||||
return 0; /* never reached */
|
return 0; /* never reached */
|
||||||
|
@ -60,7 +60,6 @@ struct ArcMotionParameters {
|
|||||||
int32_t error, x2, y2; // error is always == (x**2 + y**2 - radius**2),
|
int32_t error, x2, y2; // error is always == (x**2 + y**2 - radius**2),
|
||||||
// x2 is always 2*x, y2 is always 2*y
|
// x2 is always 2*x, y2 is always 2*y
|
||||||
uint8_t axis_x, axis_y; // maps the arc axes to stepper axes
|
uint8_t axis_x, axis_y; // maps the arc axes to stepper axes
|
||||||
int32_t target[3]; // The target position in absolute steps
|
|
||||||
int8_t plane_steppers[3]; // A vector with the steppers of axis_x and axis_y set to 1, the remaining 0
|
int8_t plane_steppers[3]; // A vector with the steppers of axis_x and axis_y set to 1, the remaining 0
|
||||||
int incomplete; // True if the arc has not reached its target yet
|
int incomplete; // True if the arc has not reached its target yet
|
||||||
};
|
};
|
||||||
@ -102,18 +101,12 @@ void mc_dwell(uint32_t milliseconds)
|
|||||||
// Prepare for linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
|
// Prepare for linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
|
||||||
// unless invert_feed_rate is true. Then the feed_rate states the number of seconds for the whole movement.
|
// unless invert_feed_rate is true. Then the feed_rate states the number of seconds for the whole movement.
|
||||||
void mc_linear_motion(double x, double y, double z, float feed_rate, int invert_feed_rate)
|
void mc_linear_motion(double x, double y, double z, float feed_rate, int invert_feed_rate)
|
||||||
{
|
|
||||||
prepare_linear_motion(trunc(x*X_STEPS_PER_MM), trunc(y*Y_STEPS_PER_MM), trunc(z*Z_STEPS_PER_MM), feed_rate, invert_feed_rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as mc_linear_motion but accepts target in absolute step coordinates
|
|
||||||
void prepare_linear_motion(uint32_t x, uint32_t y, uint32_t z, float feed_rate, int invert_feed_rate)
|
|
||||||
{
|
{
|
||||||
memset(&mc.linear, 0, sizeof(mc.arc));
|
memset(&mc.linear, 0, sizeof(mc.arc));
|
||||||
|
|
||||||
mc.linear.target[X_AXIS] = x;
|
mc.linear.target[X_AXIS] = x*X_STEPS_PER_MM;
|
||||||
mc.linear.target[Y_AXIS] = y;
|
mc.linear.target[Y_AXIS] = y*Y_STEPS_PER_MM;
|
||||||
mc.linear.target[Z_AXIS] = z;
|
mc.linear.target[Z_AXIS] = z*Z_STEPS_PER_MM;
|
||||||
|
|
||||||
mc.mode = MC_MODE_LINEAR;
|
mc.mode = MC_MODE_LINEAR;
|
||||||
uint8_t axis; // loop variable
|
uint8_t axis; // loop variable
|
||||||
@ -125,9 +118,8 @@ void prepare_linear_motion(uint32_t x, uint32_t y, uint32_t z, float feed_rate,
|
|||||||
// Find the magnitude of the axis with the longest travel
|
// Find the magnitude of the axis with the longest travel
|
||||||
mc.linear.maximum_steps = max(mc.linear.step_count[Z_AXIS],
|
mc.linear.maximum_steps = max(mc.linear.step_count[Z_AXIS],
|
||||||
max(mc.linear.step_count[X_AXIS], mc.linear.step_count[Y_AXIS]));
|
max(mc.linear.step_count[X_AXIS], mc.linear.step_count[Y_AXIS]));
|
||||||
if(mc.linear.maximum_steps == 0) { return; }
|
|
||||||
// Nothing to do?
|
// Nothing to do?
|
||||||
if ((mc.linear.maximum_steps) == 0)
|
if (mc.linear.maximum_steps == 0)
|
||||||
{
|
{
|
||||||
mc.mode = MC_MODE_AT_REST;
|
mc.mode = MC_MODE_AT_REST;
|
||||||
return;
|
return;
|
||||||
@ -306,8 +298,7 @@ void execute_arc()
|
|||||||
// Update the tool position to the new actual position
|
// Update the tool position to the new actual position
|
||||||
mc.position[mc.arc.axis_x] += mc.arc.x-start_x;
|
mc.position[mc.arc.axis_x] += mc.arc.x-start_x;
|
||||||
mc.position[mc.arc.axis_y] += mc.arc.y-start_y;
|
mc.position[mc.arc.axis_y] += mc.arc.y-start_y;
|
||||||
// Todo: Because of rounding errors we might still be off by a step or two.
|
mc.mode = MC_MODE_AT_REST;
|
||||||
mc.mode = MC_MODE_AT_REST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mc_go_home()
|
void mc_go_home()
|
||||||
@ -324,15 +315,17 @@ void execute_go_home()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mc_execute() {
|
void mc_execute() {
|
||||||
st_set_pace(mc.pace);
|
if (mc.mode != MC_MODE_AT_REST) {
|
||||||
sp_send_execution_marker();
|
st_buffer_pace(mc.pace);
|
||||||
while(mc.mode) { // Loop because one task might start another task
|
sp_send_execution_marker();
|
||||||
switch(mc.mode) {
|
while(mc.mode) { // Loop because one task might start another task
|
||||||
case MC_MODE_AT_REST: break;
|
switch(mc.mode) {
|
||||||
case MC_MODE_DWELL: st_synchronize(); _delay_ms(mc.dwell_milliseconds); mc.mode = MC_MODE_AT_REST; break;
|
case MC_MODE_AT_REST: break;
|
||||||
case MC_MODE_LINEAR: execute_linear_motion(); break;
|
case MC_MODE_DWELL: st_synchronize(); _delay_ms(mc.dwell_milliseconds); mc.mode = MC_MODE_AT_REST; break;
|
||||||
case MC_MODE_ARC: execute_arc(); break;
|
case MC_MODE_LINEAR: execute_linear_motion(); break;
|
||||||
case MC_MODE_HOME: execute_go_home(); break;
|
case MC_MODE_ARC: execute_arc(); break;
|
||||||
|
case MC_MODE_HOME: execute_go_home(); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
stepper.c
46
stepper.c
@ -35,24 +35,34 @@
|
|||||||
volatile uint8_t step_buffer[STEP_BUFFER_SIZE]; // A buffer for step instructions
|
volatile uint8_t step_buffer[STEP_BUFFER_SIZE]; // A buffer for step instructions
|
||||||
volatile int step_buffer_head = 0;
|
volatile int step_buffer_head = 0;
|
||||||
volatile int step_buffer_tail = 0;
|
volatile int step_buffer_tail = 0;
|
||||||
|
volatile uint32_t current_pace;
|
||||||
|
volatile uint32_t next_pace = 0;
|
||||||
|
|
||||||
uint8_t stepper_mode = STEPPER_MODE_STOPPED;
|
uint8_t stepper_mode = STEPPER_MODE_STOPPED;
|
||||||
uint8_t echo_steps = true;
|
uint8_t echo_steps = true;
|
||||||
|
|
||||||
|
void config_pace_timer(uint32_t microseconds);
|
||||||
|
|
||||||
// This timer interrupt is executed at the pace set with set_pace. It pops one instruction from
|
// This timer interrupt is executed at the pace set with set_pace. It pops one instruction from
|
||||||
// the step_buffer, executes it. Then it starts timer2 in order to reset the motor port after
|
// the step_buffer, executes it. Then it starts timer2 in order to reset the motor port after
|
||||||
// five microseconds.
|
// five microseconds.
|
||||||
SIGNAL(SIG_OUTPUT_COMPARE1A)
|
SIGNAL(SIG_OUTPUT_COMPARE1A)
|
||||||
{
|
{
|
||||||
if (step_buffer_head != step_buffer_tail) {
|
if (step_buffer_head != step_buffer_tail) {
|
||||||
// Set the direction pins a nanosecond or two before you step the steppers
|
if(step_buffer[step_buffer_tail] == 0xff) {
|
||||||
STEPPING_PORT = (STEPPING_PORT & ~DIRECTION_MASK) | (step_buffer[step_buffer_tail] & DIRECTION_MASK);
|
// If this is not a step-instruction, but a pace-marker: change pace
|
||||||
// Then pulse the stepping pins
|
config_pace_timer(next_pace);
|
||||||
STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | step_buffer[step_buffer_tail];
|
next_pace = 0;
|
||||||
// Reset and start timer 2 which will reset the motor port after 5 microsecond
|
} else {
|
||||||
TCNT2 = 0; // reset counter
|
// Set the direction pins a nanosecond or two before you step the steppers
|
||||||
OCR2A = 5*TICKS_PER_MICROSECOND; // set the time
|
STEPPING_PORT = (STEPPING_PORT & ~DIRECTION_MASK) | (step_buffer[step_buffer_tail] & DIRECTION_MASK);
|
||||||
TIMSK2 |= (1<<OCIE2A); // enable interrupt
|
// Then pulse the stepping pins
|
||||||
|
STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | step_buffer[step_buffer_tail];
|
||||||
|
// Reset and start timer 2 which will reset the motor port after 5 microsecond
|
||||||
|
TCNT2 = 0; // reset counter
|
||||||
|
OCR2A = 5*TICKS_PER_MICROSECOND; // set the time
|
||||||
|
TIMSK2 |= (1<<OCIE2A); // enable interrupt
|
||||||
|
}
|
||||||
// move the step buffer tail to the next instruction
|
// move the step buffer tail to the next instruction
|
||||||
step_buffer_tail = (step_buffer_tail + 1) % STEP_BUFFER_SIZE;
|
step_buffer_tail = (step_buffer_tail + 1) % STEP_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
@ -92,7 +102,7 @@ void st_init()
|
|||||||
sei();
|
sei();
|
||||||
|
|
||||||
// start off with a slow pace
|
// start off with a slow pace
|
||||||
st_set_pace(20000);
|
config_pace_timer(20000);
|
||||||
st_start();
|
st_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,11 +158,20 @@ inline void st_stop()
|
|||||||
stepper_mode = STEPPER_MODE_STOPPED;
|
stepper_mode = STEPPER_MODE_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void st_set_pace(uint32_t microseconds)
|
void st_buffer_pace(uint32_t microseconds)
|
||||||
|
{
|
||||||
|
// Do nothing if the pace in unchanged
|
||||||
|
if (current_pace == microseconds) { return; }
|
||||||
|
// If the one-element pace buffer is full, flush step buffer
|
||||||
|
if (next_pace != 0) {
|
||||||
|
st_synchronize();
|
||||||
|
}
|
||||||
|
next_pace = microseconds;
|
||||||
|
st_buffer_step(0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void config_pace_timer(uint32_t microseconds)
|
||||||
{
|
{
|
||||||
printString("pace = ");
|
|
||||||
printInteger(microseconds);
|
|
||||||
printString("\n\r");
|
|
||||||
uint32_t ticks = microseconds*TICKS_PER_MICROSECOND;
|
uint32_t ticks = microseconds*TICKS_PER_MICROSECOND;
|
||||||
uint16_t ceiling;
|
uint16_t ceiling;
|
||||||
uint16_t prescaler;
|
uint16_t prescaler;
|
||||||
@ -180,6 +199,7 @@ void st_set_pace(uint32_t microseconds)
|
|||||||
TCCR1B = (TCCR1B & ~(0x07<<CS10)) | ((prescaler+1)<<CS10);
|
TCCR1B = (TCCR1B & ~(0x07<<CS10)) | ((prescaler+1)<<CS10);
|
||||||
// Set ceiling
|
// Set ceiling
|
||||||
OCR1A = ceiling;
|
OCR1A = ceiling;
|
||||||
|
current_pace = microseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_limit_switches()
|
int check_limit_switches()
|
||||||
|
1
todo.txt
1
todo.txt
@ -4,7 +4,6 @@
|
|||||||
* Generalize feed rate code and support inverse feed rate for arcs
|
* Generalize feed rate code and support inverse feed rate for arcs
|
||||||
* Implement homing cycle in stepper.c
|
* Implement homing cycle in stepper.c
|
||||||
* Implement limit switch support in stepper.c (use port-triggered interrupts?)
|
* Implement limit switch support in stepper.c (use port-triggered interrupts?)
|
||||||
* How to implement st_set_pace? Consider synchronizing when pace is changed
|
|
||||||
* How on earth am I going to deal with arcs in setups that have different steps/mm on each axis? Must
|
* How on earth am I going to deal with arcs in setups that have different steps/mm on each axis? Must
|
||||||
support elipses?! Oh no.
|
support elipses?! Oh no.
|
||||||
* Support helical interpolation
|
* Support helical interpolation
|
||||||
|
Loading…
Reference in New Issue
Block a user