New report module. 6 persistent work coordinates. New G-codes and settings. README and minor bug updates
(NOTE: This push is likely buggy so proceed with caution. Just uploading to let people know where we're going.) - New report.c module. Moved all feedback functions into this module to centralize these processes. Includes realtime status reports, status messages, feedback messages. - Official support 6 work coordinate systems (G54-G59), which are persistently held in EEPROM memory. - New g-code support: G28.1, G30.1 stores current machine position as a home position into EEPROM. G10 L20 Px stores current machine position into work coordinates without needing to explicitly send XYZ words. - Homing performed with '$H' command. G28/G30 no longer start the homing cycle. This is how it's supposed to be. - New settings: Stepper enable invert and n_arc correction installed. - Updated and changed up some limits and homing functionality. Pull-off travel will now move after the homing cycle regardless of hard limits enabled. Fixed direction of pull-off travel (went wrong way). - Started on designing an internal Grbl command protocol based on the '$' settings letter. Commands with non numeric characters after '$' will perform switch commands, homing cycle, jogging, printing paramters, etc. Much more to do here. - Updated README to reflect all of the new features.
This commit is contained in:
parent
5d8c3dcbd7
commit
e0a9054e32
4
Makefile
4
Makefile
@ -1,6 +1,7 @@
|
|||||||
# Part of Grbl
|
# Part of Grbl
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009-2011 Simen Svale Skogsrud
|
# Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||||
|
# Copyright (c) 2012 Sungeun K. Jeon
|
||||||
#
|
#
|
||||||
# Grbl is free software: you can redistribute it and/or modify
|
# Grbl is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -31,7 +32,8 @@ DEVICE ?= atmega328p
|
|||||||
CLOCK = 16000000
|
CLOCK = 16000000
|
||||||
PROGRAMMER ?= -c avrisp2 -P usb
|
PROGRAMMER ?= -c avrisp2 -P usb
|
||||||
OBJECTS = main.o motion_control.o gcode.o spindle_control.o coolant_control.o serial.o \
|
OBJECTS = main.o motion_control.o gcode.o spindle_control.o coolant_control.o serial.o \
|
||||||
protocol.o stepper.o eeprom.o settings.o planner.o nuts_bolts.o limits.o print.o
|
protocol.o stepper.o eeprom.o settings.o planner.o nuts_bolts.o limits.o \
|
||||||
|
print.o report.o
|
||||||
# FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
|
# FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
|
||||||
FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m
|
FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m
|
||||||
# update that line with this when programmer is back up:
|
# update that line with this when programmer is back up:
|
||||||
|
23
config.h
23
config.h
@ -80,10 +80,6 @@
|
|||||||
#define CMD_CYCLE_START '~'
|
#define CMD_CYCLE_START '~'
|
||||||
#define CMD_RESET 0x18 // ctrl-x
|
#define CMD_RESET 0x18 // ctrl-x
|
||||||
|
|
||||||
// Specifies the number of work coordinate systems grbl will support (G54 - G59).
|
|
||||||
// This parameter must be one or greater, currently supporting up to a value of 6.
|
|
||||||
#define N_COORDINATE_SYSTEM 1
|
|
||||||
|
|
||||||
// The temporal resolution of the acceleration management subsystem. Higher number give smoother
|
// The temporal resolution of the acceleration management subsystem. Higher number give smoother
|
||||||
// acceleration but may impact performance.
|
// acceleration but may impact performance.
|
||||||
// NOTE: Increasing this parameter will help any resolution related issues, especially with machines
|
// NOTE: Increasing this parameter will help any resolution related issues, especially with machines
|
||||||
@ -106,13 +102,6 @@
|
|||||||
// never reach its target. This parameter should always be greater than zero.
|
// never reach its target. This parameter should always be greater than zero.
|
||||||
#define MINIMUM_STEPS_PER_MINUTE 800 // (steps/min) - Integer value only
|
#define MINIMUM_STEPS_PER_MINUTE 800 // (steps/min) - Integer value only
|
||||||
|
|
||||||
// Number of arc generation iterations by small angle approximation before exact arc trajectory
|
|
||||||
// correction. This parameter maybe decreased if there are issues with the accuracy of the arc
|
|
||||||
// generations. In general, the default value is more than enough for the intended CNC applications
|
|
||||||
// of grbl, and should be on the order or greater than the size of the buffer to help with the
|
|
||||||
// computational efficiency of generating arcs.
|
|
||||||
#define N_ARC_CORRECTION 25 // Integer (1-255)
|
|
||||||
|
|
||||||
// Time delay increments performed during a dwell. The default value is set at 50ms, which provides
|
// Time delay increments performed during a dwell. The default value is set at 50ms, which provides
|
||||||
// a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing
|
// a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing
|
||||||
// this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of
|
// this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of
|
||||||
@ -172,5 +161,17 @@
|
|||||||
// words, the steppers never disable for users that require this.
|
// words, the steppers never disable for users that require this.
|
||||||
// -> NOW INSTALLED IN SETTINGS #define STEPPER_IDLE_LOCK_TIME 25 // (milliseconds) - Integer > 0
|
// -> NOW INSTALLED IN SETTINGS #define STEPPER_IDLE_LOCK_TIME 25 // (milliseconds) - Integer > 0
|
||||||
|
|
||||||
|
// Number of arc generation iterations by small angle approximation before exact arc trajectory
|
||||||
|
// correction. This parameter maybe decreased if there are issues with the accuracy of the arc
|
||||||
|
// generations. In general, the default value is more than enough for the intended CNC applications
|
||||||
|
// of grbl, and should be on the order or greater than the size of the buffer to help with the
|
||||||
|
// computational efficiency of generating arcs.
|
||||||
|
// -> NOW INSTALLED IN SETTINGS #define N_ARC_CORRECTION 25 // Integer (1-255)
|
||||||
|
|
||||||
|
// Specifies the number of work coordinate systems grbl will support (G54 - G59).
|
||||||
|
// This parameter must be one or greater, currently supporting up to a value of 6.
|
||||||
|
// -> NOW CODED INTO SETTINGS.C #define N_COORDINATE_SYSTEM 6
|
||||||
|
|
||||||
|
// TODO: Install compile-time option to send numeric status codes rather than strings.
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
86
gcode.c
86
gcode.c
@ -32,6 +32,7 @@
|
|||||||
#include "coolant_control.h"
|
#include "coolant_control.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
// Define modal group internal numbers for checking multiple command violations and tracking the
|
// Define modal group internal numbers for checking multiple command violations and tracking the
|
||||||
// type of command that is called in the block. A modal group is a group of g-code commands that are
|
// type of command that is called in the block. A modal group is a group of g-code commands that are
|
||||||
@ -64,9 +65,12 @@
|
|||||||
#define NON_MODAL_NONE 0
|
#define NON_MODAL_NONE 0
|
||||||
#define NON_MODAL_DWELL 1 // G4
|
#define NON_MODAL_DWELL 1 // G4
|
||||||
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10
|
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10
|
||||||
#define NON_MODAL_GO_HOME 3 // G28,G30
|
#define NON_MODAL_GO_HOME_0 3 // G28
|
||||||
#define NON_MODAL_SET_COORDINATE_OFFSET 4 // G92
|
#define NON_MODAL_SET_HOME_0 4 // G28.1
|
||||||
#define NON_MODAL_RESET_COORDINATE_OFFSET 5 //G92.1
|
#define NON_MODAL_GO_HOME_1 5 // G30
|
||||||
|
#define NON_MODAL_SET_HOME_1 6 // G30.1
|
||||||
|
#define NON_MODAL_SET_COORDINATE_OFFSET 7 // G92
|
||||||
|
#define NON_MODAL_RESET_COORDINATE_OFFSET 8 //G92.1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t status_code; // Parser status for current block
|
uint8_t status_code; // Parser status for current block
|
||||||
@ -182,22 +186,20 @@ uint8_t gc_execute_line(char *line)
|
|||||||
case 19: select_plane(Y_AXIS, Z_AXIS, X_AXIS); break;
|
case 19: select_plane(Y_AXIS, Z_AXIS, X_AXIS); break;
|
||||||
case 20: gc.inches_mode = true; break;
|
case 20: gc.inches_mode = true; break;
|
||||||
case 21: gc.inches_mode = false; break;
|
case 21: gc.inches_mode = false; break;
|
||||||
case 28: case 30:
|
|
||||||
// NOTE: G28.1, G30.1 sets home position parameters. Not currently supported.
|
// NOTE: G28.1, G30.1 sets home position parameters. Not currently supported.
|
||||||
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
|
case 28: case 30:
|
||||||
non_modal_action = NON_MODAL_GO_HOME;
|
int_value = trunc(10*value); // Multiply by 10 to pick up G92.1
|
||||||
} else {
|
switch(int_value) {
|
||||||
FAIL(STATUS_SETTING_DISABLED);
|
case 280: non_modal_action = NON_MODAL_GO_HOME_0; break;
|
||||||
|
case 281: non_modal_action = NON_MODAL_SET_HOME_0; break;
|
||||||
|
case 300: non_modal_action = NON_MODAL_GO_HOME_1; break;
|
||||||
|
case 301: non_modal_action = NON_MODAL_SET_HOME_1; break;
|
||||||
|
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 53: absolute_override = true; break;
|
case 53: absolute_override = true; break;
|
||||||
case 54: case 55: case 56: case 57: case 58: case 59:
|
case 54: case 55: case 56: case 57: case 58: case 59:
|
||||||
int_value -= 54; // Compute coordinate system row index (0=G54,1=G55,...)
|
sys.coord_select = int_value-54;
|
||||||
if (int_value < N_COORDINATE_SYSTEM) {
|
|
||||||
sys.coord_select = int_value;
|
|
||||||
} else {
|
|
||||||
FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
|
case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
|
||||||
case 90: gc.absolute_mode = true; break;
|
case 90: gc.absolute_mode = true; break;
|
||||||
@ -307,6 +309,13 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// [*M7,M8,M9]: Update coolant state
|
// [*M7,M8,M9]: Update coolant state
|
||||||
coolant_run(gc.coolant_mode);
|
coolant_run(gc.coolant_mode);
|
||||||
|
|
||||||
|
// [G54,G55,...,G59]: Coordinate system selection
|
||||||
|
if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_12)) ) { // Check if called in block
|
||||||
|
float coord_data[N_AXIS];
|
||||||
|
if (!(settings_read_coord_data(sys.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); }
|
||||||
|
memcpy(sys.coord_system,coord_data,sizeof(coord_data));
|
||||||
|
}
|
||||||
|
|
||||||
// [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets.
|
// [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets.
|
||||||
// NOTE: These commands are in the same modal group, hence are mutually exclusive. G53 is in this
|
// NOTE: These commands are in the same modal group, hence are mutually exclusive. G53 is in this
|
||||||
// modal group and do not effect these actions.
|
// modal group and do not effect these actions.
|
||||||
@ -320,30 +329,41 @@ uint8_t gc_execute_line(char *line)
|
|||||||
break;
|
break;
|
||||||
case NON_MODAL_SET_COORDINATE_DATA:
|
case NON_MODAL_SET_COORDINATE_DATA:
|
||||||
int_value = trunc(p); // Convert p value to int.
|
int_value = trunc(p); // Convert p value to int.
|
||||||
if (l != 2 || (int_value < 1 || int_value > N_COORDINATE_SYSTEM)) { // L2 only. P1=G54, P2=G55, ...
|
if ((l != 2 && l != 20) || (int_value < 1 || int_value > N_COORDINATE_SYSTEM)) { // L2 and L20. P1=G54, P2=G55, ...
|
||||||
FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
FAIL(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
} else if (!axis_words) { // No axis words.
|
} else if (!axis_words && l==2) { // No axis words.
|
||||||
FAIL(STATUS_INVALID_STATEMENT);
|
FAIL(STATUS_INVALID_STATEMENT);
|
||||||
} else {
|
} else {
|
||||||
int_value--; // Adjust p to be inline with row array index.
|
int_value--; // Adjust P index to EEPROM coordinate data indexing.
|
||||||
|
if (l == 20) {
|
||||||
|
settings_write_coord_data(int_value,gc.position);
|
||||||
|
// Update system coordinate system if currently active.
|
||||||
|
if (sys.coord_select == int_value) { memcpy(sys.coord_system,gc.position,sizeof(gc.position)); }
|
||||||
|
} else {
|
||||||
|
float coord_data[N_AXIS];
|
||||||
|
if (!settings_read_coord_data(int_value,coord_data)) { return(STATUS_SETTING_READ_FAIL); }
|
||||||
// Update axes defined only in block. Always in machine coordinates. Can change non-active system.
|
// Update axes defined only in block. Always in machine coordinates. Can change non-active system.
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
|
for (i=0; i<N_AXIS; i++) { // Axes indices are consistent, so loop may be used.
|
||||||
if ( bit_istrue(axis_words,bit(i)) ) { sys.coord_system[int_value][i] = target[i]; }
|
if ( bit_istrue(axis_words,bit(i)) ) { coord_data[i] = target[i]; }
|
||||||
|
}
|
||||||
|
settings_write_coord_data(int_value,coord_data);
|
||||||
|
// Update system coordinate system if currently active.
|
||||||
|
if (sys.coord_select == int_value) { memcpy(sys.coord_system,coord_data,sizeof(coord_data)); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
|
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
|
||||||
break;
|
break;
|
||||||
case NON_MODAL_GO_HOME:
|
case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1:
|
||||||
// Move to intermediate position before going home. Obeys current coordinate system and offsets
|
// Move to intermediate position before going home. Obeys current coordinate system and offsets
|
||||||
// and absolute and incremental modes.
|
// and absolute and incremental modes.
|
||||||
if (axis_words) {
|
if (axis_words) {
|
||||||
// Apply absolute mode coordinate offsets or incremental mode offsets.
|
// Apply absolute mode coordinate offsets or incremental mode offsets.
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
|
for (i=0; i<N_AXIS; i++) { // Axes indices are consistent, so loop may be used.
|
||||||
if ( bit_istrue(axis_words,bit(i)) ) {
|
if ( bit_istrue(axis_words,bit(i)) ) {
|
||||||
if (gc.absolute_mode) {
|
if (gc.absolute_mode) {
|
||||||
target[i] += sys.coord_system[sys.coord_select][i] + sys.coord_offset[i];
|
target[i] += sys.coord_system[i] + sys.coord_offset[i];
|
||||||
} else {
|
} else {
|
||||||
target[i] += gc.position[i];
|
target[i] += gc.position[i];
|
||||||
}
|
}
|
||||||
@ -353,9 +373,19 @@ uint8_t gc_execute_line(char *line)
|
|||||||
}
|
}
|
||||||
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false);
|
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false);
|
||||||
}
|
}
|
||||||
mc_go_home();
|
// Retreive G28/30 go-home position data (in machine coordinates) from EEPROM
|
||||||
|
float coord_data[N_AXIS];
|
||||||
|
uint8_t home_select = SETTING_INDEX_G28;
|
||||||
|
if (non_modal_action == NON_MODAL_GO_HOME_1) { home_select = SETTING_INDEX_G30; }
|
||||||
|
if (!settings_read_coord_data(home_select,coord_data)) { return(STATUS_SETTING_READ_FAIL); }
|
||||||
|
mc_line(coord_data[X_AXIS], coord_data[Y_AXIS], coord_data[Z_AXIS], settings.default_seek_rate, false);
|
||||||
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
|
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
|
||||||
break;
|
break;
|
||||||
|
case NON_MODAL_SET_HOME_0: case NON_MODAL_SET_HOME_1:
|
||||||
|
home_select = SETTING_INDEX_G28;
|
||||||
|
if (non_modal_action == NON_MODAL_SET_HOME_1) { home_select = SETTING_INDEX_G30; }
|
||||||
|
settings_write_coord_data(home_select,gc.position);
|
||||||
|
break;
|
||||||
case NON_MODAL_SET_COORDINATE_OFFSET:
|
case NON_MODAL_SET_COORDINATE_OFFSET:
|
||||||
if (!axis_words) { // No axis words
|
if (!axis_words) { // No axis words
|
||||||
FAIL(STATUS_INVALID_STATEMENT);
|
FAIL(STATUS_INVALID_STATEMENT);
|
||||||
@ -365,7 +395,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
|
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
|
||||||
if (bit_istrue(axis_words,bit(i)) ) {
|
if (bit_istrue(axis_words,bit(i)) ) {
|
||||||
sys.coord_offset[i] = gc.position[i]-sys.coord_system[sys.coord_select][i]-target[i];
|
sys.coord_offset[i] = gc.position[i]-sys.coord_system[i]-target[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,7 +432,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
if ( bit_istrue(axis_words,bit(i)) ) {
|
if ( bit_istrue(axis_words,bit(i)) ) {
|
||||||
if (!absolute_override) { // Do not update target in absolute override mode
|
if (!absolute_override) { // Do not update target in absolute override mode
|
||||||
if (gc.absolute_mode) {
|
if (gc.absolute_mode) {
|
||||||
target[i] += sys.coord_system[sys.coord_select][i] + sys.coord_offset[i]; // Absolute mode
|
target[i] += sys.coord_system[i] + sys.coord_offset[i]; // Absolute mode
|
||||||
} else {
|
} else {
|
||||||
target[i] += gc.position[i]; // Incremental mode
|
target[i] += gc.position[i]; // Incremental mode
|
||||||
}
|
}
|
||||||
@ -421,6 +451,10 @@ uint8_t gc_execute_line(char *line)
|
|||||||
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false); }
|
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false); }
|
||||||
break;
|
break;
|
||||||
case MOTION_MODE_LINEAR:
|
case MOTION_MODE_LINEAR:
|
||||||
|
// TODO: Inverse time requires F-word with each statement. Need to do a check. Also need
|
||||||
|
// to check for initial F-word upon startup. Maybe just set to zero upon initialization
|
||||||
|
// and after an inverse time move and then check for non-zero feed rate each time. This
|
||||||
|
// should be efficient and effective.
|
||||||
if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
|
if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
|
||||||
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
|
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
|
||||||
(gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); }
|
(gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); }
|
||||||
@ -546,7 +580,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// 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
|
||||||
// in any intermediate location.
|
// in any intermediate location.
|
||||||
memcpy(gc.position, target, sizeof(float)*3); // gc.position[] = target[];
|
memcpy(gc.position, target, sizeof(target)); // gc.position[] = target[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
|
// M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
|
||||||
|
16
limits.c
16
limits.c
@ -31,6 +31,7 @@
|
|||||||
#include "planner.h"
|
#include "planner.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
#define MICROSECONDS_PER_ACCELERATION_TICK (1000000/ACCELERATION_TICKS_PER_SECOND)
|
#define MICROSECONDS_PER_ACCELERATION_TICK (1000000/ACCELERATION_TICKS_PER_SECOND)
|
||||||
|
|
||||||
@ -50,6 +51,11 @@ void limits_init()
|
|||||||
// homing cycles and will not respond correctly. Upon user request or need, there may be a
|
// homing cycles and will not respond correctly. Upon user request or need, there may be a
|
||||||
// special pinout for an e-stop, but it is generally recommended to just directly connect
|
// special pinout for an e-stop, but it is generally recommended to just directly connect
|
||||||
// your e-stop switch to the Arduino reset pin, since it is the most correct way to do this.
|
// your e-stop switch to the Arduino reset pin, since it is the most correct way to do this.
|
||||||
|
// TODO: This interrupt may be used to manage the homing cycle directly with the main stepper
|
||||||
|
// interrupt without adding too much to it. All it would need is some way to stop one axis
|
||||||
|
// when its limit is triggered and continue the others. This may reduce some of the code, but
|
||||||
|
// would make Grbl a little harder to read and understand down road. Holding off on this until
|
||||||
|
// we move on to new hardware or flash space becomes an issue. If it ain't broke, don't fix it.
|
||||||
ISR(LIMIT_INT_vect)
|
ISR(LIMIT_INT_vect)
|
||||||
{
|
{
|
||||||
// Only enter if the system alarm is not active.
|
// Only enter if the system alarm is not active.
|
||||||
@ -57,13 +63,8 @@ ISR(LIMIT_INT_vect)
|
|||||||
// Kill all processes upon hard limit event.
|
// Kill all processes upon hard limit event.
|
||||||
if ((LIMIT_PIN & LIMIT_MASK) ^ LIMIT_MASK) {
|
if ((LIMIT_PIN & LIMIT_MASK) ^ LIMIT_MASK) {
|
||||||
mc_alarm(); // Initiate system kill.
|
mc_alarm(); // Initiate system kill.
|
||||||
protocol_status_message(STATUS_HARD_LIMIT); // Print ok in interrupt since system killed.
|
report_status_message(STATUS_HARD_LIMIT); // Print ok in interrupt since system killed.
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// TODO: When leaving a switch, this interrupt can be activated upon detecting a pin
|
|
||||||
// change to high. If so, need to start a countdown timer to check the pin again after
|
|
||||||
// a debounce period to not falsely re-engage the alarm. Not essential, but *could* be
|
|
||||||
// a minor annoyance.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +191,8 @@ static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir,
|
|||||||
|
|
||||||
void limits_go_home()
|
void limits_go_home()
|
||||||
{
|
{
|
||||||
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); // Enable steppers, but not the cycle.
|
// Enable only the steppers, not the cycle. Cycle should be complete.
|
||||||
|
st_wake_up();
|
||||||
|
|
||||||
// Jog all axes toward home to engage their limit switches at faster homing seek rate.
|
// Jog all axes toward home to engage their limit switches at faster homing seek rate.
|
||||||
homing_cycle(false, false, true, true, false, settings.homing_seek_rate); // First jog the z axis
|
homing_cycle(false, false, true, true, false, settings.homing_seek_rate); // First jog the z axis
|
||||||
|
7
main.c
7
main.c
@ -35,6 +35,7 @@
|
|||||||
#include "gcode.h"
|
#include "gcode.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
|
#include "report.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
@ -68,9 +69,8 @@ int main(void)
|
|||||||
// releases will auto-reset the machine position back to [0,0,0] if an abort is used while
|
// releases will auto-reset the machine position back to [0,0,0] if an abort is used while
|
||||||
// grbl is moving the machine.
|
// grbl is moving the machine.
|
||||||
int32_t last_position[3];
|
int32_t last_position[3];
|
||||||
float last_coord_system[N_COORDINATE_SYSTEM][3];
|
|
||||||
memcpy(last_position, sys.position, sizeof(sys.position)); // last_position[] = sys.position[]
|
memcpy(last_position, sys.position, sizeof(sys.position)); // last_position[] = sys.position[]
|
||||||
memcpy(last_coord_system, sys.coord_system, sizeof(sys.coord_system)); // last_coord_system[] = sys.coord_system[]
|
// TODO: Last coordinate system method.
|
||||||
|
|
||||||
// Reset system.
|
// Reset system.
|
||||||
memset(&sys, 0, sizeof(sys)); // Clear all system variables
|
memset(&sys, 0, sizeof(sys)); // Clear all system variables
|
||||||
@ -86,7 +86,6 @@ int main(void)
|
|||||||
|
|
||||||
// Reload last known machine position and work systems. G92 coordinate offsets are reset.
|
// Reload last known machine position and work systems. G92 coordinate offsets are reset.
|
||||||
memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[]
|
memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[]
|
||||||
memcpy(sys.coord_system, last_coord_system, sizeof(last_coord_system)); // sys.coord_system[] = last_coord_system[]
|
|
||||||
gc_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
|
gc_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
|
||||||
plan_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
|
plan_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
|
||||||
|
|
||||||
@ -97,6 +96,8 @@ int main(void)
|
|||||||
sys.auto_start = true;
|
sys.auto_start = true;
|
||||||
}
|
}
|
||||||
// TODO: Install G20/G21 unit default into settings and load appropriate settings.
|
// TODO: Install G20/G21 unit default into settings and load appropriate settings.
|
||||||
|
|
||||||
|
report_init_message();
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol_execute_runtime();
|
protocol_execute_runtime();
|
||||||
|
@ -110,7 +110,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
|
|||||||
float linear_per_segment = linear_travel/segments;
|
float linear_per_segment = linear_travel/segments;
|
||||||
|
|
||||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||||
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
and phi is the angle of rotation. Solution approach by Jens Geisler.
|
||||||
r_T = [cos(phi) -sin(phi);
|
r_T = [cos(phi) -sin(phi);
|
||||||
sin(phi) cos(phi] * r ;
|
sin(phi) cos(phi] * r ;
|
||||||
|
|
||||||
@ -150,14 +150,14 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
|
|||||||
|
|
||||||
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
||||||
|
|
||||||
if (count < N_ARC_CORRECTION) {
|
if (count < settings.n_arc_correction) {
|
||||||
// Apply vector rotation matrix
|
// Apply vector rotation matrix
|
||||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
||||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
||||||
r_axis1 = r_axisi;
|
r_axis1 = r_axisi;
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
// Arc correction to radius vector. Computed only every n_arc_correction increments.
|
||||||
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
||||||
cos_Ti = cos(i*theta_per_segment);
|
cos_Ti = cos(i*theta_per_segment);
|
||||||
sin_Ti = sin(i*theta_per_segment);
|
sin_Ti = sin(i*theta_per_segment);
|
||||||
@ -200,30 +200,33 @@ void mc_go_home()
|
|||||||
{
|
{
|
||||||
plan_synchronize(); // Empty all motions in buffer before homing.
|
plan_synchronize(); // Empty all motions in buffer before homing.
|
||||||
PCICR &= ~(1 << LIMIT_INT); // Disable hard limits pin change interrupt
|
PCICR &= ~(1 << LIMIT_INT); // Disable hard limits pin change interrupt
|
||||||
|
plan_clear_position();
|
||||||
|
|
||||||
limits_go_home(); // Perform homing routine.
|
limits_go_home(); // Perform homing routine.
|
||||||
|
|
||||||
// Upon completion, reset all internal position vectors (g-code parser, planner, system)
|
// The machine should now be homed and machine zero has been located. Upon completion,
|
||||||
gc_clear_position();
|
// reset planner and system internal position vectors, but not gcode parser position yet.
|
||||||
plan_clear_position();
|
plan_clear_position();
|
||||||
clear_vector_float(sys.position);
|
clear_vector_float(sys.position);
|
||||||
|
|
||||||
// If hard limits enabled, move all axes off limit switches before enabling the hard limit
|
// Pull-off all axes from limit switches before continuing motion. This provides some initial
|
||||||
// pin change interrupt. This should help prevent the switches from falsely tripping.
|
// clearance off the switches and should also help prevent them from falsely tripping when
|
||||||
// NOTE: G-code parser was circumvented so its position needs to be updated explicitly.
|
// hard limits are enabled.
|
||||||
if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {
|
|
||||||
int8_t x_dir, y_dir, z_dir;
|
int8_t x_dir, y_dir, z_dir;
|
||||||
x_dir = y_dir = z_dir = 1;
|
x_dir = y_dir = z_dir = -1;
|
||||||
if (bit_istrue(settings.homing_dir_mask,bit(X_DIRECTION_BIT))) { x_dir = -1; }
|
if (bit_istrue(settings.homing_dir_mask,bit(X_DIRECTION_BIT))) { x_dir = 1; }
|
||||||
if (bit_istrue(settings.homing_dir_mask,bit(Y_DIRECTION_BIT))) { y_dir = -1; }
|
if (bit_istrue(settings.homing_dir_mask,bit(Y_DIRECTION_BIT))) { y_dir = 1; }
|
||||||
if (bit_istrue(settings.homing_dir_mask,bit(Z_DIRECTION_BIT))) { z_dir = -1; }
|
if (bit_istrue(settings.homing_dir_mask,bit(Z_DIRECTION_BIT))) { z_dir = 1; }
|
||||||
mc_line(x_dir*settings.homing_pulloff, y_dir*settings.homing_pulloff,
|
mc_line(x_dir*settings.homing_pulloff, y_dir*settings.homing_pulloff,
|
||||||
z_dir*settings.homing_pulloff, settings.homing_feed_rate, false);
|
z_dir*settings.homing_pulloff, settings.homing_feed_rate, false);
|
||||||
st_cycle_start(); // Move it. Nothing should be in the buffer except this motion.
|
st_cycle_start(); // Move it. Nothing should be in the buffer except this motion.
|
||||||
plan_synchronize(); // Make sure the motion completes.
|
plan_synchronize(); // Make sure the motion completes.
|
||||||
|
|
||||||
|
// Explicitly update the gcode parser position since it was circumvented by the pull-off maneuver.
|
||||||
gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]);
|
gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]);
|
||||||
PCICR |= (1 << LIMIT_INT); // Re-enable hard limits.
|
|
||||||
}
|
// If hard limits feature enabled, re-enable hard limits interrupt after homing cycle.
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { PCICR |= (1 << LIMIT_INT); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -234,12 +237,8 @@ void mc_alarm()
|
|||||||
// Only this function can set the system alarm. This is done to prevent multiple kill calls
|
// Only this function can set the system alarm. This is done to prevent multiple kill calls
|
||||||
// by different processes.
|
// by different processes.
|
||||||
if (bit_isfalse(sys.execute, EXEC_ALARM)) {
|
if (bit_isfalse(sys.execute, EXEC_ALARM)) {
|
||||||
sys.execute |= EXEC_ALARM; // Set alarm to allow subsystem disable for certain settings.
|
// Set system alarm flag.
|
||||||
sys.auto_start = false; // Disable auto cycle start.
|
sys.execute |= EXEC_ALARM;
|
||||||
|
|
||||||
// TODO: When Grbl system status is installed, set position lost state if the cycle is active.
|
|
||||||
// if (sys.cycle_start) { POSITION LOST }
|
|
||||||
|
|
||||||
// Immediately force stepper, spindle, and coolant to stop.
|
// Immediately force stepper, spindle, and coolant to stop.
|
||||||
st_go_idle();
|
st_go_idle();
|
||||||
spindle_stop();
|
spindle_stop();
|
||||||
|
17
nuts_bolts.h
17
nuts_bolts.h
@ -30,7 +30,8 @@
|
|||||||
#define false 0
|
#define false 0
|
||||||
#define true 1
|
#define true 1
|
||||||
|
|
||||||
#define X_AXIS 0
|
#define N_AXIS 3 // Number of axes
|
||||||
|
#define X_AXIS 0 // Axis indexing value
|
||||||
#define Y_AXIS 1
|
#define Y_AXIS 1
|
||||||
#define Z_AXIS 2
|
#define Z_AXIS 2
|
||||||
|
|
||||||
@ -39,7 +40,7 @@
|
|||||||
|
|
||||||
// Useful macros
|
// Useful macros
|
||||||
#define clear_vector(a) memset(a, 0, sizeof(a))
|
#define clear_vector(a) memset(a, 0, sizeof(a))
|
||||||
#define clear_vector_float(a) memset(a, 0.0, sizeof(a))
|
#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*3)
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
@ -75,6 +76,11 @@
|
|||||||
// #define bit(6)
|
// #define bit(6)
|
||||||
// #define bit(7)
|
// #define bit(7)
|
||||||
|
|
||||||
|
// Define Grbl system states for sys.state
|
||||||
|
|
||||||
|
// Define position lost in states?
|
||||||
|
|
||||||
|
|
||||||
// Define global system variables
|
// Define global system variables
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
|
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
|
||||||
@ -86,10 +92,9 @@ typedef struct {
|
|||||||
// NOTE: This may need to be a volatile variable, if problems arise.
|
// NOTE: This may need to be a volatile variable, if problems arise.
|
||||||
|
|
||||||
uint8_t coord_select; // Active work coordinate system number. Default: 0=G54.
|
uint8_t coord_select; // Active work coordinate system number. Default: 0=G54.
|
||||||
float coord_system[N_COORDINATE_SYSTEM][3]; // Work coordinate systems (G54+). Stores offset from
|
float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine
|
||||||
// absolute machine position in mm.
|
// position in mm. Loaded from EEPROM when called.
|
||||||
// Rows: Work system number (0=G54,1=G55,...5=G59), Columns: XYZ Offsets
|
float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to
|
||||||
float coord_offset[3]; // Retains the G92 coordinate offset (work coordinates) relative to
|
|
||||||
// machine zero in mm.
|
// machine zero in mm.
|
||||||
|
|
||||||
volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program.
|
volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program.
|
||||||
|
249
protocol.c
249
protocol.c
@ -31,124 +31,16 @@
|
|||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include "stepper.h"
|
#include "stepper.h"
|
||||||
#include "planner.h"
|
#include "planner.h"
|
||||||
|
#include "report.h"
|
||||||
|
#include "motion_control.h"
|
||||||
|
|
||||||
static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
|
static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
|
||||||
static uint8_t char_counter; // Last character counter in line variable.
|
static uint8_t char_counter; // Last character counter in line variable.
|
||||||
static uint8_t iscomment; // Comment/block delete flag for processor to ignore comment characters.
|
static uint8_t iscomment; // Comment/block delete flag for processor to ignore comment characters.
|
||||||
|
|
||||||
// Method to handle status messages, from an 'ok' to report any 'error' that has occurred.
|
|
||||||
// Errors can originate from the g-code parser, settings module, or a critical error, such
|
|
||||||
// as a triggered hard limit.
|
|
||||||
void protocol_status_message(uint8_t status_code)
|
|
||||||
{
|
|
||||||
// TODO: Compile time option to only return numeric codes for GUIs.
|
|
||||||
if (status_code == 0) { // STATUS_OK
|
|
||||||
printPgmString(PSTR("ok\r\n"));
|
|
||||||
} else {
|
|
||||||
printPgmString(PSTR("error: "));
|
|
||||||
switch(status_code) {
|
|
||||||
case STATUS_BAD_NUMBER_FORMAT:
|
|
||||||
printPgmString(PSTR("Bad number format")); break;
|
|
||||||
case STATUS_EXPECTED_COMMAND_LETTER:
|
|
||||||
printPgmString(PSTR("Expected command letter")); break;
|
|
||||||
case STATUS_UNSUPPORTED_STATEMENT:
|
|
||||||
printPgmString(PSTR("Unsupported statement")); break;
|
|
||||||
case STATUS_FLOATING_POINT_ERROR:
|
|
||||||
printPgmString(PSTR("Floating point error")); break;
|
|
||||||
case STATUS_MODAL_GROUP_VIOLATION:
|
|
||||||
printPgmString(PSTR("Modal group violation")); break;
|
|
||||||
case STATUS_INVALID_STATEMENT:
|
|
||||||
printPgmString(PSTR("Invalid statement")); break;
|
|
||||||
case STATUS_HARD_LIMIT:
|
|
||||||
printPgmString(PSTR("Limit triggered")); break;
|
|
||||||
case STATUS_SETTING_DISABLED:
|
|
||||||
printPgmString(PSTR("Grbl setting disabled")); break;
|
|
||||||
case STATUS_SETTING_STEPS_NEG:
|
|
||||||
printPgmString(PSTR("Steps/mm must be > 0.0")); break;
|
|
||||||
case STATUS_SETTING_STEP_PULSE_MIN:
|
|
||||||
printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break;
|
|
||||||
case STATUS_SETTING_READ_FAIL:
|
|
||||||
printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break;
|
|
||||||
}
|
|
||||||
printPgmString(PSTR("\r\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Prints miscellaneous messages. This serves as a centralized method to provide additional
|
|
||||||
// user feedback for things that do not pass through the protocol_execute_line() function
|
|
||||||
// and are not errors or confirmations, such as setup warnings and how to exit alarms.
|
|
||||||
void protocol_misc_message(uint8_t message_code)
|
|
||||||
{
|
|
||||||
// TODO: Install silence misc messages option in settings
|
|
||||||
switch(message_code) {
|
|
||||||
case MESSAGE_SYSTEM_ALARM:
|
|
||||||
printPgmString(PSTR("<ALARM: Reset to continue>")); break;
|
|
||||||
case MESSAGE_HOMING_ENABLE:
|
|
||||||
printPgmString(PSTR("warning: Install all axes limit switches before use")); break;
|
|
||||||
}
|
|
||||||
printPgmString(PSTR("\r\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void protocol_status_report()
|
|
||||||
{
|
|
||||||
// TODO: Status report data is written to the user here. This function should be able to grab a
|
|
||||||
// real-time snapshot of the stepper subprogram and the actual location of the CNC machine. At a
|
|
||||||
// minimum, status report should return real-time location information. Other important information
|
|
||||||
// may be distance to go on block, processed block id, and feed rate. A secondary, non-critical
|
|
||||||
// status report may include g-code state, i.e. inch mode, plane mode, absolute mode, etc.
|
|
||||||
// The report generated must be as short as possible, yet still provide the user easily readable
|
|
||||||
// information, i.e. '[0.23,120.4,2.4]'. This is necessary as it minimizes the computational
|
|
||||||
// overhead and allows grbl to keep running smoothly, especially with g-code programs with fast,
|
|
||||||
// short line segments and interface setups that require real-time status reports (5-20Hz).
|
|
||||||
|
|
||||||
// **Under construction** Bare-bones status report. Provides real-time machine position relative to
|
|
||||||
// the system power on location (0,0,0) and work coordinate position (G54 and G92 applied).
|
|
||||||
// The following are still needed: user setting of output units (mm|inch), compressed (non-human
|
|
||||||
// readable) data for interfaces?, save last known position in EEPROM?, code optimizations, solidify
|
|
||||||
// the reporting schemes, move to a separate .c file for easy user accessibility, and setting the
|
|
||||||
// home position by the user (likely through '$' setting interface).
|
|
||||||
// Successfully tested at a query rate of 10-20Hz while running a gauntlet of programs at various
|
|
||||||
// speeds.
|
|
||||||
uint8_t i;
|
|
||||||
int32_t current_position[3]; // Copy current state of the system position variable
|
|
||||||
memcpy(current_position,sys.position,sizeof(sys.position));
|
|
||||||
float print_position[3];
|
|
||||||
|
|
||||||
// Report machine position
|
|
||||||
printPgmString(PSTR("MPos:["));
|
|
||||||
for (i=0; i<= 2; i++) {
|
|
||||||
print_position[i] = current_position[i]/settings.steps_per_mm[i];
|
|
||||||
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
|
|
||||||
printFloat(print_position[i]);
|
|
||||||
if (i < 2) { printPgmString(PSTR(",")); }
|
|
||||||
else { printPgmString(PSTR("]")); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report work position
|
|
||||||
printPgmString(PSTR(",WPos:["));
|
|
||||||
for (i=0; i<= 2; i++) {
|
|
||||||
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
|
|
||||||
print_position[i] -= (sys.coord_system[sys.coord_select][i]+sys.coord_offset[i])*INCH_PER_MM;
|
|
||||||
} else {
|
|
||||||
print_position[i] -= sys.coord_system[sys.coord_select][i]+sys.coord_offset[i];
|
|
||||||
}
|
|
||||||
printFloat(print_position[i]);
|
|
||||||
if (i < 2) { printPgmString(PSTR(",")); }
|
|
||||||
else { printPgmString(PSTR("]")); }
|
|
||||||
}
|
|
||||||
|
|
||||||
printPgmString(PSTR("\r\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void protocol_init()
|
void protocol_init()
|
||||||
{
|
{
|
||||||
// Print grbl initialization message
|
|
||||||
printPgmString(PSTR("\r\nGrbl " GRBL_VERSION));
|
|
||||||
printPgmString(PSTR("\r\n'$' to dump current settings\r\n"));
|
|
||||||
|
|
||||||
char_counter = 0; // Reset line input
|
char_counter = 0; // Reset line input
|
||||||
iscomment = false;
|
iscomment = false;
|
||||||
}
|
}
|
||||||
@ -160,29 +52,43 @@ void protocol_init()
|
|||||||
// This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code
|
// This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code
|
||||||
// parsing and planning functions. This function also serves as an interface for the interrupts to
|
// parsing and planning functions. This function also serves as an interface for the interrupts to
|
||||||
// set the system runtime flags, where only the main program handles them, removing the need to
|
// set the system runtime flags, where only the main program handles them, removing the need to
|
||||||
// define more computationally-expensive volatile variables.
|
// define more computationally-expensive volatile variables. This also provides a controlled way to
|
||||||
// NOTE: The sys.execute variable flags are set by the serial read subprogram, except where noted.
|
// execute certain tasks without having two or more instances of the same task, such as the planner
|
||||||
|
// recalculating the buffer upon a feedhold or override.
|
||||||
|
// NOTE: The sys.execute variable flags are set by the serial read subprogram, except where noted,
|
||||||
|
// but may be set by any process, such as a switch pin change interrupt when pinouts are installed.
|
||||||
void protocol_execute_runtime()
|
void protocol_execute_runtime()
|
||||||
{
|
{
|
||||||
if (sys.execute) { // Enter only if any bit flag is true
|
if (sys.execute) { // Enter only if any bit flag is true
|
||||||
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
|
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
|
||||||
|
|
||||||
// System alarm. Something has gone wrong. Disable everything until system reset.
|
// System alarm. Something has gone wrong. Disable everything by entering an infinite
|
||||||
|
// loop until system reset/abort.
|
||||||
if (rt_exec & EXEC_ALARM) {
|
if (rt_exec & EXEC_ALARM) {
|
||||||
if (bit_isfalse(sys.execute,EXEC_RESET)) { protocol_misc_message(MESSAGE_SYSTEM_ALARM); }
|
if (bit_isfalse(rt_exec,EXEC_RESET)) { // Ignore loop if reset is already issued
|
||||||
|
report_feedback_message(MESSAGE_SYSTEM_ALARM);
|
||||||
while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); }
|
while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); }
|
||||||
|
}
|
||||||
bit_false(sys.execute,EXEC_ALARM);
|
bit_false(sys.execute,EXEC_ALARM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// System abort. Steppers have already been force stopped.
|
// System abort. Steppers have already been force stopped.
|
||||||
if (rt_exec & EXEC_RESET) {
|
if (rt_exec & EXEC_RESET) {
|
||||||
sys.abort = true;
|
sys.abort = true;
|
||||||
|
|
||||||
|
// If the cycle is active before killing the motion, the event will likely caused a loss
|
||||||
|
// of position since there is no controlled deceleration(feed hold) to a stop.
|
||||||
|
// TODO: Add force home option upon position lost. Need to verify that cycle start isn't
|
||||||
|
// set false by anything but the stepper module. Also, need to look at a better place for
|
||||||
|
// this. Main.c?
|
||||||
|
// if (sys.cycle_start) { protocol_feedback_message(MESSAGE_POSITION_LOST); }
|
||||||
|
|
||||||
return; // Nothing else to do but exit.
|
return; // Nothing else to do but exit.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute and serial print status
|
// Execute and serial print status
|
||||||
if (rt_exec & EXEC_STATUS_REPORT) {
|
if (rt_exec & EXEC_STATUS_REPORT) {
|
||||||
protocol_status_report();
|
report_realtime_status();
|
||||||
bit_false(sys.execute,EXEC_STATUS_REPORT);
|
bit_false(sys.execute,EXEC_STATUS_REPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,40 +113,94 @@ void protocol_execute_runtime()
|
|||||||
bit_false(sys.execute,EXEC_CYCLE_START);
|
bit_false(sys.execute,EXEC_CYCLE_START);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overrides flag byte (sys.override) and execution should be installed here, since they
|
||||||
|
// are runtime and require a direct and controlled interface to the main stepper program.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Executes one line of input according to protocol
|
// Directs and executes one line of formatted input from protocol_process. While mostly
|
||||||
|
// incoming streaming g-code blocks, this also executes Grbl internal commands, such as
|
||||||
|
// settings, initiating the homing cycle, and toggling switch states. This differs from
|
||||||
|
// the runtime command module by being susceptible to when Grbl is ready to execute the
|
||||||
|
// next line during a cycle, so for switches like block delete, the switch only effects
|
||||||
|
// the lines that are processed afterward, not necessarily real-time during a cycle,
|
||||||
|
// since there are motions already stored in the buffer. However, this 'lag' should not
|
||||||
|
// be an issue, since these commands are not typically used during a cycle.
|
||||||
uint8_t protocol_execute_line(char *line)
|
uint8_t protocol_execute_line(char *line)
|
||||||
{
|
{
|
||||||
|
// Grbl internal command and parameter lines are of the form '$4=374.3' or '$' for help
|
||||||
if(line[0] == '$') {
|
if(line[0] == '$') {
|
||||||
|
|
||||||
// TODO: Re-write this '$' as a way to change runtime settings without having to reset, i.e.
|
uint8_t char_counter = 1;
|
||||||
// auto-starting, status query output formatting and type, jog mode (axes, direction, and
|
float parameter, value;
|
||||||
// nominal feedrate), toggle block delete, etc. This differs from the EEPROM settings, as they
|
switch( line[char_counter] ) {
|
||||||
// are considered defaults and loaded upon startup/reset.
|
case 0 :
|
||||||
// This use is envisioned where '$' itself dumps settings and help. Defined characters
|
report_grbl_help();
|
||||||
// proceeding the '$' may be used to setup modes, such as jog mode with a '$J=X100' for X-axis
|
return(STATUS_OK);
|
||||||
// motion with a nominal feedrate of 100mm/min. Writing EEPROM settings will likely stay the
|
break;
|
||||||
// same or similar. Should be worked out in upcoming releases.
|
// case '#' :
|
||||||
return(settings_execute_line(line)); // Delegate lines starting with '$' to the settings module
|
// if ( line[++char_counter] == 0 ) {
|
||||||
|
// // Print all parameters
|
||||||
// } else if {
|
// return(STATUS_OK);
|
||||||
|
// } else {
|
||||||
|
// return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
|
// }
|
||||||
|
// case 'G' : // Start up blocks
|
||||||
|
// if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_BAD_NUMBER_FORMAT); }
|
||||||
|
// if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); }
|
||||||
|
// // Extract startup block, execute, and store.
|
||||||
|
// for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) {
|
||||||
|
// line[char_counter] = line[char_counter+3];
|
||||||
|
// }
|
||||||
|
// uint8_t status = gc_execute_line(line);
|
||||||
|
// if (status) { return(status); }
|
||||||
|
// else { settings_store_startup_block(line); }
|
||||||
|
// break;
|
||||||
|
case 'H' : // Perform homing cycle
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
|
||||||
|
mc_go_home();
|
||||||
|
return(STATUS_OK);
|
||||||
|
} else {
|
||||||
|
return(STATUS_SETTING_DISABLED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// // case 'J' : break; // Jogging methods
|
||||||
|
// // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be
|
||||||
|
// // susceptible to other runtime commands except for e-stop. The jogging function is intended to
|
||||||
|
// // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped
|
||||||
|
// // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would
|
||||||
|
// // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the
|
||||||
|
// // motion by repeatedly toggling to slow the motion to the desired location. Location data would
|
||||||
|
// // need to be updated real-time and supplied to the user through status queries.
|
||||||
|
// // More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are
|
||||||
|
// // handled by the planner. It would be possible for the jog subprogram to insert blocks into the
|
||||||
|
// // block buffer without having the planner plan them. It would need to manage de/ac-celerations
|
||||||
|
// // on its own carefully. This approach could be effective and possibly size/memory efficient.
|
||||||
|
// case 'P' : // Print g-code parameters and parser state
|
||||||
|
// if(line[char_counter] != 0) { return(STATUS_UNSUPPORTED_STATEMENT); }
|
||||||
//
|
//
|
||||||
// JOG MODE
|
// break;
|
||||||
//
|
// case 'S' : // Switch methods
|
||||||
// TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be
|
// // Opt stop and block delete are referred to as switches.
|
||||||
// susceptible to other runtime commands except for e-stop. The jogging function is intended to
|
// // How to store home position and work offsets real-time??
|
||||||
// be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped
|
// break;
|
||||||
// steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would
|
// // Parse $parameter=value settings
|
||||||
// start motion and toggle off would initiate a deceleration to stop. One could 'feather' the
|
default :
|
||||||
// motion by repeatedly toggling to slow the motion to the desired location. Location data would
|
if(!read_float(line, &char_counter, ¶meter)) {
|
||||||
// need to be updated real-time and supplied to the user through status queries.
|
return(STATUS_BAD_NUMBER_FORMAT);
|
||||||
// More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are
|
}
|
||||||
// handled by the planner. It would be possible for the jog subprogram to insert blocks into the
|
if(line[char_counter++] != '=') {
|
||||||
// block buffer without having the planner plan them. It would need to manage de/ac-celerations
|
return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
// on its own carefully. This approach could be effective and possibly size/memory efficient.
|
}
|
||||||
|
if(!read_float(line, &char_counter, &value)) {
|
||||||
|
return(STATUS_BAD_NUMBER_FORMAT);
|
||||||
|
}
|
||||||
|
if(line[char_counter] != 0) {
|
||||||
|
return(STATUS_UNSUPPORTED_STATEMENT);
|
||||||
|
}
|
||||||
|
return(settings_store_global_setting(parameter, value));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return(gc_execute_line(line)); // Everything else is gcode
|
return(gc_execute_line(line)); // Everything else is gcode
|
||||||
// TODO: Install option to set system alarm upon any error code received back from the
|
// TODO: Install option to set system alarm upon any error code received back from the
|
||||||
@ -250,7 +210,8 @@ uint8_t protocol_execute_line(char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Process one line of incoming serial data. Remove unneeded characters and capitalize.
|
// Process and report status one line of incoming serial data. Performs an initial filtering
|
||||||
|
// by removing spaces and comments and capitalizing all letters.
|
||||||
void protocol_process()
|
void protocol_process()
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
@ -265,10 +226,10 @@ void protocol_process()
|
|||||||
|
|
||||||
if (char_counter > 0) {// Line is complete. Then execute!
|
if (char_counter > 0) {// Line is complete. Then execute!
|
||||||
line[char_counter] = 0; // Terminate string
|
line[char_counter] = 0; // Terminate string
|
||||||
protocol_status_message(protocol_execute_line(line));
|
report_status_message(protocol_execute_line(line));
|
||||||
} else {
|
} else {
|
||||||
// Empty or comment line. Skip block.
|
// Empty or comment line. Skip block.
|
||||||
protocol_status_message(STATUS_OK); // Send status message for syncing purposes.
|
report_status_message(STATUS_OK); // Send status message for syncing purposes.
|
||||||
}
|
}
|
||||||
char_counter = 0; // Reset line buffer index
|
char_counter = 0; // Reset line buffer index
|
||||||
iscomment = false; // Reset comment flag
|
iscomment = false; // Reset comment flag
|
||||||
|
25
protocol.h
25
protocol.h
@ -29,25 +29,6 @@
|
|||||||
// buffer.
|
// buffer.
|
||||||
#define LINE_BUFFER_SIZE 50
|
#define LINE_BUFFER_SIZE 50
|
||||||
|
|
||||||
// Define Grbl status codes.
|
|
||||||
#define STATUS_OK 0
|
|
||||||
#define STATUS_BAD_NUMBER_FORMAT 1
|
|
||||||
#define STATUS_EXPECTED_COMMAND_LETTER 2
|
|
||||||
#define STATUS_UNSUPPORTED_STATEMENT 3
|
|
||||||
#define STATUS_FLOATING_POINT_ERROR 4
|
|
||||||
#define STATUS_MODAL_GROUP_VIOLATION 5
|
|
||||||
#define STATUS_INVALID_STATEMENT 6
|
|
||||||
#define STATUS_HARD_LIMIT 7
|
|
||||||
#define STATUS_SETTING_DISABLED 8
|
|
||||||
#define STATUS_SETTING_STEPS_NEG 9
|
|
||||||
#define STATUS_SETTING_STEP_PULSE_MIN 10
|
|
||||||
#define STATUS_SETTING_READ_FAIL 11
|
|
||||||
|
|
||||||
// Define Grbl misc message codes
|
|
||||||
#define MESSAGE_SYSTEM_ALARM 0
|
|
||||||
#define MESSAGE_HOMING_ENABLE 1
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize the serial protocol
|
// Initialize the serial protocol
|
||||||
void protocol_init();
|
void protocol_init();
|
||||||
|
|
||||||
@ -61,10 +42,4 @@ uint8_t protocol_execute_line(char *line);
|
|||||||
// Checks and executes a runtime command at various stop points in main program
|
// Checks and executes a runtime command at various stop points in main program
|
||||||
void protocol_execute_runtime();
|
void protocol_execute_runtime();
|
||||||
|
|
||||||
// Prints Grbl's status messages.
|
|
||||||
void protocol_status_message(uint8_t status_code);
|
|
||||||
|
|
||||||
// Prints any misc messages.
|
|
||||||
void protocol_misc_message(uint8_t message_code);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,19 +9,24 @@ It accepts standards-compliant G-code and has been tested with the output of sev
|
|||||||
Grbl includes full acceleration management with look ahead. That means the controller will look up to 18 motions into the future and plan its velocities ahead to deliver smooth acceleration and jerk-free cornering.
|
Grbl includes full acceleration management with look ahead. That means the controller will look up to 18 motions into the future and plan its velocities ahead to deliver smooth acceleration and jerk-free cornering.
|
||||||
|
|
||||||
*Changelog for v0.8 from v0.7:*
|
*Changelog for v0.8 from v0.7:*
|
||||||
- *ALPHA status: _Under heavy development. Code state may significantly change with each push as new features are integrated._*
|
- *BETA status: _Under development. Code state may significantly change with each push as new features are integrated._*
|
||||||
- Major structural overhaul to allow for multi-tasking events and new feature sets
|
- Major structural overhaul to allow for multi-tasking events and new feature sets
|
||||||
- New run-time command control: Feed hold (pause), Cycle start (resume), Reset (abort), Status reporting
|
- New run-time command control: Feed hold (pause), Cycle start (resume), Reset (abort), Status reporting
|
||||||
- Controlled feed hold with deceleration to ensure no skipped steps and loss of location.
|
- Controlled feed hold with deceleration to ensure no skipped steps and loss of location.
|
||||||
- After feed hold, cycle accelerations are re-planned and may be resumed.
|
- After feed hold, cycle accelerations are re-planned and may be resumed.
|
||||||
|
- Advanced homing cycle with direction and speed configuration options. (Requires limit switches.)
|
||||||
|
- Limit pins are held normal high with an internal pull-up resister. Wiring only requires a normally-open switch connected to ground. (For both ends of an axis, simply wire two in parallel into the same pin.)
|
||||||
|
- Hard limits option and plays nice with homing cycle, so switches can be used for both homing and hard limits.
|
||||||
- Re-factored g-code parser with robust error-checking.
|
- Re-factored g-code parser with robust error-checking.
|
||||||
- Work coordinate system (G54), offsets(G92), and machine coordinate system support. G10 work coordinate settings support. (Up to 6 work coordinate systems(G54-G59) available as a compile-time option.)
|
- 6 work coordinate systems (G54-G59), offsets(G92), and machine coordinate system support. Work systems are stored in EEPROM and persistent.
|
||||||
|
- G10 L2 and L20 work coordinate settings support. L2 sets one or more axes values. L20 sets the current machine position to the specified work origin.
|
||||||
- Program stop(M0,M1*,M2,M30) initial support. Optional stop to do.
|
- Program stop(M0,M1*,M2,M30) initial support. Optional stop to do.
|
||||||
|
- Coolant control(M7*,M8,M9) support. (M7 is a compile-time option).
|
||||||
- System reset re-initializes grbl without resetting the Arduino and retains machine/home position and work coordinates.
|
- System reset re-initializes grbl without resetting the Arduino and retains machine/home position and work coordinates.
|
||||||
- Restructured planner and stepper modules to become independent and ready for future features.
|
- Restructured planner and stepper modules to become independent and ready for future features.
|
||||||
- Reduced serial read buffer to 128 characters and increased write buffer to 64 characters.
|
- Settings re-factoring to allow configuration without compiling of most features. (Still in progress).
|
||||||
- Misc bug fixes and removed deprecated acceleration enabled code.
|
- Misc bug fixes and removed deprecated acceleration enabled code.
|
||||||
- Planned features: Jog mode, full-featured status reporting, runtime settings such as toggling block delete.
|
- Planned features: Axis acceleration and max speed individual settings, full-featured status reporting, runtime settings such as toggling block delete.
|
||||||
- Advanced compile-time options: Up to 6 work coordinate systems(G54-G59), XON/XOFF flow control (limited support), direction and step pulse time delay.
|
- Advanced compile-time options: Up to 6 work coordinate systems(G54-G59), XON/XOFF flow control (limited support), direction and step pulse time delay.
|
||||||
|
|
||||||
|
|
||||||
|
211
report.c
Normal file
211
report.c
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
report.c - reporting and messaging methods
|
||||||
|
Part of Grbl
|
||||||
|
|
||||||
|
Copyright (c) 2012 Sungeun K. Jeon
|
||||||
|
|
||||||
|
Grbl is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Grbl is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file functions as the primary feedback interface for Grbl. Any outgoing data, such
|
||||||
|
as the protocol status messages, feedback messages, and status reports, are stored here.
|
||||||
|
For the most part, these functions primarily are called from protocol.c methods. If a
|
||||||
|
different style feedback is desired (i.e. JSON), then a user can change these following
|
||||||
|
methods to accomodate their needs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "print.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include "nuts_bolts.h"
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include "report.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Handles the primary confirmation protocol response for streaming interfaces and human-feedback.
|
||||||
|
// For every incoming line, this method responds with an 'ok' for a successful command or an
|
||||||
|
// 'error:' to indicate some error event with the line or some critical system error during
|
||||||
|
// operation. Errors events can originate from the g-code parser, settings module, or asynchronously
|
||||||
|
// from a critical error, such as a triggered hard limit. Interface should always monitor for these
|
||||||
|
// responses.
|
||||||
|
// NOTE: In silent mode, all error codes are greater than zero.
|
||||||
|
// TODO: Install silent mode to return only numeric values, primarily for GUIs.
|
||||||
|
void report_status_message(uint8_t status_code)
|
||||||
|
{
|
||||||
|
if (status_code == 0) { // STATUS_OK
|
||||||
|
printPgmString(PSTR("ok\r\n"));
|
||||||
|
} else {
|
||||||
|
printPgmString(PSTR("error: "));
|
||||||
|
switch(status_code) {
|
||||||
|
case STATUS_BAD_NUMBER_FORMAT:
|
||||||
|
printPgmString(PSTR("Bad number format")); break;
|
||||||
|
case STATUS_EXPECTED_COMMAND_LETTER:
|
||||||
|
printPgmString(PSTR("Expected command letter")); break;
|
||||||
|
case STATUS_UNSUPPORTED_STATEMENT:
|
||||||
|
printPgmString(PSTR("Unsupported statement")); break;
|
||||||
|
case STATUS_FLOATING_POINT_ERROR:
|
||||||
|
printPgmString(PSTR("Floating point error")); break;
|
||||||
|
case STATUS_MODAL_GROUP_VIOLATION:
|
||||||
|
printPgmString(PSTR("Modal group violation")); break;
|
||||||
|
case STATUS_INVALID_STATEMENT:
|
||||||
|
printPgmString(PSTR("Invalid statement")); break;
|
||||||
|
case STATUS_HARD_LIMIT:
|
||||||
|
printPgmString(PSTR("Limit triggered")); break;
|
||||||
|
case STATUS_SETTING_DISABLED:
|
||||||
|
printPgmString(PSTR("Grbl setting disabled")); break;
|
||||||
|
case STATUS_SETTING_VALUE_NEG:
|
||||||
|
printPgmString(PSTR("Set value must be > 0.0")); break;
|
||||||
|
case STATUS_SETTING_STEP_PULSE_MIN:
|
||||||
|
printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break;
|
||||||
|
case STATUS_SETTING_READ_FAIL:
|
||||||
|
printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break;
|
||||||
|
}
|
||||||
|
printPgmString(PSTR("\r\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prints feedback messages. This serves as a centralized method to provide additional
|
||||||
|
// user feedback for things that are not of the status message response protocol. These
|
||||||
|
// are messages such as setup warnings and how to exit alarms.
|
||||||
|
// NOTE: For interfaces, messages are always placed within parentheses. And if silent mode
|
||||||
|
// is installed, the message codes are less than zero.
|
||||||
|
// TODO: Install silence feedback messages option in settings
|
||||||
|
void report_feedback_message(int8_t message_code)
|
||||||
|
{
|
||||||
|
printPgmString(PSTR("("));
|
||||||
|
switch(message_code) {
|
||||||
|
case MESSAGE_SYSTEM_ALARM:
|
||||||
|
printPgmString(PSTR("ALARM: Check and reset Grbl")); break;
|
||||||
|
case MESSAGE_POSITION_LOST:
|
||||||
|
printPgmString(PSTR("warning: Position may be lost")); break;
|
||||||
|
case MESSAGE_HOMING_ENABLE:
|
||||||
|
printPgmString(PSTR("'$H' to home. Ensure all limit switches are installed")); break;
|
||||||
|
}
|
||||||
|
printPgmString(PSTR(")\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Welcome message
|
||||||
|
void report_init_message()
|
||||||
|
{
|
||||||
|
// Print grbl initialization message
|
||||||
|
printPgmString(PSTR("\r\nGrbl " GRBL_VERSION));
|
||||||
|
printPgmString(PSTR("\r\n'$' for help and to view settings\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void report_grbl_help() {
|
||||||
|
printPgmString(PSTR("$0 = ")); printFloat(settings.steps_per_mm[X_AXIS]);
|
||||||
|
printPgmString(PSTR(" (x axis, steps/mm)\r\n$1 = ")); printFloat(settings.steps_per_mm[Y_AXIS]);
|
||||||
|
printPgmString(PSTR(" (y axis, steps/mm)\r\n$2 = ")); printFloat(settings.steps_per_mm[Z_AXIS]);
|
||||||
|
printPgmString(PSTR(" (z axis, steps/mm)\r\n$3 = ")); printInteger(settings.pulse_microseconds);
|
||||||
|
printPgmString(PSTR(" (step pulse, usec)\r\n$4 = ")); printFloat(settings.default_feed_rate);
|
||||||
|
printPgmString(PSTR(" (default feed rate, mm/min)\r\n$5 = ")); printFloat(settings.default_seek_rate);
|
||||||
|
printPgmString(PSTR(" (default seek rate, mm/min)\r\n$6 = ")); printFloat(settings.mm_per_arc_segment);
|
||||||
|
printPgmString(PSTR(" (arc resolution, mm/segment)\r\n$7 = ")); printInteger(settings.invert_mask);
|
||||||
|
printPgmString(PSTR(" (step port invert mask, int:binary = ")); print_uint8_base2(settings.invert_mask);
|
||||||
|
printPgmString(PSTR(")\r\n$8 = ")); printFloat(settings.acceleration/(60*60)); // Convert from mm/min^2 for human readability
|
||||||
|
printPgmString(PSTR(" (acceleration, mm/sec^2)\r\n$9 = ")); printFloat(settings.junction_deviation);
|
||||||
|
printPgmString(PSTR(" (cornering junction deviation, mm)\r\n$10 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
|
||||||
|
printPgmString(PSTR(" (status report inches, bool)\r\n$11 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
|
||||||
|
printPgmString(PSTR(" (auto start enable, bool)\r\n$12 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
|
||||||
|
printPgmString(PSTR(" (invert stepper enable, bool)\r\n$13 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
|
||||||
|
printPgmString(PSTR(" (hard limit enable, bool)\r\n$14 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
||||||
|
printPgmString(PSTR(" (homing enable, bool)\r\n$15 = ")); printInteger(settings.homing_dir_mask);
|
||||||
|
printPgmString(PSTR(" (homing direction mask, int:binary = ")); print_uint8_base2(settings.homing_dir_mask);
|
||||||
|
printPgmString(PSTR(")\r\n$16 = ")); printFloat(settings.homing_feed_rate);
|
||||||
|
printPgmString(PSTR(" (homing feed rate, mm/min)\r\n$17 = ")); printFloat(settings.homing_seek_rate);
|
||||||
|
printPgmString(PSTR(" (homing seek rate, mm/min)\r\n$18 = ")); printInteger(settings.homing_debounce_delay);
|
||||||
|
printPgmString(PSTR(" (homing debounce delay, msec)\r\n$19 = ")); printFloat(settings.homing_pulloff);
|
||||||
|
printPgmString(PSTR(" (homing pull-off travel, mm)\r\n$20 = ")); printInteger(settings.stepper_idle_lock_time);
|
||||||
|
printPgmString(PSTR(" (stepper idle lock time, msec)\r\n$21 = ")); printInteger(settings.decimal_places);
|
||||||
|
printPgmString(PSTR(" (decimal places, int)\r\n$22 = ")); printInteger(settings.n_arc_correction);
|
||||||
|
// char st_line[LINE_BUFFER_SIZE];
|
||||||
|
// printPgmString(PSTR("\r\n\r\n Startup\r\n$100 = ")); printString(settings_read_startup(st_line,0));
|
||||||
|
// printPgmString(PSTR("\r\n$101 = ")); printString(settings_read_startup(st_line,1));
|
||||||
|
|
||||||
|
// char buf[4];
|
||||||
|
// settings_startup_string((char *)buf);
|
||||||
|
// printPgmString(PSTR("\r\n Startup: ")); printString(buf);
|
||||||
|
|
||||||
|
printPgmString(PSTR("\r\n'$x=value' to store setting"));
|
||||||
|
// printPgmString(PSTR("\r\n'$Sx' to toggle switch\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// void report_gcode_status()
|
||||||
|
// {
|
||||||
|
// // Print gcode parser state
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void report_gcode_parameters()
|
||||||
|
// {
|
||||||
|
// // Print gcode work coordinate offsets?
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
void report_realtime_status()
|
||||||
|
{
|
||||||
|
// TODO: Status report data is written to the user here. This function should be able to grab a
|
||||||
|
// real-time snapshot of the stepper subprogram and the actual location of the CNC machine. At a
|
||||||
|
// minimum, status report should return real-time location information. Other important information
|
||||||
|
// may be distance to go on block, processed block id, and feed rate. A secondary, non-critical
|
||||||
|
// status report may include g-code state, i.e. inch mode, plane mode, absolute mode, etc.
|
||||||
|
// The report generated must be as short as possible, yet still provide the user easily readable
|
||||||
|
// information, i.e. '[0.23,120.4,2.4]'. This is necessary as it minimizes the computational
|
||||||
|
// overhead and allows grbl to keep running smoothly, especially with g-code programs with fast,
|
||||||
|
// short line segments and interface setups that require real-time status reports (5-20Hz).
|
||||||
|
|
||||||
|
// **Under construction** Bare-bones status report. Provides real-time machine position relative to
|
||||||
|
// the system power on location (0,0,0) and work coordinate position (G54 and G92 applied).
|
||||||
|
// The following are still needed: user setting of output units (mm|inch), compressed (non-human
|
||||||
|
// readable) data for interfaces?, save last known position in EEPROM?, code optimizations, solidify
|
||||||
|
// the reporting schemes, move to a separate .c file for easy user accessibility, and setting the
|
||||||
|
// home position by the user (likely through '$' setting interface).
|
||||||
|
// Successfully tested at a query rate of 10-20Hz while running a gauntlet of programs at various
|
||||||
|
// speeds.
|
||||||
|
uint8_t i;
|
||||||
|
int32_t current_position[3]; // Copy current state of the system position variable
|
||||||
|
memcpy(current_position,sys.position,sizeof(sys.position));
|
||||||
|
float print_position[3];
|
||||||
|
|
||||||
|
// Report machine position
|
||||||
|
printPgmString(PSTR("MPos:["));
|
||||||
|
for (i=0; i<= 2; i++) {
|
||||||
|
print_position[i] = current_position[i]/settings.steps_per_mm[i];
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
|
||||||
|
printFloat(print_position[i]);
|
||||||
|
if (i < 2) { printPgmString(PSTR(",")); }
|
||||||
|
else { printPgmString(PSTR("]")); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report work position
|
||||||
|
printPgmString(PSTR(",WPos:["));
|
||||||
|
for (i=0; i<= 2; i++) {
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
|
||||||
|
print_position[i] -= (sys.coord_system[i]+sys.coord_offset[i])*INCH_PER_MM;
|
||||||
|
} else {
|
||||||
|
print_position[i] -= sys.coord_system[i]+sys.coord_offset[i];
|
||||||
|
}
|
||||||
|
printFloat(print_position[i]);
|
||||||
|
if (i < 2) { printPgmString(PSTR(",")); }
|
||||||
|
else { printPgmString(PSTR("]")); }
|
||||||
|
}
|
||||||
|
|
||||||
|
printPgmString(PSTR("\r\n"));
|
||||||
|
}
|
59
report.h
Normal file
59
report.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
report.h - reporting and messaging methods
|
||||||
|
Part of Grbl
|
||||||
|
|
||||||
|
Copyright (c) 2012 Sungeun K. Jeon
|
||||||
|
|
||||||
|
Grbl is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Grbl is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef report_h
|
||||||
|
#define report_h
|
||||||
|
|
||||||
|
|
||||||
|
// Define Grbl status codes.
|
||||||
|
#define STATUS_OK 0
|
||||||
|
#define STATUS_BAD_NUMBER_FORMAT 1
|
||||||
|
#define STATUS_EXPECTED_COMMAND_LETTER 2
|
||||||
|
#define STATUS_UNSUPPORTED_STATEMENT 3
|
||||||
|
#define STATUS_FLOATING_POINT_ERROR 4
|
||||||
|
#define STATUS_MODAL_GROUP_VIOLATION 5
|
||||||
|
#define STATUS_INVALID_STATEMENT 6
|
||||||
|
#define STATUS_HARD_LIMIT 7
|
||||||
|
#define STATUS_SETTING_DISABLED 8
|
||||||
|
#define STATUS_SETTING_VALUE_NEG 9
|
||||||
|
#define STATUS_SETTING_STEP_PULSE_MIN 10
|
||||||
|
#define STATUS_SETTING_READ_FAIL 11
|
||||||
|
|
||||||
|
// Define Grbl feedback message codes. Less than zero to distinguish message from error.
|
||||||
|
#define MESSAGE_SYSTEM_ALARM -1
|
||||||
|
#define MESSAGE_POSITION_LOST -2
|
||||||
|
#define MESSAGE_HOMING_ENABLE -3
|
||||||
|
|
||||||
|
|
||||||
|
// Prints system status messages.
|
||||||
|
void report_status_message(uint8_t status_code);
|
||||||
|
|
||||||
|
// Prints miscellaneous feedback messages.
|
||||||
|
void report_feedback_message(int8_t message_code);
|
||||||
|
|
||||||
|
// Prints welcome message
|
||||||
|
void report_init_message();
|
||||||
|
|
||||||
|
// Prints Grbl help and current global settings
|
||||||
|
void report_grbl_help();
|
||||||
|
|
||||||
|
// Prints realtime status report
|
||||||
|
void report_realtime_status();
|
||||||
|
|
||||||
|
#endif
|
2
serial.c
2
serial.c
@ -166,7 +166,7 @@ ISR(USART_RX_vect)
|
|||||||
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
|
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
|
||||||
case CMD_RESET:
|
case CMD_RESET:
|
||||||
// Immediately force stepper and spindle subsystem idle at an interrupt level.
|
// Immediately force stepper and spindle subsystem idle at an interrupt level.
|
||||||
if (!(sys.execute & EXEC_RESET)) { mc_alarm(); } // Stop only first time.
|
mc_alarm();
|
||||||
sys.execute |= EXEC_RESET; // Set as true
|
sys.execute |= EXEC_RESET; // Set as true
|
||||||
break;
|
break;
|
||||||
default: // Write character to buffer
|
default: // Write character to buffer
|
||||||
|
207
settings.c
Executable file → Normal file
207
settings.c
Executable file → Normal file
@ -28,21 +28,11 @@
|
|||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
settings_t settings;
|
settings_t settings;
|
||||||
|
|
||||||
// Version 1 outdated settings record
|
// Version 4 outdated settings record
|
||||||
typedef struct {
|
|
||||||
float steps_per_mm[3];
|
|
||||||
uint8_t microsteps;
|
|
||||||
uint8_t pulse_microseconds;
|
|
||||||
float default_feed_rate;
|
|
||||||
float default_seek_rate;
|
|
||||||
uint8_t invert_mask;
|
|
||||||
float mm_per_arc_segment;
|
|
||||||
} settings_v1_t;
|
|
||||||
|
|
||||||
// Version 2,3,4 outdated settings record
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float steps_per_mm[3];
|
float steps_per_mm[3];
|
||||||
uint8_t microsteps;
|
uint8_t microsteps;
|
||||||
@ -53,7 +43,7 @@ typedef struct {
|
|||||||
float mm_per_arc_segment;
|
float mm_per_arc_segment;
|
||||||
float acceleration;
|
float acceleration;
|
||||||
float junction_deviation;
|
float junction_deviation;
|
||||||
} settings_v2_v4_t;
|
} settings_v4_t;
|
||||||
|
|
||||||
// Default settings (used when resetting eeprom-settings)
|
// Default settings (used when resetting eeprom-settings)
|
||||||
#define MICROSTEPS 8
|
#define MICROSTEPS 8
|
||||||
@ -71,6 +61,7 @@ typedef struct {
|
|||||||
// Developmental default settings
|
// Developmental default settings
|
||||||
#define DEFAULT_REPORT_INCHES 0 // false
|
#define DEFAULT_REPORT_INCHES 0 // false
|
||||||
#define DEFAULT_AUTO_START 1 // true
|
#define DEFAULT_AUTO_START 1 // true
|
||||||
|
#define DEFAULT_INVERT_ST_ENABLE 0 // false
|
||||||
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
|
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
|
||||||
#define DEFAULT_HOMING_ENABLE 0 // false
|
#define DEFAULT_HOMING_ENABLE 0 // false
|
||||||
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
|
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
|
||||||
@ -80,6 +71,22 @@ typedef struct {
|
|||||||
#define DEFAULT_HOMING_PULLOFF 1 // mm
|
#define DEFAULT_HOMING_PULLOFF 1 // mm
|
||||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
|
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
|
||||||
#define DEFAULT_DECIMAL_PLACES 3
|
#define DEFAULT_DECIMAL_PLACES 3
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25
|
||||||
|
|
||||||
|
|
||||||
|
void settings_write_coord_data(uint8_t coord_select, float *coord_data)
|
||||||
|
{
|
||||||
|
uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
|
||||||
|
memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_global_settings()
|
||||||
|
{
|
||||||
|
eeprom_put_char(0, SETTINGS_VERSION);
|
||||||
|
memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void settings_reset(bool reset_all) {
|
void settings_reset(bool reset_all) {
|
||||||
// Reset all settings or only the migration settings to the new version.
|
// Reset all settings or only the migration settings to the new version.
|
||||||
@ -97,7 +104,9 @@ void settings_reset(bool reset_all) {
|
|||||||
}
|
}
|
||||||
// New settings since last version
|
// New settings since last version
|
||||||
settings.flags = 0;
|
settings.flags = 0;
|
||||||
|
if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; }
|
||||||
if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; }
|
if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; }
|
||||||
|
if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
|
||||||
if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
|
if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
|
||||||
if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; }
|
if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; }
|
||||||
settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK;
|
settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK;
|
||||||
@ -107,138 +116,56 @@ void settings_reset(bool reset_all) {
|
|||||||
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
|
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
|
||||||
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
|
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
|
||||||
settings.decimal_places = DEFAULT_DECIMAL_PLACES;
|
settings.decimal_places = DEFAULT_DECIMAL_PLACES;
|
||||||
|
settings.n_arc_correction = DEFAULT_N_ARC_CORRECTION;
|
||||||
|
write_global_settings();
|
||||||
|
|
||||||
|
// Zero all coordinate parameter data.
|
||||||
|
float coord_data[N_AXIS];
|
||||||
|
clear_vector_float(coord_data);
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (i=0; i<=SETTING_INDEX_NCOORD; i++) {
|
||||||
|
settings_write_coord_data(i,coord_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static void settings_startup_string(char *buf) {
|
// Read selected coordinate data from EEPROM. Updates pointed coord_data value.
|
||||||
// memcpy_from_eeprom_with_checksum((char*)buf,512, 4);
|
uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data)
|
||||||
// }
|
{
|
||||||
|
uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
|
||||||
void settings_dump() {
|
if ((!memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) {
|
||||||
printPgmString(PSTR("$0 = ")); printFloat(settings.steps_per_mm[X_AXIS]);
|
clear_vector_float(coord_data); // Default zero vector
|
||||||
printPgmString(PSTR(" (x axis, steps/mm)\r\n$1 = ")); printFloat(settings.steps_per_mm[Y_AXIS]);
|
settings_write_coord_data(coord_select,coord_data);
|
||||||
printPgmString(PSTR(" (y axis, steps/mm)\r\n$2 = ")); printFloat(settings.steps_per_mm[Z_AXIS]);
|
return(false);
|
||||||
printPgmString(PSTR(" (z axis, steps/mm)\r\n$3 = ")); printInteger(settings.pulse_microseconds);
|
} else {
|
||||||
printPgmString(PSTR(" (step pulse, usec)\r\n$4 = ")); printFloat(settings.default_feed_rate);
|
return(true);
|
||||||
printPgmString(PSTR(" (default feed rate, mm/min)\r\n$5 = ")); printFloat(settings.default_seek_rate);
|
}
|
||||||
printPgmString(PSTR(" (default seek rate, mm/min)\r\n$6 = ")); printFloat(settings.mm_per_arc_segment);
|
|
||||||
printPgmString(PSTR(" (arc resolution, mm/segment)\r\n$7 = ")); printInteger(settings.invert_mask);
|
|
||||||
printPgmString(PSTR(" (step port invert mask, int:binary = ")); print_uint8_base2(settings.invert_mask);
|
|
||||||
printPgmString(PSTR(")\r\n$8 = ")); printFloat(settings.acceleration/(60*60)); // Convert from mm/min^2 for human readability
|
|
||||||
printPgmString(PSTR(" (acceleration, mm/sec^2)\r\n$9 = ")); printFloat(settings.junction_deviation);
|
|
||||||
printPgmString(PSTR(" (cornering junction deviation, mm)\r\n$10 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
|
|
||||||
printPgmString(PSTR(" (status report inches, bool)\r\n$11 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
|
|
||||||
printPgmString(PSTR(" (auto start enable, bool)\r\n$12 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
|
|
||||||
printPgmString(PSTR(" (hard limit enable, bool)\r\n$13 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
|
||||||
printPgmString(PSTR(" (homing enable, bool)\r\n$14 = ")); printInteger(settings.homing_dir_mask);
|
|
||||||
printPgmString(PSTR(" (homing direction mask, int:binary = ")); print_uint8_base2(settings.homing_dir_mask);
|
|
||||||
printPgmString(PSTR(")\r\n$15 = ")); printFloat(settings.homing_feed_rate);
|
|
||||||
printPgmString(PSTR(" (homing feed rate, mm/min)\r\n$16 = ")); printFloat(settings.homing_seek_rate);
|
|
||||||
printPgmString(PSTR(" (homing seek rate, mm/min)\r\n$17 = ")); printInteger(settings.homing_debounce_delay);
|
|
||||||
printPgmString(PSTR(" (homing debounce delay, msec)\r\n$18 = ")); printFloat(settings.homing_pulloff);
|
|
||||||
printPgmString(PSTR(" (homing pull-off travel, mm)\r\n$19 = ")); printInteger(settings.stepper_idle_lock_time);
|
|
||||||
printPgmString(PSTR(" (stepper idle lock time, msec)\r\n$20 = ")); printInteger(settings.decimal_places);
|
|
||||||
printPgmString(PSTR(" (decimal places, int)"));
|
|
||||||
|
|
||||||
// char buf[4];
|
|
||||||
// settings_startup_string((char *)buf);
|
|
||||||
// printPgmString(PSTR("\r\n Startup: ")); printString(buf);
|
|
||||||
|
|
||||||
printPgmString(PSTR("\r\n'$x=value' to set parameter or just '$' to dump current settings\r\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameter lines are on the form '$4=374.3' or '$' to dump current settings
|
|
||||||
// NOTE: Assumes '$' already exists in line[0], which is checked by protocol.c.
|
|
||||||
uint8_t settings_execute_line(char *line) {
|
|
||||||
uint8_t char_counter = 1;
|
|
||||||
// unsigned char letter;
|
|
||||||
float parameter, value;
|
|
||||||
if(line[char_counter] == 0) {
|
|
||||||
settings_dump(); return(STATUS_OK);
|
|
||||||
}
|
|
||||||
// if(line[char_counter] >= 'A' || line[char_counter] <= 'Z') {
|
|
||||||
// letter = line[char_counter++];
|
|
||||||
// if(line[char_counter++] != '=') {
|
|
||||||
// return(STATUS_UNSUPPORTED_STATEMENT);
|
|
||||||
// }
|
|
||||||
// for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) {
|
|
||||||
// line[char_counter] = line[char_counter+3];
|
|
||||||
// }
|
|
||||||
// uint8_t status = gc_execute_line(line);
|
|
||||||
// if (status) { return(status); }
|
|
||||||
// else { settings_store_startup_line(line); }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Opt stop and block delete are referred to as switches.
|
|
||||||
// // How to store home position and work offsets real-time??
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
if(!read_float(line, &char_counter, ¶meter)) {
|
|
||||||
return(STATUS_BAD_NUMBER_FORMAT);
|
|
||||||
}
|
|
||||||
if(line[char_counter++] != '=') {
|
|
||||||
return(STATUS_UNSUPPORTED_STATEMENT);
|
|
||||||
}
|
|
||||||
if(!read_float(line, &char_counter, &value)) {
|
|
||||||
return(STATUS_BAD_NUMBER_FORMAT);
|
|
||||||
}
|
|
||||||
if(line[char_counter] != 0) {
|
|
||||||
return(STATUS_UNSUPPORTED_STATEMENT);
|
|
||||||
}
|
|
||||||
return(settings_store_setting(parameter, value));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_settings() {
|
uint8_t read_global_settings() {
|
||||||
eeprom_put_char(0, SETTINGS_VERSION);
|
|
||||||
memcpy_to_eeprom_with_checksum(1, (char*)&settings, sizeof(settings_t));
|
|
||||||
//
|
|
||||||
// char buf[4]; buf[0] = 'G'; buf[1] = '2'; buf[2] = '0'; buf[3] = 0;
|
|
||||||
// memcpy_to_eeprom_with_checksum(512, (char*)buf, 4);
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_settings() {
|
|
||||||
// Check version-byte of eeprom
|
// Check version-byte of eeprom
|
||||||
uint8_t version = eeprom_get_char(0);
|
uint8_t version = eeprom_get_char(0);
|
||||||
|
|
||||||
if (version == SETTINGS_VERSION) {
|
if (version == SETTINGS_VERSION) {
|
||||||
// Read settings-record and check checksum
|
// Read settings-record and check checksum
|
||||||
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t)))) {
|
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) {
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Incrementally update the old versions until up-to-date.
|
|
||||||
if (version == 1) {
|
|
||||||
// Migrate from settings version 1 to version 4.
|
|
||||||
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v1_t)))) {
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
settings.acceleration = DEFAULT_ACCELERATION;
|
|
||||||
settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
|
|
||||||
} else if ((version == 2) || (version == 3)) {
|
|
||||||
// Migrate from settings version 2 and 3 to version 4.
|
|
||||||
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v2_v4_t)))) {
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
if (version == 2) { settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; }
|
|
||||||
settings.acceleration *= 3600; // Convert to mm/min^2 from mm/sec^2
|
|
||||||
}
|
|
||||||
if (version <= 4) {
|
if (version <= 4) {
|
||||||
// Migrate from settings version 4 to current version.
|
// Migrate from settings version 4 to current version.
|
||||||
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v2_v4_t)))) {
|
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t)))) {
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
settings_reset(false);
|
settings_reset(false);
|
||||||
write_settings();
|
|
||||||
} else if (version >= 50) {
|
} else if (version >= 50) {
|
||||||
// Developmental settings. Version numbers greater than or equal to 50 are temporary.
|
// Developmental settings. Version numbers greater than or equal to 50 are temporary.
|
||||||
// Currently, this will update the user settings to v4 and the remainder of the settings
|
// Currently, this will update the user settings to v4 and the remainder of the settings
|
||||||
// should be re-written to the default value, if the developmental version number changed.
|
// should be re-written to the default value, if the developmental version number changed.
|
||||||
|
|
||||||
// Grab settings regardless of error.
|
// Grab settings regardless of error.
|
||||||
memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t));
|
memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t));
|
||||||
settings_reset(false);
|
settings_reset(false);
|
||||||
write_settings();
|
|
||||||
} else {
|
} else {
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
@ -246,11 +173,12 @@ int read_settings() {
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// A helper method to set settings from command line
|
// A helper method to set settings from command line
|
||||||
uint8_t settings_store_setting(int parameter, float value) {
|
uint8_t settings_store_global_setting(int parameter, float value) {
|
||||||
switch(parameter) {
|
switch(parameter) {
|
||||||
case 0: case 1: case 2:
|
case 0: case 1: case 2:
|
||||||
if (value <= 0.0) { return(STATUS_SETTING_STEPS_NEG); }
|
if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); }
|
||||||
settings.steps_per_mm[parameter] = value; break;
|
settings.steps_per_mm[parameter] = value; break;
|
||||||
case 3:
|
case 3:
|
||||||
if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
|
if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
|
||||||
@ -273,39 +201,46 @@ uint8_t settings_store_setting(int parameter, float value) {
|
|||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
if (value) {
|
if (value) {
|
||||||
settings.flags |= BITFLAG_HARD_LIMIT_ENABLE;
|
settings.flags |= BITFLAG_INVERT_ST_ENABLE;
|
||||||
} else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
|
} else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
|
if (value) {
|
||||||
|
settings.flags |= BITFLAG_HARD_LIMIT_ENABLE;
|
||||||
|
} else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
if (value) {
|
if (value) {
|
||||||
settings.flags |= BITFLAG_HOMING_ENABLE;
|
settings.flags |= BITFLAG_HOMING_ENABLE;
|
||||||
protocol_misc_message(MESSAGE_HOMING_ENABLE);
|
report_feedback_message(MESSAGE_HOMING_ENABLE);
|
||||||
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
|
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
|
||||||
break;
|
break;
|
||||||
case 14: settings.homing_dir_mask = trunc(value); break;
|
case 15: settings.homing_dir_mask = trunc(value); break;
|
||||||
case 15: settings.homing_feed_rate = value; break;
|
case 16: settings.homing_feed_rate = value; break;
|
||||||
case 16: settings.homing_seek_rate = value; break;
|
case 17: settings.homing_seek_rate = value; break;
|
||||||
case 17: settings.homing_debounce_delay = round(value); break;
|
case 18: settings.homing_debounce_delay = round(value); break;
|
||||||
case 18: settings.homing_pulloff = value; break;
|
|
||||||
case 19:
|
case 19:
|
||||||
|
if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); }
|
||||||
|
settings.homing_pulloff = value; break;
|
||||||
|
case 20:
|
||||||
settings.stepper_idle_lock_time = round(value);
|
settings.stepper_idle_lock_time = round(value);
|
||||||
// TODO: Immediately check and toggle steppers from always enable or disable?
|
// TODO: Immediately check and toggle steppers from always enable or disable?
|
||||||
break;
|
break;
|
||||||
case 20: settings.decimal_places = round(value); break;
|
case 21: settings.decimal_places = round(value); break;
|
||||||
|
case 22: settings.n_arc_correction = round(value); break;
|
||||||
default:
|
default:
|
||||||
return(STATUS_INVALID_STATEMENT);
|
return(STATUS_INVALID_STATEMENT);
|
||||||
}
|
}
|
||||||
write_settings();
|
write_global_settings();
|
||||||
return(STATUS_OK);
|
return(STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the config subsystem
|
// Initialize the config subsystem
|
||||||
void settings_init() {
|
void settings_init() {
|
||||||
if(!read_settings()) {
|
if(!read_global_settings()) {
|
||||||
protocol_status_message(STATUS_SETTING_READ_FAIL);
|
report_status_message(STATUS_SETTING_READ_FAIL);
|
||||||
settings_reset(true);
|
settings_reset(true);
|
||||||
write_settings();
|
report_grbl_help();
|
||||||
settings_dump();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
settings.h
38
settings.h
@ -24,20 +24,35 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "nuts_bolts.h"
|
||||||
|
|
||||||
#define GRBL_VERSION "0.8b"
|
#define GRBL_VERSION "0.8b"
|
||||||
|
|
||||||
// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl
|
// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl
|
||||||
// when firmware is upgraded. Always stored in byte 0 of eeprom
|
// when firmware is upgraded. Always stored in byte 0 of eeprom
|
||||||
#define SETTINGS_VERSION 55
|
#define SETTINGS_VERSION 56
|
||||||
|
|
||||||
// Define bit flag masks for the boolean settings in settings.flag.
|
// Define bit flag masks for the boolean settings in settings.flag.
|
||||||
#define BITFLAG_REPORT_INCHES bit(0)
|
#define BITFLAG_REPORT_INCHES bit(0)
|
||||||
#define BITFLAG_AUTO_START bit(1)
|
#define BITFLAG_AUTO_START bit(1)
|
||||||
#define BITFLAG_HARD_LIMIT_ENABLE bit(2)
|
#define BITFLAG_INVERT_ST_ENABLE bit(2)
|
||||||
#define BITFLAG_HOMING_ENABLE bit(3)
|
#define BITFLAG_HARD_LIMIT_ENABLE bit(3)
|
||||||
|
#define BITFLAG_HOMING_ENABLE bit(4)
|
||||||
|
|
||||||
// Current global settings (persisted in EEPROM from byte 1 onwards)
|
// Define EEPROM memory address location values for on-demand settings and parameters
|
||||||
|
#define EEPROM_ADDR_GLOBAL 1
|
||||||
|
#define EEPROM_ADDR_PARAMETERS 512
|
||||||
|
#define EEPROM_ADDR_STARTUP_SCRIPT 768
|
||||||
|
|
||||||
|
// Define EEPROM address indexing for coordinate parameters
|
||||||
|
#define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1)
|
||||||
|
#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+2 // Total number of system stored (from index 0)
|
||||||
|
// NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59)
|
||||||
|
#define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1
|
||||||
|
#define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2
|
||||||
|
#define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset
|
||||||
|
|
||||||
|
// Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float steps_per_mm[3];
|
float steps_per_mm[3];
|
||||||
uint8_t microsteps;
|
uint8_t microsteps;
|
||||||
@ -56,20 +71,21 @@ typedef struct {
|
|||||||
float homing_pulloff;
|
float homing_pulloff;
|
||||||
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.
|
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.
|
||||||
uint8_t decimal_places;
|
uint8_t decimal_places;
|
||||||
|
uint8_t n_arc_correction;
|
||||||
} settings_t;
|
} settings_t;
|
||||||
extern settings_t settings;
|
extern settings_t settings;
|
||||||
|
|
||||||
// Initialize the configuration subsystem (load settings from EEPROM)
|
// Initialize the configuration subsystem (load settings from EEPROM)
|
||||||
void settings_init();
|
void settings_init();
|
||||||
|
|
||||||
// Print current settings
|
|
||||||
void settings_dump();
|
|
||||||
|
|
||||||
// Handle settings command
|
|
||||||
uint8_t settings_execute_line(char *line);
|
|
||||||
|
|
||||||
// A helper method to set new settings from command line
|
// A helper method to set new settings from command line
|
||||||
uint8_t settings_store_setting(int parameter, float value);
|
uint8_t settings_store_global_setting(int parameter, float value);
|
||||||
|
|
||||||
|
// Writes selected coordinate data to EEPROM
|
||||||
|
void settings_write_coord_data(uint8_t coord_select, float *coord_data);
|
||||||
|
|
||||||
|
// Reads selected coordinate data from EEPROM
|
||||||
|
uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data);
|
||||||
|
|
||||||
// int8_t settings_execute_startup();
|
// int8_t settings_execute_startup();
|
||||||
|
|
||||||
|
32
stepper.c
32
stepper.c
@ -84,9 +84,17 @@ static volatile uint8_t busy; // True when SIG_OUTPUT_COMPARE1A is being servi
|
|||||||
|
|
||||||
static void set_step_events_per_minute(uint32_t steps_per_minute);
|
static void set_step_events_per_minute(uint32_t steps_per_minute);
|
||||||
|
|
||||||
// Stepper state initialization
|
// Stepper state initialization. Cycle should only start if the st.cycle_start flag is
|
||||||
static void st_wake_up()
|
// enabled. Startup init and limits call this function but shouldn't start the cycle.
|
||||||
|
void st_wake_up()
|
||||||
{
|
{
|
||||||
|
// Enable steppers by resetting the stepper disable port
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) {
|
||||||
|
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
|
||||||
|
} else {
|
||||||
|
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
|
||||||
|
}
|
||||||
|
if (sys.cycle_start) {
|
||||||
// Initialize stepper output bits
|
// Initialize stepper output bits
|
||||||
out_bits = (0) ^ (settings.invert_mask);
|
out_bits = (0) ^ (settings.invert_mask);
|
||||||
// Initialize step pulse timing from settings. Here to ensure updating after re-writing.
|
// Initialize step pulse timing from settings. Here to ensure updating after re-writing.
|
||||||
@ -99,25 +107,28 @@ static void st_wake_up()
|
|||||||
// Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement.
|
// Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement.
|
||||||
step_pulse_time = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3);
|
step_pulse_time = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3);
|
||||||
#endif
|
#endif
|
||||||
// Enable steppers by resetting the stepper disable port
|
|
||||||
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
|
|
||||||
// Enable stepper driver interrupt
|
// Enable stepper driver interrupt
|
||||||
TIMSK1 |= (1<<OCIE1A);
|
TIMSK1 |= (1<<OCIE1A);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stepper shutdown
|
// Stepper shutdown
|
||||||
void st_go_idle()
|
void st_go_idle()
|
||||||
{
|
{
|
||||||
// Disable stepper driver interrupt
|
// Disable stepper driver interrupt
|
||||||
TIMSK1 &= ~(1<<OCIE1A);
|
TIMSK1 &= ~(1<<OCIE1A);
|
||||||
|
// Disable steppers only upon system alarm activated or by user setting to not be kept enabled.
|
||||||
|
if ((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) {
|
||||||
// Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete
|
// Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete
|
||||||
// stop and not drift from residual inertial forces at the end of the last movement.
|
// stop and not drift from residual inertial forces at the end of the last movement.
|
||||||
delay_ms(settings.stepper_idle_lock_time);
|
delay_ms(settings.stepper_idle_lock_time);
|
||||||
// Disable steppers only upon system alarm activated or by user setting to not be kept enabled.
|
if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) {
|
||||||
if ((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) {
|
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
|
||||||
|
} else {
|
||||||
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
|
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This function determines an acceleration velocity change every CYCLES_PER_ACCELERATION_TICK by
|
// This function determines an acceleration velocity change every CYCLES_PER_ACCELERATION_TICK by
|
||||||
// keeping track of the number of elapsed cycles during a de/ac-celeration. The code assumes that
|
// keeping track of the number of elapsed cycles during a de/ac-celeration. The code assumes that
|
||||||
@ -362,7 +373,8 @@ void st_init()
|
|||||||
TIMSK2 |= (1<<OCIE2A); // Enable Timer2 Compare Match A interrupt
|
TIMSK2 |= (1<<OCIE2A); // Enable Timer2 Compare Match A interrupt
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Start in the idle state
|
// Start in the idle state, but first wake up to check for keep steppers enabled option.
|
||||||
|
st_wake_up();
|
||||||
st_go_idle();
|
st_go_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,15 +426,19 @@ static void set_step_events_per_minute(uint32_t steps_per_minute)
|
|||||||
|
|
||||||
// Planner external interface to start stepper interrupt and execute the blocks in queue. Called
|
// Planner external interface to start stepper interrupt and execute the blocks in queue. Called
|
||||||
// by the main program functions: planner auto-start and run-time command execution.
|
// by the main program functions: planner auto-start and run-time command execution.
|
||||||
|
// TODO: Update sys.cycle_start and feed_hold variables to a sys.state variable. This state
|
||||||
|
// variable will manage all of Grbl's processes and keep them separate.
|
||||||
void st_cycle_start()
|
void st_cycle_start()
|
||||||
{
|
{
|
||||||
if (!sys.cycle_start) {
|
if (!sys.cycle_start) {
|
||||||
if (!sys.feed_hold) {
|
if (!sys.feed_hold) {
|
||||||
sys.cycle_start = true;
|
if (bit_isfalse(sys.execute,EXEC_ALARM)) {
|
||||||
|
sys.cycle_start = true; // Only place this variable is set true.
|
||||||
st_wake_up();
|
st_wake_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Execute a feed hold with deceleration, only during cycle. Called by main program.
|
// Execute a feed hold with deceleration, only during cycle. Called by main program.
|
||||||
void st_feed_hold()
|
void st_feed_hold()
|
||||||
|
@ -29,10 +29,14 @@
|
|||||||
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits
|
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits
|
||||||
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits
|
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits
|
||||||
#define STEPPING_MASK (STEP_MASK | DIRECTION_MASK) // All stepping-related bits (step/direction)
|
#define STEPPING_MASK (STEP_MASK | DIRECTION_MASK) // All stepping-related bits (step/direction)
|
||||||
|
#define STEPPERS_DISABLE_MASK (1<<STEPPERS_DISABLE_BIT)
|
||||||
|
|
||||||
// Initialize and setup the stepper motor subsystem
|
// Initialize and setup the stepper motor subsystem
|
||||||
void st_init();
|
void st_init();
|
||||||
|
|
||||||
|
// Enable steppers, but cycle does not start unless called by motion control or runtime command.
|
||||||
|
void st_wake_up();
|
||||||
|
|
||||||
// Immediately disables steppers
|
// Immediately disables steppers
|
||||||
void st_go_idle();
|
void st_go_idle();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user