Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4th axis for grbl Mega #21

Open
wants to merge 5 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions grbl/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
// one configuration file by placing their specific defaults and pin map at the bottom of this file.
// If doing so, simply comment out these two defines and see instructions below.
#define DEFAULTS_GENERIC
#define DEFAULTS_ABC_AXIS
#define CPU_MAP_2560_INITIAL

// Serial baud rate
Expand Down Expand Up @@ -105,6 +106,9 @@
#define HOMING_CYCLE_0 (1<<Z_AXIS) // REQUIRED: First move Z to clear workspace.
#define HOMING_CYCLE_1 ((1<<X_AXIS)|(1<<Y_AXIS)) // OPTIONAL: Then move X,Y at the same time.
// #define HOMING_CYCLE_2 // OPTIONAL: Uncomment and add axes mask to enable
// #define HOMING_CYCLE_3 // OPTIONAL: Uncomment and add axes mask to enable
// #define HOMING_CYCLE_4 // OPTIONAL: Uncomment and add axes mask to enable
// #define HOMING_CYCLE_5 // OPTIONAL: Uncomment and add axes mask to enable

// NOTE: The following are two examples to setup homing for 2-axis machines.
// #define HOMING_CYCLE_0 ((1<<X_AXIS)|(1<<Y_AXIS)) // NOT COMPATIBLE WITH COREXY: Homes both X-Y in one cycle.
Expand Down
15 changes: 12 additions & 3 deletions grbl/cpu_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
#define X_STEP_BIT 2 // MEGA2560 Digital Pin 24
#define Y_STEP_BIT 3 // MEGA2560 Digital Pin 25
#define Z_STEP_BIT 4 // MEGA2560 Digital Pin 26
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits
#define A_STEP_BIT 5 // MEGA2560 Digital Pin 27
#define B_STEP_BIT 6 // MEGA2560 Digital Pin 28
#define C_STEP_BIT 7 // MEGA2560 Digital Pin 29
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)|(1<<A_STEP_BIT)|(1<<B_STEP_BIT)|(1<<C_STEP_BIT)) // All step bits

// Define step direction output pins. NOTE: All direction pins must be on the same port.
#define DIRECTION_DDR DDRC
Expand All @@ -48,7 +51,10 @@
#define X_DIRECTION_BIT 7 // MEGA2560 Digital Pin 30
#define Y_DIRECTION_BIT 6 // MEGA2560 Digital Pin 31
#define Z_DIRECTION_BIT 5 // MEGA2560 Digital Pin 32
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits
#define A_DIRECTION_BIT 4 // MEGA2560 Digital Pin 33
#define B_DIRECTION_BIT 3 // MEGA2560 Digital Pin 34
#define C_DIRECTION_BIT 2 // MEGA2560 Digital Pin 35
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)|(1<<A_DIRECTION_BIT)|(1<<B_DIRECTION_BIT)|(1<<C_DIRECTION_BIT)) // All direction bits

// Define stepper driver enable/disable output pin.
#define STEPPERS_DISABLE_DDR DDRB
Expand All @@ -64,10 +70,13 @@
#define X_LIMIT_BIT 4 // MEGA2560 Digital Pin 10
#define Y_LIMIT_BIT 5 // MEGA2560 Digital Pin 11
#define Z_LIMIT_BIT 6 // MEGA2560 Digital Pin 12
#define A_LIMIT_BIT 0 // MEGA2560 Digital Pin 53
#define B_LIMIT_BIT 1 // MEGA2560 Digital Pin 52
#define C_LIMIT_BIT 2 // MEGA2560 Digital Pin 51
#define LIMIT_INT PCIE0 // Pin change interrupt enable pin
#define LIMIT_INT_vect PCINT0_vect
#define LIMIT_PCMSK PCMSK0 // Pin change interrupt register
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)|(1<<A_LIMIT_BIT)|(1<<B_LIMIT_BIT)|(1<<C_LIMIT_BIT)) // All limit bits

// Define spindle enable and spindle direction output pins.
#define SPINDLE_ENABLE_DDR DDRH
Expand Down
17 changes: 17 additions & 0 deletions grbl/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,21 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif

#ifdef DEFAULTS_ABC_AXIS
#define DEFAULT_A_STEPS_PER_MM 250.0
#define DEFAULT_A_MAX_RATE 500.0 // mm/min
#define DEFAULT_A_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_A_MAX_TRAVEL 200.0 // mm

#define DEFAULT_B_STEPS_PER_MM 250.0
#define DEFAULT_B_MAX_RATE 500.0 // mm/min
#define DEFAULT_B_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_B_MAX_TRAVEL 200.0 // mm

#define DEFAULT_C_STEPS_PER_MM 250.0
#define DEFAULT_C_MAX_RATE 500.0 // mm/min
#define DEFAULT_C_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_C_MAX_TRAVEL 200.0 // mm
#endif

#endif
13 changes: 12 additions & 1 deletion grbl/gcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ uint8_t gc_execute_line(char *line)
legal g-code words and stores their value. Error-checking is performed later since some
words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */
switch(letter){
#ifdef A_AXIS
case 'A': word_bit = WORD_A; gc_block.values.xyz[A_AXIS] = value; axis_words |= (1<<A_AXIS); break;
#endif
#ifdef B_AXIS
case 'B': word_bit = WORD_B; gc_block.values.xyz[B_AXIS] = value; axis_words |= (1<<B_AXIS); break;
#endif
#ifdef C_AXIS
case 'C': word_bit = WORD_C; gc_block.values.xyz[C_AXIS] = value; axis_words |= (1<<C_AXIS); break;
#endif

// case 'A': // Not supported
// case 'B': // Not supported
// case 'C': // Not supported
Expand Down Expand Up @@ -518,6 +528,7 @@ uint8_t gc_execute_line(char *line)
else { coord_select = gc_block.modal.coord_select; } // Index P0 as the active coordinate system

// NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
// FIXME: Instead of IJK, we'd better use: float vector[N_AXIS]; // [DG]
if (!settings_read_coord_data(coord_select,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); } // [EEPROM read fail]

// Pre-calculate the coordinate data changes.
Expand Down Expand Up @@ -810,7 +821,7 @@ uint8_t gc_execute_line(char *line)
} else {
bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words.
}
if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words.
if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z)|bit(WORD_A)|bit(WORD_B)|bit(WORD_C))); } // Remove axis words.
if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]

/* -------------------------------------------------------------------------------------
Expand Down
8 changes: 6 additions & 2 deletions grbl/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@
#define WORD_Y 11
#define WORD_Z 12

#define WORD_A 13
#define WORD_B 14
#define WORD_C 15

// Define g-code parser position updating flags
#define GC_UPDATE_POS_TARGET 0 // Must be zero
#define GC_UPDATE_POS_SYSTEM 1
Expand Down Expand Up @@ -191,15 +195,15 @@ typedef struct {

typedef struct {
float f; // Feed
float ijk[3]; // I,J,K Axis arc offsets
float ijk[N_AXIS]; // I,J,K Axis arc offsets
uint8_t l; // G10 or canned cycles parameters
int32_t n; // Line number
float p; // G10 or dwell parameters
// float q; // G82 peck drilling
float r; // Arc radius
float s; // Spindle speed
uint8_t t; // Tool selection
float xyz[3]; // X,Y,Z Translational axes
float xyz[N_AXIS]; // X,Y,Z Translational axes
} gc_values_t;


Expand Down
9 changes: 9 additions & 0 deletions grbl/motion_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ void mc_homing_cycle(uint8_t cycle_mask)
#ifdef HOMING_CYCLE_2
limits_go_home(HOMING_CYCLE_2); // Homing cycle 2
#endif
#ifdef HOMING_CYCLE_3
limits_go_home(HOMING_CYCLE_3); // Homing cycle 3
#endif
#ifdef HOMING_CYCLE_4
limits_go_home(HOMING_CYCLE_4); // Homing cycle 4
#endif
#ifdef HOMING_CYCLE_5
limits_go_home(HOMING_CYCLE_5); // Homing cycle 5
#endif
}

protocol_execute_realtime(); // Check for reset and set system abort.
Expand Down
6 changes: 4 additions & 2 deletions grbl/nuts_bolts.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
#define SOME_LARGE_VALUE 1.0E+38

// Axis array index values. Must start with 0 and be continuous.
#define N_AXIS 3 // Number of axes
#define N_AXIS 4 // Number of axes
#define X_AXIS 0 // Axis indexing value.
#define Y_AXIS 1
#define Z_AXIS 2
// #define A_AXIS 3
#define A_AXIS 3
//#define B_AXIS 4
//#define C_AXIS 5

// CoreXY motor assignments. DO NOT ALTER.
// NOTE: If the A and B motor axis bindings are changed, this effects the CoreXY equations.
Expand Down
9 changes: 9 additions & 0 deletions grbl/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,15 @@ void report_realtime_status()
if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); }
if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); }
if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); }
#ifdef A_AXIS
if (bit_istrue(lim_pin_state,bit(A_AXIS))) { serial_write('A'); }
#endif
#ifdef B_AXIS
if (bit_istrue(lim_pin_state,bit(B_AXIS))) { serial_write('B'); }
#endif
#ifdef C_AXIS
if (bit_istrue(lim_pin_state,bit(C_AXIS))) { serial_write('C'); }
#endif
}
if (ctrl_pin_state) {
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
Expand Down
60 changes: 59 additions & 1 deletion grbl/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ void settings_restore(uint8_t restore_flag) {
settings.max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL);
settings.max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL);

#ifdef A_AXIS
settings.steps_per_mm[A_AXIS] = DEFAULT_A_STEPS_PER_MM;
settings.max_rate[A_AXIS] = DEFAULT_A_MAX_RATE;
settings.acceleration[A_AXIS] = DEFAULT_A_ACCELERATION;
settings.max_travel[A_AXIS] = (-DEFAULT_A_MAX_TRAVEL);
#endif
#ifdef B_AXIS
settings.steps_per_mm[B_AXIS] = DEFAULT_B_STEPS_PER_MM;
settings.max_rate[B_AXIS] = DEFAULT_B_MAX_RATE;
settings.acceleration[B_AXIS] = DEFAULT_B_ACCELERATION;
settings.max_travel[B_AXIS] = (-DEFAULT_B_MAX_TRAVEL);
#endif
#ifdef C_AXIS
settings.steps_per_mm[C_AXIS] = DEFAULT_C_STEPS_PER_MM;
settings.acceleration[C_AXIS] = DEFAULT_C_ACCELERATION;
settings.max_rate[C_AXIS] = DEFAULT_C_MAX_RATE;
settings.max_travel[C_AXIS] = (-DEFAULT_C_MAX_TRAVEL);
#endif

write_global_settings();
}

Expand Down Expand Up @@ -317,7 +336,20 @@ uint8_t get_step_pin_mask(uint8_t axis_idx)
{
if ( axis_idx == X_AXIS ) { return((1<<X_STEP_BIT)); }
if ( axis_idx == Y_AXIS ) { return((1<<Y_STEP_BIT)); }
#if defined(A_AXIS) || defined(B_AXIS) || defined(C_AXIS)
if ( axis_idx == Z_AXIS ) { return((1<<Z_STEP_BIT)); }
#endif
#ifdef A_AXIS
if ( axis_idx == A_AXIS ) { return((1<<A_STEP_BIT)); }
#endif
#ifdef B_AXIS
if ( axis_idx == B_AXIS ) { return((1<<B_STEP_BIT)); }
#endif
#ifdef C_AXIS
return((1<<C_STEP_BIT));
#else
return((1<<Z_STEP_BIT));
#endif
}


Expand All @@ -326,7 +358,20 @@ uint8_t get_direction_pin_mask(uint8_t axis_idx)
{
if ( axis_idx == X_AXIS ) { return((1<<X_DIRECTION_BIT)); }
if ( axis_idx == Y_AXIS ) { return((1<<Y_DIRECTION_BIT)); }
#if defined(A_AXIS) || defined(B_AXIS) || defined(C_AXIS)
if ( axis_idx == Z_AXIS ) { return((1<<Z_DIRECTION_BIT)); }
#endif
#ifdef A_AXIS
if ( axis_idx == A_AXIS ) { return((1<<A_DIRECTION_BIT)); }
#endif
#ifdef B_AXIS
if ( axis_idx == B_AXIS ) { return((1<<B_DIRECTION_BIT)); }
#endif
#ifdef C_AXIS
return((1<<C_DIRECTION_BIT));
#else
return((1<<Z_DIRECTION_BIT));
#endif
}


Expand All @@ -335,5 +380,18 @@ uint8_t get_limit_pin_mask(uint8_t axis_idx)
{
if ( axis_idx == X_AXIS ) { return((1<<X_LIMIT_BIT)); }
if ( axis_idx == Y_AXIS ) { return((1<<Y_LIMIT_BIT)); }
return((1<<Z_LIMIT_BIT));
#if defined(A_AXIS) || defined(B_AXIS) || defined(C_AXIS)
if ( axis_idx == Z_AXIS ) { return((1<<Z_LIMIT_BIT)); }
#endif
#ifdef A_AXIS
if ( axis_idx == A_AXIS ) { return((1<<A_LIMIT_BIT)); }
#endif
#ifdef B_AXIS
if ( axis_idx == B_AXIS ) { return((1<<B_LIMIT_BIT)); }
#endif
#ifdef C_AXIS
return((1<<C_LIMIT_BIT));
#else
return((1<<Z_LIMIT_BIT));
#endif
}
66 changes: 65 additions & 1 deletion grbl/stepper.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,18 @@ typedef struct {
// Used by the bresenham line algorithm
uint32_t counter_x, // Counter variables for the bresenham line tracer
counter_y,
counter_z;
counter_z
#ifdef A_AXIS
, counter_a
#endif
#ifdef B_AXIS
, counter_b
#endif
#ifdef C_AXIS
, counter_c
#endif
;

#ifdef STEP_PULSE_DELAY
uint8_t step_bits; // Stores out_bits output to complete the step pulse delay
#endif
Expand Down Expand Up @@ -339,6 +350,9 @@ ISR(TIMER1_COMPA_vect)

// Initialize Bresenham line and distance counters
st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1);
#ifdef A_AXIS
st.counter_a = st.counter_x;
#endif
}
st.dir_outbits = st.exec_block->direction_bits ^ dir_port_invert_mask;

Expand All @@ -347,6 +361,16 @@ ISR(TIMER1_COMPA_vect)
st.steps[X_AXIS] = st.exec_block->steps[X_AXIS] >> st.exec_segment->amass_level;
st.steps[Y_AXIS] = st.exec_block->steps[Y_AXIS] >> st.exec_segment->amass_level;
st.steps[Z_AXIS] = st.exec_block->steps[Z_AXIS] >> st.exec_segment->amass_level;
#ifdef A_AXIS
st.steps[A_AXIS] = st.exec_block->steps[A_AXIS] >> st.exec_segment->amass_level;
#endif
#ifdef B_AXIS
st.steps[B_AXIS] = st.exec_block->steps[B_AXIS] >> st.exec_segment->amass_level;
#endif
#ifdef C_AXIS
st.steps[C_AXIS] = st.exec_block->steps[C_AXIS] >> st.exec_segment->amass_level;
#endif

#endif

// Set real-time spindle output as segment is loaded, just prior to the first step.
Expand Down Expand Up @@ -404,6 +428,46 @@ ISR(TIMER1_COMPA_vect)
else { sys_position[Z_AXIS]++; }
}

#ifdef A_AXIS
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
st.counter_a += st.steps[A_AXIS];
#else
st.counter_a += st.exec_block->steps[A_AXIS];
#endif
if (st.counter_a > st.exec_block->step_event_count) {
st.step_outbits |= (1<<A_STEP_BIT);
st.counter_a -= st.exec_block->step_event_count;
if (st.exec_block->direction_bits & (1<<A_DIRECTION_BIT)) { sys_position[A_AXIS]--; }
else { sys_position[A_AXIS]++; }
}
#endif
#ifdef B_AXIS
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
st.counter_b += st.steps[B_AXIS];
#else
st.counter_b += st.exec_block->steps[B_AXIS];
#endif
if (st.counter_b > st.exec_block->step_event_count) {
st.step_outbits |= (1<<B_STEP_BIT);
st.counter_b -= st.exec_block->step_event_count;
if (st.exec_block->direction_bits & (1<<B_DIRECTION_BIT)) { sys_position[B_AXIS]--; }
else { sys_position[B_AXIS]++; }
}
#endif
#ifdef C_AXIS
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
st.counter_c += st.steps[C_AXIS];
#else
st.counter_c += st.exec_block->steps[C_AXIS];
#endif
if (st.counter_c > st.exec_block->step_event_count) {
st.step_outbits |= (1<<C_STEP_BIT);
st.counter_c -= st.exec_block->step_event_count;
if (st.exec_block->direction_bits & (1<<C_DIRECTION_BIT)) { sys_position[C_AXIS]--; }
else { sys_position[C_AXIS]++; }
}
#endif

// During a homing cycle, lock out and prevent desired axes from moving.
if (sys.state == STATE_HOMING) { st.step_outbits &= sys.homing_axis_lock; }

Expand Down
Loading