Position reporting, refactored system variables, serial print fixes, updated streaming scripts.
- Added machine position reporting to status queries. This will be further developed with part positioning/offsets and maintaining location upon reset. - System variables refactored into a global struct for better readability. - Removed old obsolete Ruby streaming scripts. These were no longer compatible. Updated Python streaming scripts. - Fixed printFloat() and other printing functions. - Decreased planner buffer back to 18 blocks and increased TX serial buffer to 64 bytes. Need the memory space for future developments. - Begun adding run-time modes to grbl, where block delete toggle, mm/in reporting modes, jog modes, etc can be set during runtime. Will be fleshed out and placed into EEPROM when everything is added.
This commit is contained in:
parent
03e2ca7cd5
commit
e8a6bfd179
53
config.h
53
config.h
@ -27,37 +27,38 @@
|
||||
#define BAUD_RATE 9600
|
||||
|
||||
// Define pin-assignments
|
||||
#define STEPPERS_DISABLE_DDR DDRB
|
||||
#define STEPPERS_DISABLE_PORT PORTB
|
||||
#define STEPPERS_DISABLE_BIT 0
|
||||
|
||||
#define STEPPING_DDR DDRD
|
||||
#define STEPPING_PORT PORTD
|
||||
#define X_STEP_BIT 2
|
||||
#define Y_STEP_BIT 3
|
||||
#define Z_STEP_BIT 4
|
||||
#define X_DIRECTION_BIT 5
|
||||
#define Y_DIRECTION_BIT 6
|
||||
#define Z_DIRECTION_BIT 7
|
||||
#define X_STEP_BIT 2 // Uno Digital Pin 2
|
||||
#define Y_STEP_BIT 3 // Uno Digital Pin 3
|
||||
#define Z_STEP_BIT 4 // Uno Digital Pin 4
|
||||
#define X_DIRECTION_BIT 5 // Uno Digital Pin 5
|
||||
#define Y_DIRECTION_BIT 6 // Uno Digital Pin 6
|
||||
#define Z_DIRECTION_BIT 7 // Uno Digital Pin 7
|
||||
|
||||
#define STEPPERS_DISABLE_DDR DDRB
|
||||
#define STEPPERS_DISABLE_PORT PORTB
|
||||
#define STEPPERS_DISABLE_BIT 0 // Uno Digital Pin 8
|
||||
|
||||
#define LIMIT_DDR DDRB
|
||||
#define LIMIT_PIN PINB
|
||||
#define X_LIMIT_BIT 1
|
||||
#define Y_LIMIT_BIT 2
|
||||
#define Z_LIMIT_BIT 3
|
||||
#define X_LIMIT_BIT 1 // Uno Digital Pin 9
|
||||
#define Y_LIMIT_BIT 2 // Uno Digital Pin 10
|
||||
#define Z_LIMIT_BIT 3 // Uno Digital Pin 11
|
||||
|
||||
#define SPINDLE_ENABLE_DDR DDRB
|
||||
#define SPINDLE_ENABLE_PORT PORTB
|
||||
#define SPINDLE_ENABLE_BIT 4
|
||||
#define SPINDLE_ENABLE_BIT 4 // Uno Digital Pin 12
|
||||
|
||||
#define SPINDLE_DIRECTION_DDR DDRB
|
||||
#define SPINDLE_DIRECTION_PORT PORTB
|
||||
#define SPINDLE_DIRECTION_BIT 5
|
||||
#define SPINDLE_DIRECTION_BIT 5 // Uno Digital Pin 13
|
||||
|
||||
// Define runtime command special characters. These characters are 'picked-off' directly from the
|
||||
// serial read data stream and are not passed to the grbl line execution parser. Select characters
|
||||
// that do not and must not exist in the streamed g-code program. ASCII control characters may be
|
||||
// used, if they are available per user setup.
|
||||
// used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in
|
||||
// g-code programs, maybe selected for interface programs.
|
||||
// TODO: Solidify these default characters. Temporary for now.
|
||||
#define CMD_STATUS_REPORT '?'
|
||||
#define CMD_FEED_HOLD '!'
|
||||
@ -70,8 +71,8 @@
|
||||
// entering g-code into grbl, i.e. locating part zero or simple manual machining. If the axes drift,
|
||||
// grbl has no way to know this has happened, since stepper motors are open-loop control. Depending
|
||||
// on the machine, this parameter may need to be larger or smaller than the default time.
|
||||
// NOTE: If defined 0, the delay will not be compiled.
|
||||
#define STEPPER_IDLE_LOCK_TIME 25 // (milliseconds) - Integer >= 0
|
||||
// NOTE: If commented out, the delay will not be compiled.
|
||||
#define STEPPER_IDLE_LOCK_TIME 25 // (milliseconds) - Integer > 0
|
||||
|
||||
// The temporal resolution of the acceleration management subsystem. Higher number give smoother
|
||||
// acceleration but may impact performance.
|
||||
@ -109,4 +110,20 @@
|
||||
// time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays.
|
||||
#define DWELL_TIME_STEP 50 // Integer (milliseconds)
|
||||
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
// TODO: The following options are set as compile-time options for now, until the next EEPROM
|
||||
// settings version has solidified.
|
||||
#define CYCLE_AUTO_START 1 // Cycle auto-start boolean flag for the planner.
|
||||
#define BLOCK_DELETE_ENABLE 0 // Block delete enable/disable flag during g-code parsing
|
||||
#define REPORT_INCH_MODE 0 // Status reporting unit mode (1 = inch, 0 = mm)
|
||||
#if REPORT_INCH_MODE
|
||||
#define DECIMAL_PLACES 3
|
||||
#define DECIMAL_MULTIPLIER 1000 // 10^DECIMAL_PLACES
|
||||
#else
|
||||
#define DECIMAL_PLACES 2 // mm-mode
|
||||
#define DECIMAL_MULTIPLIER 100
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
2
gcode.c
2
gcode.c
@ -32,8 +32,6 @@
|
||||
#include "errno.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#define MM_PER_INCH (25.4)
|
||||
|
||||
#define NEXT_ACTION_DEFAULT 0
|
||||
#define NEXT_ACTION_DWELL 1
|
||||
#define NEXT_ACTION_GO_HOME 2
|
||||
|
48
main.c
48
main.c
@ -4,7 +4,6 @@
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 Sungeun K. Jeon
|
||||
Copyright (c) 2011 Jens Geisler
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -20,11 +19,8 @@
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
#include "config.h"
|
||||
#include "planner.h"
|
||||
#include "nuts_bolts.h"
|
||||
@ -34,15 +30,11 @@
|
||||
#include "gcode.h"
|
||||
#include "protocol.h"
|
||||
#include "limits.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "serial.h"
|
||||
|
||||
#include "print.h"
|
||||
|
||||
// Declare system global variables
|
||||
uint8_t sys_abort; // Global system abort flag
|
||||
volatile uint8_t sys_state; // Global system state variable
|
||||
// Declare system global variable structure
|
||||
system_t sys;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
@ -50,17 +42,18 @@ int main(void)
|
||||
sei(); // Enable interrupts
|
||||
serial_init(BAUD_RATE); // Setup serial baud rate and interrupts
|
||||
st_init(); // Setup stepper pins and interrupt timers
|
||||
sys_abort = true; // Set abort to complete initialization
|
||||
|
||||
sys.abort = true; // Set abort to complete initialization
|
||||
|
||||
while(1) {
|
||||
|
||||
// Upon a system abort, the main program will return to this loop. Once here, it is safe to
|
||||
// re-initialize the system. Upon startup, the system will automatically reset to finish the
|
||||
// initialization process.
|
||||
if (sys_abort) {
|
||||
// Execute system reset
|
||||
sys_state = 0; // Reset system state
|
||||
sys_abort = false; // Release system abort
|
||||
// Execute system reset upon a system abort, where the main program will return to this loop.
|
||||
// Once here, it is safe to re-initialize the system. At startup, the system will automatically
|
||||
// reset to finish the initialization process.
|
||||
if (sys.abort) {
|
||||
|
||||
// Clear all system variables
|
||||
memset(&sys, 0, sizeof(sys));
|
||||
|
||||
// Reset system.
|
||||
serial_reset_read_buffer(); // Clear serial read buffer
|
||||
@ -70,19 +63,14 @@ int main(void)
|
||||
gc_init(); // Set g-code parser to default state
|
||||
spindle_init();
|
||||
limits_init();
|
||||
st_reset(); // Clear stepper subsystem variables.
|
||||
|
||||
// TODO: For now, the stepper subsystem tracks the absolute stepper position from the point
|
||||
// of power up or hard reset. This reset is a soft reset, where the information of the current
|
||||
// position is not lost after a system abort. This is not guaranteed to be correct, since
|
||||
// during an abort, the steppers can lose steps in the immediate stop. However, if a feed
|
||||
// hold is performed before a system abort, this position should be correct. In the next few
|
||||
// updates, this soft reset feature will be fleshed out along with the status reporting and
|
||||
// jogging features.
|
||||
st_reset(); // Clear stepper subsystem variables. Machine position variable is not reset.
|
||||
|
||||
// Print grbl initialization message
|
||||
printPgmString(PSTR("\r\nGrbl " GRBL_VERSION));
|
||||
printPgmString(PSTR("\r\n'$' to dump current settings\r\n"));
|
||||
// Set system runtime defaults
|
||||
// TODO: Eventual move to EEPROM from config.h when all of the new settings are worked out.
|
||||
// Mainly to avoid having to maintain several different versions.
|
||||
#ifdef CYCLE_AUTO_START
|
||||
sys.auto_start = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
protocol_execute_runtime();
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include "limits.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#include "print.h"
|
||||
|
||||
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
|
||||
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
|
||||
// (1 minute)/feed_rate time.
|
||||
@ -56,17 +54,19 @@ void mc_line(double x, double y, double z, double feed_rate, uint8_t invert_feed
|
||||
// Remain in this loop until there is room in the buffer.
|
||||
do {
|
||||
protocol_execute_runtime(); // Check for any run-time commands
|
||||
if (sys_abort) { return; } // Bail, if system abort.
|
||||
if (sys.abort) { return; } // Bail, if system abort.
|
||||
} while ( plan_check_full_buffer() );
|
||||
plan_buffer_line(x, y, z, feed_rate, invert_feed_rate);
|
||||
|
||||
// Auto-cycle start.
|
||||
// TODO: Determine a more efficient and robust way of implementing the auto-starting the cycle.
|
||||
// For example, only auto-starting when the buffer is full; if there was only one g-code command
|
||||
// sent during manual operation; or if there is buffer starvation, making sure it minimizes any
|
||||
// dwelling/motion hiccups. Additionally, these situations must not auto-start during a feed hold.
|
||||
// Only the cycle start runtime command should be able to restart the cycle after a feed hold.
|
||||
st_cycle_start();
|
||||
// Auto-cycle start immediately after planner finishes. Enabled/disabled by grbl settings. During
|
||||
// a feed hold, auto-start is disabled momentarily until the cycle is resumed by the cycle-start
|
||||
// runtime command.
|
||||
// NOTE: This is allows the user to decide to exclusively use the cycle start runtime command to
|
||||
// begin motion or let grbl auto-start it for them. This is useful when: manually cycle-starting
|
||||
// when the buffer is completely full and primed; auto-starting, if there was only one g-code
|
||||
// command sent during manual operation; or if a system is prone to buffer starvation, auto-start
|
||||
// helps make sure it minimizes any dwelling/motion hiccups and keeps the cycle going.
|
||||
if (sys.auto_start) { st_cycle_start(); }
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ void mc_arc(double *position, double *target, double *offset, uint8_t axis_0, ui
|
||||
mc_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
|
||||
// Bail mid-circle on system abort. Runtime command check already performed by mc_line.
|
||||
if (sys_abort) { return; }
|
||||
if (sys.abort) { return; }
|
||||
}
|
||||
// Ensure last segment arrives at target location.
|
||||
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
@ -183,7 +183,7 @@ void mc_dwell(double seconds)
|
||||
while (i > 0) {
|
||||
// NOTE: Check and execute runtime commands during dwell every <= DWELL_TIME_STEP milliseconds.
|
||||
protocol_execute_runtime();
|
||||
if (sys_abort) { return; }
|
||||
if (sys.abort) { return; }
|
||||
_delay_ms(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment
|
||||
i--;
|
||||
}
|
||||
|
49
nuts_bolts.h
49
nuts_bolts.h
@ -32,27 +32,50 @@
|
||||
#define Y_AXIS 1
|
||||
#define Z_AXIS 2
|
||||
|
||||
#define MM_PER_INCH (25.4)
|
||||
|
||||
// Useful macros
|
||||
#define clear_vector(a) memset(a, 0, sizeof(a))
|
||||
#define clear_vector_double(a) memset(a, 0.0, sizeof(a))
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
// Define system state bit map. Used internally by runtime protocol as runtime command flags.
|
||||
// NOTE: The system state is an unsigned 8-bit volatile variable and has a 8 flag limit. The default
|
||||
// flags are always false, so the runtime protocol only needs to check for a non-zero state value to
|
||||
// Bit field and masking macros
|
||||
#define bit(n) (1 << n)
|
||||
#define bit_true(x,mask) (x |= mask)
|
||||
#define bit_false(x,mask) (x &= ~mask)
|
||||
#define bit_toggle(x,mask) (x ^= mask)
|
||||
#define bit_istrue(x,mask) ((x & mask) != 0)
|
||||
#define bit_isfalse(x,mask) ((x & mask) == 0)
|
||||
|
||||
// Define system executor bit map. Used internally by runtime protocol as runtime command flags,
|
||||
// which notifies the main program to execute the specified runtime command asynchronously.
|
||||
// NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default
|
||||
// flags are always false, so the runtime protocol only needs to check for a non-zero value to
|
||||
// know when there is a runtime command to execute.
|
||||
#define BIT_STATUS_REPORT 1 // bit 00000001
|
||||
#define BIT_CYCLE_START 2 // bit 00000010
|
||||
#define BIT_FEED_HOLD 4 // bit 00000100
|
||||
#define BIT_RESET 8 // bit 00001000
|
||||
#define BIT_REPLAN_CYCLE 16 // bit 00010000
|
||||
// #define 32 // bit 00100000
|
||||
// #define 64 // bit 01000000
|
||||
// #define 128 // bit 10000000
|
||||
#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001
|
||||
#define EXEC_CYCLE_START bit(1) // bitmask 00000010
|
||||
#define EXEC_CYCLE_STOP bit(2) // bitmask 00000100
|
||||
#define EXEC_FEED_HOLD bit(3) // bitmask 00001000
|
||||
#define EXEC_RESET bit(4) // bitmask 00010000
|
||||
// #define bit(5) // bitmask 00100000
|
||||
// #define bit(6) // bitmask 01000000
|
||||
// #define bit(7) // bitmask 10000000
|
||||
|
||||
// Define global system variables
|
||||
extern uint8_t sys_abort; // Global system abort flag
|
||||
extern volatile uint8_t sys_state; // Global system state variable
|
||||
typedef struct {
|
||||
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
|
||||
uint8_t feed_hold; // Feed hold flag. Held true during feed hold. Released when ready to resume.
|
||||
uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.
|
||||
|
||||
int32_t position[3]; // Real-time machine position vector in steps. This may need to be a volatile
|
||||
// variable, if problems arise. Subject to change. Need to add coordinate offset
|
||||
// functionality to correctly track part zero and machine zero.
|
||||
|
||||
volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program.
|
||||
volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks.
|
||||
} system_t;
|
||||
extern system_t sys;
|
||||
|
||||
// Read a floating point value from a string. Line points to the input buffer, char_counter
|
||||
// is the indexer pointing to the current character of the line, while double_ptr is
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "protocol.h"
|
||||
|
||||
// The number of linear motions that can be in the plan at any give time
|
||||
#define BLOCK_BUFFER_SIZE 20
|
||||
#define BLOCK_BUFFER_SIZE 18
|
||||
|
||||
static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions
|
||||
static volatile uint8_t block_buffer_head; // Index of the next block to be pushed
|
||||
@ -336,7 +336,7 @@ void plan_synchronize()
|
||||
{
|
||||
while(plan_get_current_block()) {
|
||||
protocol_execute_runtime(); // Check and execute run-time commands
|
||||
if (sys_abort) { return; } // Check for system abort
|
||||
if (sys.abort) { return; } // Check for system abort
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ typedef struct {
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
double nominal_speed; // The nominal speed for this block in mm/min
|
||||
double entry_speed; // Entry speed at previous-current junction in mm/min
|
||||
double entry_speed; // Entry speed at previous-current block junction in mm/min
|
||||
double max_entry_speed; // Maximum allowable junction entry speed in mm/min
|
||||
double millimeters; // The total travel of this block in mm
|
||||
uint8_t recalculate_flag; // Planner flag to recalculate trapezoids on entry junction
|
||||
|
84
print.c
84
print.c
@ -3,6 +3,7 @@
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 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
|
||||
@ -24,12 +25,9 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "config.h"
|
||||
#include "serial.h"
|
||||
|
||||
#ifndef DECIMAL_PLACES
|
||||
#define DECIMAL_PLACES 3
|
||||
#endif
|
||||
|
||||
void printString(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
@ -44,10 +42,45 @@ void printPgmString(const char *s)
|
||||
serial_write(c);
|
||||
}
|
||||
|
||||
void printIntegerInBase(unsigned long n, unsigned long base)
|
||||
// void printIntegerInBase(unsigned long n, unsigned long base)
|
||||
// {
|
||||
// unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
// unsigned long i = 0;
|
||||
//
|
||||
// if (n == 0) {
|
||||
// serial_write('0');
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// while (n > 0) {
|
||||
// buf[i++] = n % base;
|
||||
// n /= base;
|
||||
// }
|
||||
//
|
||||
// for (; i > 0; i--)
|
||||
// serial_write(buf[i - 1] < 10 ?
|
||||
// '0' + buf[i - 1] :
|
||||
// 'A' + buf[i - 1] - 10);
|
||||
// }
|
||||
|
||||
void print_uint8_base2(uint8_t n)
|
||||
{
|
||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
unsigned long i = 0;
|
||||
unsigned char buf[8];
|
||||
uint8_t i = 0;
|
||||
|
||||
for (; i < 8; i++) {
|
||||
buf[i] = n & 1;
|
||||
n >>= 1;
|
||||
}
|
||||
|
||||
for (; i > 0; i--)
|
||||
serial_write('0' + buf[i - 1]);
|
||||
}
|
||||
|
||||
static void print_uint32_base10(unsigned long n)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
uint8_t i = 0;
|
||||
|
||||
if (n == 0) {
|
||||
serial_write('0');
|
||||
@ -55,14 +88,12 @@ void printIntegerInBase(unsigned long n, unsigned long base)
|
||||
}
|
||||
|
||||
while (n > 0) {
|
||||
buf[i++] = n % base;
|
||||
n /= base;
|
||||
buf[i++] = n % 10;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
for (; i > 0; i--)
|
||||
serial_write(buf[i - 1] < 10 ?
|
||||
'0' + buf[i - 1] :
|
||||
'A' + buf[i - 1] - 10);
|
||||
serial_write('0' + buf[i - 1]);
|
||||
}
|
||||
|
||||
void printInteger(long n)
|
||||
@ -71,25 +102,30 @@ void printInteger(long n)
|
||||
serial_write('-');
|
||||
n = -n;
|
||||
}
|
||||
|
||||
printIntegerInBase(n, 10);
|
||||
print_uint32_base10(n);
|
||||
}
|
||||
|
||||
// A very simple
|
||||
void printFloat(double n)
|
||||
{
|
||||
double integer_part, fractional_part;
|
||||
uint8_t decimal_part;
|
||||
fractional_part = modf(n, &integer_part);
|
||||
printInteger(integer_part);
|
||||
if (n < 0) {
|
||||
serial_write('-');
|
||||
n = -n;
|
||||
}
|
||||
n += 0.5/DECIMAL_MULTIPLIER; // Add rounding factor
|
||||
|
||||
long integer_part;
|
||||
integer_part = (int)n;
|
||||
print_uint32_base10(integer_part);
|
||||
|
||||
serial_write('.');
|
||||
fractional_part *= 10;
|
||||
|
||||
n -= integer_part;
|
||||
int decimals = DECIMAL_PLACES;
|
||||
uint8_t decimal_part;
|
||||
while(decimals-- > 0) {
|
||||
decimal_part = floor(fractional_part);
|
||||
n *= 10;
|
||||
decimal_part = (int) n;
|
||||
serial_write('0'+decimal_part);
|
||||
fractional_part -= decimal_part;
|
||||
fractional_part *= 10;
|
||||
n -= decimal_part;
|
||||
}
|
||||
}
|
||||
|
||||
|
3
print.h
3
print.h
@ -3,6 +3,7 @@
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 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
|
||||
@ -30,7 +31,7 @@ void printPgmString(const char *s);
|
||||
|
||||
void printInteger(long n);
|
||||
|
||||
void printIntegerInBase(unsigned long n, unsigned long base);
|
||||
void print_uint8_base2(uint8_t n);
|
||||
|
||||
void printFloat(double n);
|
||||
|
||||
|
87
protocol.c
87
protocol.c
@ -69,15 +69,39 @@ void protocol_status_report()
|
||||
// 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. 'x0.23 y120.4 z2.4'. This is necessary as it minimizes the computational
|
||||
// information, i.e. 'x0.23,y120.4,z2.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 (10-20Hz).
|
||||
printString("Query Received.\r\n"); // Notify that it's working.
|
||||
// short line segments and interface setups that require real-time status reports (5-20Hz).
|
||||
// Additionally, during an abort, the steppers are immediately stopped regardless of what they
|
||||
// are doing. If they are moving, the abort stop can cause grbl to lose steps. However, if a feed
|
||||
// hold is performed before a system abort, the steppers will steadily decelerate at the max
|
||||
// acceleration rate, hence the stopped machine position will be maintained and correct.
|
||||
|
||||
|
||||
// Bare-bones status report. Provides real-time machine position relative to the initialization
|
||||
// or system reset location (0,0,0), not a home position. This section is under construction and
|
||||
// the following are needed: coordinate offsets/updating of machine position relative to home, work
|
||||
// coordinate position?, user setting of output units (mm|inch), compressed (non-human readable)
|
||||
// data for interfaces?, save last known position in EEPROM?
|
||||
#if REPORT_INCH_MODE
|
||||
printString("x"); printFloat(sys.position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH));
|
||||
printString(",y"); printFloat(sys.position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH));
|
||||
printString(",z"); printFloat(sys.position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH));
|
||||
#else
|
||||
printString("x"); printFloat(sys.position[X_AXIS]/(settings.steps_per_mm[X_AXIS]));
|
||||
printString(",y"); printFloat(sys.position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]));
|
||||
printString(",z"); printFloat(sys.position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]));
|
||||
#endif
|
||||
printString("\r\n");
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
iscomment = false;
|
||||
}
|
||||
@ -87,40 +111,46 @@ void protocol_init()
|
||||
// program, primarily where there may be a while loop waiting for a buffer to clear space or any
|
||||
// point where the execution time from the last check point may be more than a fraction of a second.
|
||||
// This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code
|
||||
// parsing and planning functions.
|
||||
// NOTE: The sys_state variable flags are set by the serial read subprogram, except where noted.
|
||||
// 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 to handles them, removing the need to
|
||||
// define more computationally-expensive volatile variables.
|
||||
// NOTE: The sys.execute variable flags are set by the serial read subprogram, except where noted.
|
||||
void protocol_execute_runtime()
|
||||
{
|
||||
if (sys_state) { // Enter only if any bit flag is enabled
|
||||
if (sys.execute) { // Enter only if any bit flag is true
|
||||
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
|
||||
|
||||
// System abort. Steppers have already been force stopped.
|
||||
if (sys_state & BIT_RESET) {
|
||||
sys_abort = true;
|
||||
if (rt_exec & EXEC_RESET) {
|
||||
sys.abort = true;
|
||||
return; // Nothing else to do but exit.
|
||||
}
|
||||
|
||||
// Execute and serial print status
|
||||
if (sys_state & BIT_STATUS_REPORT) {
|
||||
if (rt_exec & EXEC_STATUS_REPORT) {
|
||||
bit_false(sys.execute,EXEC_STATUS_REPORT);
|
||||
protocol_status_report();
|
||||
sys_state ^= BIT_STATUS_REPORT; // Toggle off
|
||||
}
|
||||
|
||||
// Initiate stepper feed hold
|
||||
if (sys_state & BIT_FEED_HOLD) {
|
||||
st_feed_hold();
|
||||
sys_state ^= BIT_FEED_HOLD; // Toggle off
|
||||
if (rt_exec & EXEC_FEED_HOLD) {
|
||||
st_feed_hold(); // Initiate feed hold.
|
||||
bit_false(sys.execute,EXEC_FEED_HOLD);
|
||||
}
|
||||
|
||||
// Re-plans the buffer after a feed hold completes
|
||||
// NOTE: BIT_REPLAN_CYCLE is set by the stepper subsystem when the feed hold is complete.
|
||||
if (sys_state & BIT_REPLAN_CYCLE) {
|
||||
// Reinitializes the stepper module running flags and re-plans the buffer after a feed hold.
|
||||
// NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
|
||||
if (rt_exec & EXEC_CYCLE_STOP) {
|
||||
st_cycle_reinitialize();
|
||||
sys_state ^= BIT_REPLAN_CYCLE; // Toggle off
|
||||
bit_false(sys.execute,EXEC_CYCLE_STOP);
|
||||
}
|
||||
|
||||
if (sys_state & BIT_CYCLE_START) {
|
||||
if (rt_exec & EXEC_CYCLE_START) {
|
||||
st_cycle_start(); // Issue cycle start command to stepper subsystem
|
||||
sys_state ^= BIT_CYCLE_START; // Toggle off
|
||||
#ifdef CYCLE_AUTO_START
|
||||
sys.auto_start = true; // Re-enable auto start after feed hold.
|
||||
#endif
|
||||
bit_false(sys.execute,EXEC_CYCLE_START);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,6 +160,15 @@ void protocol_execute_runtime()
|
||||
uint8_t protocol_execute_line(char *line)
|
||||
{
|
||||
if(line[0] == '$') {
|
||||
|
||||
// TODO: Re-write this '$' as a way to change runtime settings without having to reset, i.e.
|
||||
// auto-starting, status query output formatting and type, jog mode (axes, direction, and
|
||||
// nominal feedrate), toggle block delete, etc. This differs from the EEPROM settings, as they
|
||||
// are considered defaults and loaded upon startup/reset.
|
||||
// This use is envisioned where '$' itself dumps settings and help. Defined characters
|
||||
// proceeding the '$' may be used to setup modes, such as jog mode with a '$J=X100' for X-axis
|
||||
// motion with a nominal feedrate of 100mm/min. Writing EEPROM settings will likely stay the
|
||||
// same or similar. Should be worked out in upcoming releases.
|
||||
return(settings_execute_line(line)); // Delegate lines starting with '$' to the settings module
|
||||
|
||||
// } else if {
|
||||
@ -165,7 +204,7 @@ void protocol_process()
|
||||
// NOTE: If there is no line, this function should quickly return to the main program when
|
||||
// the buffer empties of non-executable data.
|
||||
protocol_execute_runtime();
|
||||
if (sys_abort) { return; } // Bail to main program upon system abort
|
||||
if (sys.abort) { return; } // Bail to main program upon system abort
|
||||
|
||||
if (char_counter > 0) {// Line is complete. Then execute!
|
||||
line[char_counter] = 0; // Terminate string
|
||||
@ -176,6 +215,7 @@ void protocol_process()
|
||||
}
|
||||
char_counter = 0; // Reset line buffer index
|
||||
iscomment = false; // Reset comment flag
|
||||
|
||||
} else {
|
||||
if (iscomment) {
|
||||
// Throw away all comment characters
|
||||
@ -187,9 +227,10 @@ void protocol_process()
|
||||
if (c <= ' ') {
|
||||
// Throw away whitepace and control characters
|
||||
} else if (c == '/') {
|
||||
// Disable block delete and throw away character
|
||||
// To enable block delete, uncomment following line. Will ignore until EOL.
|
||||
// iscomment = true;
|
||||
// Disable block delete and throw away characters. Will ignore until EOL.
|
||||
#if BLOCK_DELETE_ENABLE
|
||||
iscomment = true;
|
||||
#endif
|
||||
} else if (c == '(') {
|
||||
// Enable comments flag and ignore all characters until ')' or EOL.
|
||||
iscomment = true;
|
||||
|
@ -1,6 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
Simple g-code streaming script for grbl
|
||||
|
||||
Provided as an illustration of the basic communication interface
|
||||
for grbl. When grbl has finished parsing the g-code block, it will
|
||||
return an 'ok' or 'error' response. When the planner buffer is full,
|
||||
grbl will not send a response until the planner buffer clears space.
|
||||
|
||||
G02/03 arcs are special exceptions, where they inject short line
|
||||
segments directly into the planner. So there may not be a response
|
||||
from grbl for the duration of the arc.
|
||||
"""
|
||||
|
||||
import serial
|
||||
|
80
script/stream.py
Executable file
80
script/stream.py
Executable file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
Stream g-code to grbl controller
|
||||
|
||||
This script differs from the simple_stream.py script by
|
||||
tracking the number of characters in grbl's serial read
|
||||
buffer. This allows grbl to fetch the next line directly
|
||||
from the serial buffer and does not have to wait for a
|
||||
response from the computer. This effectively adds another
|
||||
buffer layer to prevent buffer starvation.
|
||||
|
||||
TODO: - Add runtime command capabilities
|
||||
|
||||
Version: SKJ.20120104
|
||||
"""
|
||||
|
||||
import serial
|
||||
import re
|
||||
import time
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
RX_BUFFER_SIZE = 128
|
||||
|
||||
# Define command line argument interface
|
||||
parser = argparse.ArgumentParser(description='Stream g-code file to grbl. (pySerial library required)')
|
||||
parser.add_argument('gcode', type=argparse.FileType('r'),
|
||||
help='g-code filename to be streamed')
|
||||
parser.add_argument('device',
|
||||
help='serial device path')
|
||||
parser.add_argument('-q','--quiet',action='store_true', default=False,
|
||||
help='suppress output text')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Initialize
|
||||
s = serial.Serial(args.device_file,9600)
|
||||
f = args.gcode_file
|
||||
verbose = True
|
||||
if args.quiet : verbose = False
|
||||
|
||||
# Wake up grbl
|
||||
print "Initializing grbl..."
|
||||
s.write("\r\n\r\n")
|
||||
|
||||
# Wait for grbl to initialize and flush startup text in serial input
|
||||
time.sleep(2)
|
||||
s.flushInput()
|
||||
|
||||
# Stream g-code to grbl
|
||||
print "Streaming ", args.gcode_file.name, " to ", args.device_file
|
||||
l_count = 0
|
||||
g_count = 0
|
||||
c_line = []
|
||||
for line in f:
|
||||
l_count += 1 # Iterate line counter
|
||||
# l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize
|
||||
l_block = line.strip()
|
||||
c_line.append(len(l_block)) # Track number of characters in grbl serial read buffer
|
||||
grbl_out = ''
|
||||
while sum(c_line) >= RX_BUFFER_SIZE-1 | s.inWaiting() :
|
||||
out_temp = s.readline().strip() # Wait for grbl response
|
||||
if out_temp not in ['ok','error'] :
|
||||
print " Debug: ",out_temp # Debug response
|
||||
else :
|
||||
grbl_out += out_temp;
|
||||
g_count += 1 # Iterate g-code counter
|
||||
grbl_out += str(g_count); # Add line finished indicator
|
||||
del c_line[0]
|
||||
if verbose: print "SND: " + str(l_count) + " : " + l_block,
|
||||
s.write(l_block + '\n') # Send block to grbl
|
||||
if verbose : print "BUF:",str(sum(c_line)),"REC:",grbl_out
|
||||
|
||||
# Wait for user input after streaming is completed
|
||||
print "G-code streaming finished!\n"
|
||||
print "WARNING: Wait until grbl completes buffered g-code blocks before exiting."
|
||||
raw_input(" Press <Enter> to exit and disable grbl.")
|
||||
|
||||
# Close file and serial port
|
||||
f.close()
|
||||
s.close()
|
14
serial.c
14
serial.c
@ -31,7 +31,7 @@
|
||||
#include "protocol.h"
|
||||
|
||||
#define RX_BUFFER_SIZE 128
|
||||
#define TX_BUFFER_SIZE 32
|
||||
#define TX_BUFFER_SIZE 64
|
||||
|
||||
uint8_t rx_buffer[RX_BUFFER_SIZE];
|
||||
uint8_t rx_buffer_head = 0;
|
||||
@ -72,7 +72,7 @@ void serial_write(uint8_t data) {
|
||||
// Wait until there is space in the buffer
|
||||
while (next_head == tx_buffer_tail) {
|
||||
protocol_execute_runtime(); // Check for any run-time commands
|
||||
if (sys_abort) { return; } // Bail, if system abort.
|
||||
if (sys.abort) { return; } // Bail, if system abort.
|
||||
}
|
||||
|
||||
// Store data and advance head
|
||||
@ -124,15 +124,15 @@ ISR(USART_RX_vect)
|
||||
// Pick off runtime command characters directly from the serial stream. These characters are
|
||||
// not passed into the buffer, but these set system state flag bits for runtime execution.
|
||||
switch (data) {
|
||||
case CMD_STATUS_REPORT: sys_state |= BIT_STATUS_REPORT; break; // Set as true
|
||||
case CMD_CYCLE_START: sys_state |= BIT_CYCLE_START; break; // Set as true
|
||||
case CMD_FEED_HOLD: sys_state |= BIT_FEED_HOLD; break; // Set as true
|
||||
case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true
|
||||
case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true
|
||||
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
|
||||
case CMD_RESET:
|
||||
// Immediately force stepper subsystem idle at an interrupt level.
|
||||
if (!(sys_state & BIT_RESET)) { // Force stop only first time.
|
||||
if (!(sys.execute & EXEC_RESET)) { // Force stop only first time.
|
||||
st_go_idle();
|
||||
}
|
||||
sys_state |= BIT_RESET; // Set as true
|
||||
sys.execute |= EXEC_RESET; // Set as true
|
||||
break;
|
||||
default : // Write character to buffer
|
||||
rx_buffer[rx_buffer_head] = data;
|
||||
|
16
settings.c
16
settings.c
@ -54,6 +54,7 @@ typedef struct {
|
||||
#define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
|
||||
#define DEFAULT_STEPPING_INVERT_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT))
|
||||
// #define DEFAULT_AUTO_START 1 // Boolean
|
||||
|
||||
void settings_reset() {
|
||||
settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM;
|
||||
@ -77,10 +78,11 @@ void settings_dump() {
|
||||
printPgmString(PSTR(" (mm/min default feed rate)\r\n$5 = ")); printFloat(settings.default_seek_rate);
|
||||
printPgmString(PSTR(" (mm/min default seek rate)\r\n$6 = ")); printFloat(settings.mm_per_arc_segment);
|
||||
printPgmString(PSTR(" (mm/arc segment)\r\n$7 = ")); printInteger(settings.invert_mask);
|
||||
printPgmString(PSTR(" (step port invert mask. binary = ")); printIntegerInBase(settings.invert_mask, 2);
|
||||
printPgmString(PSTR(" (step port invert mask. 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 in mm/sec^2)\r\n$9 = ")); printFloat(settings.junction_deviation);
|
||||
printPgmString(PSTR(" (cornering junction deviation in mm)"));
|
||||
printPgmString(PSTR(" (cornering junction deviation in mm)"));//\r\n$10 = ")); // printInteger(settings.auto_start);
|
||||
// printPgmString(PSTR(" (auto-start boolean)"));
|
||||
printPgmString(PSTR("\r\n'$x=value' to set parameter or just '$' to dump current settings\r\n"));
|
||||
}
|
||||
|
||||
@ -131,6 +133,7 @@ int read_settings() {
|
||||
}
|
||||
settings.acceleration = DEFAULT_ACCELERATION;
|
||||
settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
|
||||
// settings.auto_start = DEFAULT_AUTO_START;
|
||||
write_settings();
|
||||
} else if ((version == 2) || (version == 3)) {
|
||||
// Migrate from settings version 2 and 3
|
||||
@ -139,7 +142,15 @@ int read_settings() {
|
||||
}
|
||||
if (version == 2) { settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; }
|
||||
settings.acceleration *= 3600; // Convert to mm/min^2 from mm/sec^2
|
||||
// settings.auto_start = DEFAULT_AUTO_START;
|
||||
write_settings();
|
||||
// } else if (version == 4) {
|
||||
// // Migrate from settings version 4
|
||||
// if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t)))) {
|
||||
// return(false);
|
||||
// }
|
||||
// settings.auto_start = DEFAULT_AUTO_START;
|
||||
// write_settings();
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
@ -167,6 +178,7 @@ void settings_store_setting(int parameter, double value) {
|
||||
case 7: settings.invert_mask = trunc(value); break;
|
||||
case 8: settings.acceleration = value*60*60; break; // Convert to mm/min^2 for grbl internal use.
|
||||
case 9: settings.junction_deviation = fabs(value); break;
|
||||
// case 10: settings.auto_start = value; break;
|
||||
default:
|
||||
printPgmString(PSTR("Unknown parameter\r\n"));
|
||||
return;
|
||||
|
@ -22,7 +22,6 @@
|
||||
#ifndef settings_h
|
||||
#define settings_h
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
66
stepper.c
66
stepper.c
@ -4,7 +4,6 @@
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 Sungeun K. Jeon
|
||||
Copyright (c) 2011 Jens Geisler
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -34,8 +33,6 @@
|
||||
#include "planner.h"
|
||||
#include "limits.h"
|
||||
|
||||
#include "print.h"
|
||||
|
||||
// Some useful constants
|
||||
#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
|
||||
@ -46,9 +43,6 @@
|
||||
|
||||
// Stepper state variable. Contains running data and trapezoid variables.
|
||||
typedef struct {
|
||||
volatile uint8_t cycle_start; // Cycle start flag
|
||||
volatile uint8_t feed_hold; // Feed hold flag
|
||||
|
||||
// Used by the bresenham line algorithm
|
||||
int32_t counter_x, // Counter variables for the bresenham line tracer
|
||||
counter_y,
|
||||
@ -62,10 +56,9 @@ typedef struct {
|
||||
// pace without allocating a separate timer
|
||||
uint32_t trapezoid_adjusted_rate; // The current rate of step_events according to the trapezoid generator
|
||||
uint32_t min_safe_rate; // Minimum safe rate for full deceleration rate reduction step. Otherwise halves step_rate.
|
||||
} stepper_state_t;
|
||||
} stepper_t;
|
||||
|
||||
static stepper_state_t st;
|
||||
static int32_t st_position[3]; // Track current position in steps from initialization state.
|
||||
static stepper_t st;
|
||||
static block_t *current_block; // A pointer to the block currently being traced
|
||||
|
||||
// Used by the stepper driver interrupt
|
||||
@ -112,7 +105,7 @@ void st_go_idle()
|
||||
TIMSK1 &= ~(1<<OCIE1A);
|
||||
// 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.
|
||||
#if STEPPER_IDLE_LOCK_TIME
|
||||
#ifdef STEPPER_IDLE_LOCK_TIME
|
||||
_delay_ms(STEPPER_IDLE_LOCK_TIME);
|
||||
#endif
|
||||
// Disable steppers by setting stepper disable
|
||||
@ -146,6 +139,7 @@ static uint8_t iterate_trapezoid_cycle_counter()
|
||||
// interrupt doing its thing, not that big of a deal, but the latter cause is unknown and worrisome. Need
|
||||
// to track down what is causing this problem. Functionally, this shouldn't cause any noticeable issues
|
||||
// as long as stepper drivers have a pulse minimum of 1usec or so (Pololu and any Allegro IC are ok).
|
||||
// This seems to be an inherent issue that dates all the way back to Simen's v0.6b.
|
||||
|
||||
ISR(TIMER1_COMPA_vect,ISR_NOBLOCK)
|
||||
{
|
||||
@ -165,7 +159,8 @@ ISR(TIMER1_COMPA_vect,ISR_NOBLOCK)
|
||||
// Anything in the buffer? If so, initialize next motion.
|
||||
current_block = plan_get_current_block();
|
||||
if (current_block != NULL) {
|
||||
if (!st.feed_hold) { // During feed hold, do not update rate and trap counter. Keep decelerating.
|
||||
if (!sys.feed_hold) {
|
||||
// During feed hold, do not update rate and trap counter. Keep decelerating.
|
||||
st.trapezoid_adjusted_rate = current_block->initial_rate;
|
||||
set_step_events_per_minute(st.trapezoid_adjusted_rate); // Initialize cycles_per_step_event
|
||||
st.trapezoid_tick_cycle_counter = CYCLES_PER_ACCELERATION_TICK/2; // Start halfway for midpoint rule.
|
||||
@ -177,9 +172,9 @@ ISR(TIMER1_COMPA_vect,ISR_NOBLOCK)
|
||||
st.event_count = current_block->step_event_count;
|
||||
st.step_events_completed = 0;
|
||||
} else {
|
||||
st.cycle_start = false;
|
||||
st.feed_hold = false;
|
||||
st_go_idle();
|
||||
sys.cycle_start = false;
|
||||
bit_true(sys.execute,EXEC_CYCLE_STOP); // Flag main program for cycle end
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,29 +185,29 @@ ISR(TIMER1_COMPA_vect,ISR_NOBLOCK)
|
||||
if (st.counter_x > 0) {
|
||||
out_bits |= (1<<X_STEP_BIT);
|
||||
st.counter_x -= st.event_count;
|
||||
if (out_bits & (1<<X_DIRECTION_BIT)) { st_position[X_AXIS]--; }
|
||||
else { st_position[X_AXIS]++; }
|
||||
if (out_bits & (1<<X_DIRECTION_BIT)) { sys.position[X_AXIS]--; }
|
||||
else { sys.position[X_AXIS]++; }
|
||||
}
|
||||
st.counter_y += current_block->steps_y;
|
||||
if (st.counter_y > 0) {
|
||||
out_bits |= (1<<Y_STEP_BIT);
|
||||
st.counter_y -= st.event_count;
|
||||
if (out_bits & (1<<Y_DIRECTION_BIT)) { st_position[Y_AXIS]--; }
|
||||
else { st_position[Y_AXIS]++; }
|
||||
if (out_bits & (1<<Y_DIRECTION_BIT)) { sys.position[Y_AXIS]--; }
|
||||
else { sys.position[Y_AXIS]++; }
|
||||
}
|
||||
st.counter_z += current_block->steps_z;
|
||||
if (st.counter_z > 0) {
|
||||
out_bits |= (1<<Z_STEP_BIT);
|
||||
st.counter_z -= st.event_count;
|
||||
if (out_bits & (1<<Z_DIRECTION_BIT)) { st_position[Z_AXIS]--; }
|
||||
else { st_position[Z_AXIS]++; }
|
||||
if (out_bits & (1<<Z_DIRECTION_BIT)) { sys.position[Z_AXIS]--; }
|
||||
else { sys.position[Z_AXIS]++; }
|
||||
}
|
||||
|
||||
st.step_events_completed++; // Iterate step events
|
||||
|
||||
// While in block steps, check for de/ac-celeration events and execute them accordingly.
|
||||
if (st.step_events_completed < current_block->step_event_count) {
|
||||
if (st.feed_hold) {
|
||||
if (sys.feed_hold) {
|
||||
// Check for and execute feed hold by enforcing a steady deceleration from the moment of
|
||||
// execution. The rate of deceleration is limited by rate_delta and will never decelerate
|
||||
// faster or slower than in normal operation. If the distance required for the feed hold
|
||||
@ -225,10 +220,11 @@ ISR(TIMER1_COMPA_vect,ISR_NOBLOCK)
|
||||
// If deceleration complete, set system flags and shutdown steppers.
|
||||
if (st.trapezoid_adjusted_rate <= current_block->rate_delta) {
|
||||
// Just go idle. Do not NULL current block. The bresenham algorithm variables must
|
||||
// remain intact to ensure the stepper path is exactly the same.
|
||||
st.cycle_start = false;
|
||||
// remain intact to ensure the stepper path is exactly the same. Feed hold is still
|
||||
// active and is released after the buffer has been reinitialized.
|
||||
st_go_idle();
|
||||
sys_state |= BIT_REPLAN_CYCLE; // Flag main program that feed hold is complete.
|
||||
sys.cycle_start = false;
|
||||
bit_true(sys.execute,EXEC_CYCLE_STOP); // Flag main program that feed hold is complete.
|
||||
} else {
|
||||
st.trapezoid_adjusted_rate -= current_block->rate_delta;
|
||||
set_step_events_per_minute(st.trapezoid_adjusted_rate);
|
||||
@ -340,9 +336,6 @@ void st_init()
|
||||
TCCR2B = (1<<CS21); // Full speed, 1/8 prescaler
|
||||
TIMSK2 |= (1<<TOIE2);
|
||||
|
||||
// Initialize machine position vector
|
||||
clear_vector(st_position);
|
||||
|
||||
// Start in the idle state
|
||||
st_go_idle();
|
||||
}
|
||||
@ -394,12 +387,12 @@ 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
|
||||
// by planner auto-start and run-time command functions.
|
||||
// by the main program functions: planner auto-start and run-time command execution.
|
||||
void st_cycle_start()
|
||||
{
|
||||
if (!st.cycle_start) {
|
||||
if (!st.feed_hold) {
|
||||
st.cycle_start = true;
|
||||
if (!sys.cycle_start) {
|
||||
if (!sys.feed_hold) {
|
||||
sys.cycle_start = true;
|
||||
st_wake_up();
|
||||
}
|
||||
}
|
||||
@ -408,9 +401,10 @@ void st_cycle_start()
|
||||
// Execute a feed hold with deceleration, only during cycle. Called by main program.
|
||||
void st_feed_hold()
|
||||
{
|
||||
if (!st.feed_hold) {
|
||||
if (st.cycle_start) {
|
||||
st.feed_hold = true;
|
||||
if (!sys.feed_hold) {
|
||||
if (sys.cycle_start) {
|
||||
sys.auto_start = false; // Disable planner auto start upon feed hold.
|
||||
sys.feed_hold = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -422,6 +416,7 @@ void st_feed_hold()
|
||||
// Only the planner de/ac-celerations profiles and stepper rates have been updated.
|
||||
void st_cycle_reinitialize()
|
||||
{
|
||||
if (current_block != NULL) {
|
||||
// Replan buffer from the feed hold stop location.
|
||||
plan_cycle_reinitialize(current_block->step_event_count - st.step_events_completed);
|
||||
// Update initial rate and timers after feed hold.
|
||||
@ -429,5 +424,8 @@ void st_cycle_reinitialize()
|
||||
set_step_events_per_minute(st.trapezoid_adjusted_rate);
|
||||
st.trapezoid_tick_cycle_counter = CYCLES_PER_ACCELERATION_TICK/2; // Start halfway for midpoint rule.
|
||||
st.step_events_completed = 0;
|
||||
st.feed_hold = false; // Release feed hold. Cycle is ready to re-start.
|
||||
}
|
||||
sys.feed_hold = false; // Release feed hold. Cycle is ready to re-start.
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user