Skip to content

Commit

Permalink
dwell implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan Hechenberger committed Mar 21, 2012
1 parent 303f5c9 commit 3b273c8
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 97 deletions.
2 changes: 1 addition & 1 deletion config.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
#define CONFIG_INVERT_X_AXIS 1 // 0 is regular, 1 inverts the x direction
#define CONFIG_INVERT_Y_AXIS 1 // 0 is regular, 1 inverts the y direction

#define CONFIG_WAIT_ON_SCODE 0 // time (sec) to wait after a S-code laser intensity change
#define CONFIG_BEAM_DYNAMICS 0 // whether (0 or 1) to adapt the laser intensity to speed changes
#define CONFIG_USE_LASER_ENABLE_BIT 0 // whether (0 or 1) to use the laser enable pin on seeks (G0)
#define CONFIG_LASER_ENABLE_LATENCY 0 // time (sec) it takes to enable the laser


#define LIMITS_OVERWRITE_DDR DDRD
Expand Down
61 changes: 38 additions & 23 deletions gcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ uint8_t gcode_execute_line(char *line) {
int int_value;
double unit_converted_value;
uint8_t next_action = NEXT_ACTION_NONE;
double target[3], offset[3];
double p = 0;
double target[3];
double p = 0.0;
int cs = 0;
int l = 0;
gc.status_code = STATUS_OK;
Expand Down Expand Up @@ -248,8 +248,6 @@ uint8_t gcode_execute_line(char *line) {
if (gc.status_code) { return gc.status_code; }

char_counter = 0;
clear_vector(target);
clear_vector(offset);
memcpy(target, gc.position, sizeof(target)); // i.e. target = gc.position

//// Pass 2: Parameters
Expand Down Expand Up @@ -296,22 +294,39 @@ uint8_t gcode_execute_line(char *line) {

//// Perform any physical actions
switch (next_action) {
case NEXT_ACTION_SEEK:
planner_line( target[X_AXIS] + gc.offsets[3*gc.offselect+X_AXIS],
target[Y_AXIS] + gc.offsets[3*gc.offselect+Y_AXIS],
target[Z_AXIS] + gc.offsets[3*gc.offselect+Z_AXIS],
gc.seek_rate, 0 );
case NEXT_ACTION_SEEK: // G0
if (CONFIG_USE_LASER_ENABLE_BIT) {
if (control_is_laser_enabled()) {
// when path ends -> disable laser and dwell some time
planner_control_laser_disable(CONFIG_LASER_ENABLE_LATENCY);
}
// seek - keep pwm up, laser is disabled via the LASER_ENABLE_BIT
planner_line( target[X_AXIS] + gc.offsets[3*gc.offselect+X_AXIS],
target[Y_AXIS] + gc.offsets[3*gc.offselect+Y_AXIS],
target[Z_AXIS] + gc.offsets[3*gc.offselect+Z_AXIS],
gc.seek_rate, gc.nominal_laser_intensity );
} else {
// seek - turn pwm down
planner_line( target[X_AXIS] + gc.offsets[3*gc.offselect+X_AXIS],
target[Y_AXIS] + gc.offsets[3*gc.offselect+Y_AXIS],
target[Z_AXIS] + gc.offsets[3*gc.offselect+Z_AXIS],
gc.seek_rate, 0 );
}
break;
case NEXT_ACTION_FEED:
case NEXT_ACTION_FEED: // G1
if (CONFIG_USE_LASER_ENABLE_BIT && !control_is_laser_enabled()) {
// when a new path starts -> enable laser and dwell some time
planner_control_laser_enable(CONFIG_LASER_ENABLE_LATENCY, gc.nominal_laser_intensity);
}
planner_line( target[X_AXIS] + gc.offsets[3*gc.offselect+X_AXIS],
target[Y_AXIS] + gc.offsets[3*gc.offselect+Y_AXIS],
target[Z_AXIS] + gc.offsets[3*gc.offselect+Z_AXIS],
gc.feed_rate, gc.nominal_laser_intensity );
break;
case NEXT_ACTION_DWELL:
case NEXT_ACTION_DWELL: // G4
planner_dwell(p, gc.nominal_laser_intensity);
break;
case NEXT_ACTION_HOMING_CYCLE:
case NEXT_ACTION_HOMING_CYCLE: // G30
stepper_homing_cycle();
// now that we are at the physical home
// zero all the position vectors
Expand All @@ -328,7 +343,7 @@ uint8_t gcode_execute_line(char *line) {
target[Z_AXIS] + gc.offsets[3*gc.offselect+Z_AXIS],
gc.seek_rate, 0 );
break;
case NEXT_ACTION_SET_COORDINATE_OFFSET:
case NEXT_ACTION_SET_COORDINATE_OFFSET: // G10
if (cs == OFFSET_G54 || cs == OFFSET_G55) {
if (l == 2) {
//set offset to target, eg: G10 L2 P1 X15 Y15 Z0
Expand All @@ -343,20 +358,20 @@ uint8_t gcode_execute_line(char *line) {
}
}
break;
case NEXT_ACTION_AIRGAS_DISABLE:
planner_control_airgas_disable();
case NEXT_ACTION_AIRGAS_DISABLE: // M9
planner_control_airgas_disable(p);
break;
case NEXT_ACTION_AIR_ENABLE:
planner_control_air_enable();
case NEXT_ACTION_AIR_ENABLE: // M7
planner_control_air_enable(p);
break;
case NEXT_ACTION_GAS_ENABLE:
planner_control_gas_enable();
case NEXT_ACTION_GAS_ENABLE: // M8
planner_control_gas_enable(p);
break;
case NEXT_ACTION_LASER_ENABLE:
planner_control_laser_enable();
case NEXT_ACTION_LASER_ENABLE: // M141
planner_control_laser_enable(p, gc.nominal_laser_intensity);
break;
case NEXT_ACTION_LASER_DISABLE:
planner_control_laser_disable();
case NEXT_ACTION_LASER_DISABLE: // M140
planner_control_laser_disable(p);
break;
}

Expand Down
26 changes: 11 additions & 15 deletions planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,21 +195,14 @@ void planner_line(double x, double y, double z, double feed_rate, uint8_t nomina
}


void planner_dwell(double seconds, uint8_t nominal_laser_intensity) {
// // Execute dwell in seconds. Maximum time delay is > 18 hours, more than enough for any application.
// void mc_dwell(double seconds) {
// uint16_t i = floor(seconds);
// stepper_synchronize();
// _delay_ms(floor(1000*(seconds-i))); // Delay millisecond remainder
// while (i > 0) {
// _delay_ms(1000); // Delay one second
// i--;
// }
// }
}


void planner_command(uint8_t type) {
// Add a new control and/or dwell command to the queue.
// These commands can control a GPIO and then dwell for a bit. This is useful when
// the hardware being switch has some delay. Alternatively by passing TYPE_DWELL the
// switching part can be omitted and simply a dwell can be scheduled. When doing this
// with a laser intensity !=0 this is effectively a piercing action.
// Note: any command (even when dwell time is 0) causes the planner to fully decelerate.
void planner_command(uint8_t type, double seconds, uint8_t nominal_laser_intensity) {
// calculate the buffer head and check for space
int next_buffer_head = next_block_index( block_buffer_head );
while(block_buffer_tail == next_buffer_head) { // buffer full condition
Expand All @@ -223,9 +216,12 @@ void planner_command(uint8_t type) {
// set block type command
block->type = type;

// set dwell time in cycles
block->dwell_until = seconds * F_CPU;

// set block fields so planner calculates a correct
// acceleration profiles for the adjacent blocks
block->nominal_laser_intensity = 0;
block->nominal_laser_intensity = nominal_laser_intensity;
block->direction_bits = 0;
block->steps_x = 0;
block->steps_y = 0;
Expand Down
31 changes: 16 additions & 15 deletions planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,22 @@
#include "config.h"


// Command types the planner and stepper can schedule for execution
// Command types the planner and stepper can schedule for execution
#define TYPE_LINE 0
#define TYPE_AIRGAS_DISABLE 1
#define TYPE_AIR_ENABLE 2
#define TYPE_GAS_ENABLE 3
#define TYPE_LASER_ENABLE 4
#define TYPE_LASER_DISABLE 5
#define TYPE_DWELL 1
#define TYPE_AIRGAS_DISABLE 2
#define TYPE_AIR_ENABLE 3
#define TYPE_GAS_ENABLE 4
#define TYPE_LASER_ENABLE 5
#define TYPE_LASER_DISABLE 6

#define planner_control_airgas_disable() planner_command(TYPE_AIRGAS_DISABLE)
#define planner_control_air_enable() planner_command(TYPE_AIR_ENABLE)
#define planner_control_gas_enable() planner_command(TYPE_GAS_ENABLE)
#define planner_control_laser_enable() planner_command(TYPE_LASER_ENABLE)
#define planner_control_laser_disable() planner_command(TYPE_LASER_DISABLE)

#define planner_dwell(seconds, intensity) planner_command(TYPE_DWELL, seconds, intensity)
#define planner_control_airgas_disable(seconds) planner_command(TYPE_AIRGAS_DISABLE, seconds, 0)
#define planner_control_air_enable(seconds) planner_command(TYPE_AIR_ENABLE, seconds, 0)
#define planner_control_gas_enable(seconds) planner_command(TYPE_GAS_ENABLE, seconds, 0)
#define planner_control_laser_enable(seconds, intensity) planner_command(TYPE_LASER_ENABLE, seconds, intensity)
#define planner_control_laser_disable(seconds) planner_command(TYPE_LASER_DISABLE, seconds, 0)


// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
Expand All @@ -53,6 +56,7 @@ typedef struct {
double entry_speed; // Entry speed at previous-current junction in mm/min
double vmax_junction; // max junction speed (mm/min) based on angle between segments, accel and deviation settings
double millimeters; // The total travel of this block in mm
double dwell_until; // number of cycles to dwell in place (not used for TYPE_LINE)
uint8_t nominal_laser_intensity; // 0-255 is 0-100% percentage
bool recalculate_flag; // Planner flag to recalculate trapezoids on entry junction
bool nominal_length_flag; // Planner flag for nominal speed always reached
Expand All @@ -72,12 +76,9 @@ void planner_init();
// the signed, absolute target position in millimaters. Feed rate specifies the speed of the motion.
void planner_line(double x, double y, double z, double feed_rate, uint8_t nominal_laser_intensity);

// Add a new piercing action, lasing at one spot
void planner_dwell(double seconds, uint8_t nominal_laser_intensity);

// Add a non-motion command to the queue.
// Typical types are: TYPE_AIRGAS_DISABLE, TYPE_AIR_ENABLE, TYPE_GAS_ENABLE
void planner_command(uint8_t type);
void planner_command(uint8_t type, double seconds, uint8_t nominal_laser_intensity);


bool planner_blocks_available();
Expand Down
5 changes: 5 additions & 0 deletions sense_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void control_init() {
}



void control_laser_enable(bool enable) {
if (enable) {
LASER_PORT &= ~(1 << LASER_ENABLE_BIT);
Expand All @@ -73,6 +74,10 @@ void control_laser_enable(bool enable) {
}
}

bool control_is_laser_enabled() {
return (LASER_PORT >> LASER_ENABLE_BIT) & 1;
}

void control_laser_intensity(uint8_t intensity) {
OCR0A = intensity;
}
Expand Down
1 change: 1 addition & 0 deletions sense_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void sense_init();
void control_init();

void control_laser_enable(bool enable);
bool control_is_laser_enabled();
void control_laser_intensity(uint8_t intensity); //0-255 is 0-100%

void control_air(bool enable);
Expand Down
89 changes: 46 additions & 43 deletions stepper.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ static volatile uint8_t busy; // true whe stepper ISR is in already running

// Variables used by the trapezoid generation
static uint32_t cycles_per_step_event; // The number of machine cycles between each step event
static uint32_t acceleration_tick_counter; // The cycles since last acceleration_tick.
static uint32_t tick_counter; // The cycles since last speed change.
// Used to generate ticks at a steady pace without allocating a separate timer.
static uint32_t adjusted_rate; // The current rate of step_events according to the speed profile
static bool processing_flag; // indicates if blocks are being processed
static volatile bool stop_requested; // when set to true stepper interrupt will go idle on next entry


// prototypes for static functions (non-accesible from other files)
static bool acceleration_tick();
static void adjust_speed( uint32_t steps_per_minute );
Expand Down Expand Up @@ -107,7 +106,7 @@ void stepper_init() {

adjust_speed(MINIMUM_STEPS_PER_MINUTE);
clear_vector(stepper_position);
acceleration_tick_counter = 0;
tick_counter = 0;
current_block = NULL;
stop_requested = false;
busy = false;
Expand Down Expand Up @@ -250,18 +249,20 @@ ISR(TIMER1_COMPA_vect) {
// event - starting new block
if (current_block->type == TYPE_LINE) {
adjusted_rate = current_block->initial_rate;
acceleration_tick_counter = CYCLES_PER_ACCELERATION_TICK/2; // start halfway, midpoint rule.
tick_counter = CYCLES_PER_ACCELERATION_TICK/2; // start halfway, midpoint rule.
adjust_speed( adjusted_rate ); // initialize cycles_per_step_event
counter_x = -(current_block->step_event_count >> 1);
counter_y = counter_x;
counter_z = counter_x;
step_events_completed = 0;
} else { // TYPE_DWELL, ...
tick_counter = 0; // use tick_counter to keep track of dwell time
}
}

// process current block, populate out_bits (or handle other commands)
switch (current_block->type) {
case TYPE_LINE:
//// process current block, populate out_bits (or handle other commands) ////

if (current_block->type == TYPE_LINE) {
////// Execute step displacement profile by bresenham line algorithm
out_bits = current_block->direction_bits;
counter_x += current_block->steps_x;
Expand Down Expand Up @@ -321,7 +322,7 @@ ISR(TIMER1_COMPA_vect) {
} else if (step_events_completed == current_block->decelerate_after) {
// reset counter, midpoint rule
// makes sure deceleration is performed the same every time
acceleration_tick_counter = CYCLES_PER_ACCELERATION_TICK/2;
tick_counter = CYCLES_PER_ACCELERATION_TICK/2;

// decelerating
} else if (step_events_completed >= current_block->decelerate_after) {
Expand All @@ -347,38 +348,40 @@ ISR(TIMER1_COMPA_vect) {
}
////////// END OF SPEED ADJUSTMENT

break;

case TYPE_AIRGAS_DISABLE:
control_air(false);
control_gas(false);
current_block = NULL;
planner_discard_current_block();
break;

case TYPE_AIR_ENABLE:
control_air(true);
current_block = NULL;
planner_discard_current_block();
break;

case TYPE_GAS_ENABLE:
control_gas(true);
current_block = NULL;
planner_discard_current_block();
break;

case TYPE_LASER_ENABLE:
control_laser_enable(true);
current_block = NULL;
planner_discard_current_block();
break;

case TYPE_LASER_DISABLE:
control_laser_enable(false);
current_block = NULL;
planner_discard_current_block();
break;
} else if ( current_block->type == TYPE_DWELL ||
current_block->type == TYPE_AIRGAS_DISABLE ||
current_block->type == TYPE_AIR_ENABLE ||
current_block->type == TYPE_GAS_ENABLE ||
current_block->type == TYPE_LASER_ENABLE ||
current_block->type == TYPE_LASER_DISABLE ) {
// on first entry do switching based on type
if (tick_counter == 0) {
switch (current_block->type) {
case TYPE_AIRGAS_DISABLE:
control_air(false);
control_gas(false);
break;
case TYPE_AIR_ENABLE:
control_air(true);
break;
case TYPE_GAS_ENABLE:
control_gas(true);
break;
case TYPE_LASER_ENABLE:
control_laser_enable(true);
break;
case TYPE_LASER_DISABLE:
control_laser_enable(false);
break;
}
}
// keep track of time
tick_counter += cycles_per_step_event;
// finalize when dwell time is over
if(tick_counter > current_block->dwell_until) {
current_block = NULL;
planner_discard_current_block();
} // else reenter and increase tick_counter until dwell time over
}

busy = false;
Expand All @@ -391,9 +394,9 @@ ISR(TIMER1_COMPA_vect) {
// keeping track of the number of elapsed cycles during a de/ac-celeration. The code assumes that
// step_events occur significantly more often than the acceleration velocity iterations.
static bool acceleration_tick() {
acceleration_tick_counter += cycles_per_step_event;
if(acceleration_tick_counter > CYCLES_PER_ACCELERATION_TICK) {
acceleration_tick_counter -= CYCLES_PER_ACCELERATION_TICK;
tick_counter += cycles_per_step_event;
if(tick_counter > CYCLES_PER_ACCELERATION_TICK) {
tick_counter -= CYCLES_PER_ACCELERATION_TICK;
return true;
} else {
return false;
Expand Down

0 comments on commit 3b273c8

Please sign in to comment.