Skip to content

Commit

Permalink
Planner and printFloat update.
Browse files Browse the repository at this point in the history
- Planner model update. Improves performance for machines with
different accelerations on each axes. Particularly for 3D carving.

- Print float update to print 13 (from 10) characters. Help reduce
print errors for unusually long floating point values.
  • Loading branch information
chamnit authored and chamnit committed May 11, 2016
1 parent d5decf8 commit 2b82c42
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 47 deletions.
38 changes: 10 additions & 28 deletions doc/log/commit_log_v1.0d.txt
@@ -1,3 +1,13 @@
----------------
Date: 2016-04-10
Author: chamnit
Subject: Alarm and safety door bug fix.

- Typo in protocol.c caused a safety door to lock out the system during
an alarm. The correct character should keep that from happening and
bring back the original door/alarm behavior.


----------------
Date: 2016-04-04
Author: Sonny Jeon
Expand Down Expand Up @@ -60,31 +70,3 @@ time being. These removal options will go away eventually before they
become hard-coded in. (They will be toggle-able with the status report
mask in settings though.)


----------------
Date: 2016-03-19
Author: Sonny Jeon
Subject: Removed 328p-related code. Enabled options by default.

- Removed all of the 328p-related code, which seemed to clean up things
quite a bit without all those ifdefs everywhere.

- Since the 328p was very memory and flash limited, lots of
compile-time options were disabled by default. These have been now been
enabled by default. As they are considered generally helpful and does
not significantly impact how Grbl runs.

- For example, status reports can now report back real time feed rate
and line number being executed. Variable spindle is standard with a
separate spindle enable pin. Grbl will now check if a user setting has
exceeded the maximum step frequency and report an error, if so. And
finally, M7 flood coolant is enabled.

- In addition, all buffers have been significantly increased to take
advantage of the additional memory available. The planner buffer can
plan up to 36 motions. The serial buffers have been doubled in size
(256/128 bytes RX/TX). And the longest line Grbl can accept is 256
bytes, per the g-code standard (Grbl 328p is limited to 80).

- Removed the cpu_map folder, since this version is strictly Mega2560.

2 changes: 1 addition & 1 deletion grbl/grbl.h
Expand Up @@ -23,7 +23,7 @@

// Grbl versioning system
#define GRBL_VERSION "1.0d"
#define GRBL_VERSION_BUILD "20160410"
#define GRBL_VERSION_BUILD "20160510"

// Define standard libraries used by Grbl.
#include <avr/io.h>
Expand Down
43 changes: 26 additions & 17 deletions grbl/planner.c
Expand Up @@ -272,8 +272,6 @@ uint8_t plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rat
block->line_number = line_number;

// Compute and store initial move distance data.
// TODO: After this for-loop, we don't touch the stepper algorithm data. Might be a good idea
// to try to keep these types of things completely separate from the planner for portability.
int32_t target_steps[N_AXIS], position_steps[N_AXIS];
float unit_vec[N_AXIS], delta_mm;
uint8_t idx;
Expand Down Expand Up @@ -326,7 +324,6 @@ uint8_t plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rat
if (block->step_event_count == 0) { return(PLAN_EMPTY_BLOCK); }

// Adjust feed_rate value to mm/min depending on type of rate input (normal, inverse time, or rapids)
// TODO: Need to distinguish a rapids vs feed move for overrides. Some flag of some sort.
if (feed_rate < 0) { feed_rate = SOME_LARGE_VALUE; } // Scaled down to absolute max/rapids rate later
else if (invert_feed_rate) { feed_rate *= block->millimeters; }
if (feed_rate < MINIMUM_FEED_RATE) { feed_rate = MINIMUM_FEED_RATE; } // Prevents step generation round-off condition.
Expand All @@ -335,23 +332,26 @@ uint8_t plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rat
// down such that no individual axes maximum values are exceeded with respect to the line direction.
// NOTE: This calculation assumes all axes are orthogonal (Cartesian) and works with ABC-axes,
// if they are also orthogonal/independent. Operates on the absolute value of the unit vector.
float inverse_unit_vec_value;
float junction_vec[N_AXIS];
float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple float divides
float junction_cos_theta = 0.0;
float magnitude_junction_vec = 0.0;
for (idx=0; idx<N_AXIS; idx++) {
if (unit_vec[idx] != 0) { // Avoid divide by zero.
unit_vec[idx] *= inverse_millimeters; // Complete unit vector calculation
inverse_unit_vec_value = fabs(1.0/unit_vec[idx]); // Inverse to remove multiple float divides.

// Check and limit feed rate against max individual axis velocities and accelerations
feed_rate = min(feed_rate,settings.max_rate[idx]*inverse_unit_vec_value);
block->acceleration = min(block->acceleration,settings.acceleration[idx]*inverse_unit_vec_value);

block->acceleration = min(block->acceleration,fabs(settings.acceleration[idx]/unit_vec[idx]));
feed_rate = min(feed_rate,fabs(settings.max_rate[idx]/unit_vec[idx]));
// Incrementally compute cosine of angle between previous and current path. Cos(theta) of the junction
// between the current move and the previous move is simply the dot product of the two unit vectors,
// where prev_unit_vec is negative. Used later to compute maximum junction speed.
junction_cos_theta -= pl.previous_unit_vec[idx] * unit_vec[idx];
junction_cos_theta -= pl.previous_unit_vec[idx]*unit_vec[idx];
}
// Compute junction acceleration vector. Magnitude completed later when necessary.
junction_vec[idx] = unit_vec[idx]-pl.previous_unit_vec[idx];
magnitude_junction_vec += junction_vec[idx]*junction_vec[idx];
}

// TODO: Need to check this method handling zero junction speeds when starting from rest.
Expand Down Expand Up @@ -386,19 +386,28 @@ uint8_t plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rat
memory in the event of a feedrate override changing the nominal speeds of blocks, which can
change the overall maximum entry speed conditions of all blocks.
*/

// NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
if (junction_cos_theta > 0.999999) {
// For a 0 degree acute junction, just set minimum junction speed.
block->max_junction_speed_sqr = MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED;
} else {
junction_cos_theta = max(junction_cos_theta,-0.999999); // Check for numerical round-off to avoid divide by zero.
float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive.

// TODO: Technically, the acceleration used in calculation needs to be limited by the minimum of the
// two junctions. However, this shouldn't be a significant problem except in extreme circumstances.
block->max_junction_speed_sqr = max( MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED,
(block->acceleration * settings.junction_deviation * sin_theta_d2)/(1.0-sin_theta_d2) );

if (junction_cos_theta < -0.999999) {
// Junction is a straight line or 180 degrees. Junction speed is infinite.
block->max_junction_speed_sqr = SOME_LARGE_VALUE;
} else {
float junction_acceleration = SOME_LARGE_VALUE;
magnitude_junction_vec = sqrt(magnitude_junction_vec); // Complete magnitude calculation.
for (idx=0; idx<N_AXIS; idx++) {
if (junction_vec[idx] != 0) { // Avoid divide by zero.
junction_acceleration = min( junction_acceleration,
fabs((settings.acceleration[idx]*magnitude_junction_vec)/junction_vec[idx]) );
}
}
float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive.
block->max_junction_speed_sqr = max( MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED,
(junction_acceleration * settings.junction_deviation * sin_theta_d2)/(1.0-sin_theta_d2) );
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion grbl/print.c
Expand Up @@ -145,7 +145,7 @@ void printFloat(float n, uint8_t decimal_places)
n += 0.5; // Add rounding factor. Ensures carryover through entire value.

// Generate digits backwards and store in string.
unsigned char buf[10];
unsigned char buf[13];
uint8_t i = 0;
uint32_t a = (long)n;
buf[decimal_places] = '.'; // Place decimal point, even if decimal places are zero.
Expand Down

0 comments on commit 2b82c42

Please sign in to comment.