Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Jerk Acceleration Settings and HAAS G187 Acceleration Profiles #593

Merged
merged 59 commits into from
Dec 30, 2024

Conversation

Dietz0r
Copy link
Contributor

@Dietz0r Dietz0r commented Sep 29, 2024

This adds code to implement 3rd order accleration settings over the acceleration ticks of the stepper loop.

With the default settings of 100 acceleration ticks it will update the acceleration values according to the jerk setting with each 10ms block that gets fed into the stepper loop.
If a CPU is strong enough to run 1000 acceleration ticks that would net a 1ms Jerk Stepper Loop but 100 or 200 ticks work fine.
Tested on 2 independent machines with help from @EmpyreanCNC

Known Issue:
The machine moves a bit erratically/stuttery when getting fed jog commands from either a pendant or the IOSender interface, i think this has to do with how those conitinous jog commands are fed to the controller but i wasnt able to veryify or fix the issue on my end. Normal G-Code file execution works as expected. I hope you might have more insight into why this problem arises.

Also added support for HAAS style G187 acceleration profiles currently set to 20%, 40% 60% 80% and 100% of the max settings to allow for fine control during toolpathes and improved surface finishes.
Gets called as G187 P1 for 100% speed roughing to G187 P5 for 20% slow finishing.

Hope this helps! :)

Dietz0r and others added 30 commits October 30, 2023 11:37
First experimental checkin for constant jerk motions
First experimental checkin for constant jerk motions
First experimental checkin for constant jerk motions
missing semicolon
bugfixing float variables
DEFAULT_X_JERK capitalization
static char added for axis_jerk
@Dietz0r
Copy link
Contributor Author

Dietz0r commented Oct 30, 2024

FYI I'll be back home in a week...

Hope you enjoyed your trip! :)

This means that there should be a setting for the default P value? And cancellation implemented?

I think the most reliable thing would be to have the default value be 100%, so the settings that are set on the axis and be modified from there with the profiles. Saves a setting slot and if you really want to just run at 80% max it's trivial to just add G187 P4 at the start of any code.

The cancellation is a good point! didnt think of that! Will look at it and add it.

This should be !gc_block.words.p to check if a value has been supplied. IMO also check gc_block.words.e, if supplied (true) error out since it is not supported?

So no one accidentally tries to use a real HAAS routine on it? yeah i see it.

settings.c Outdated Show resolved Hide resolved
settings.c Outdated
ActiveAccelProfile = 1; // Initialize machine with 100% Profile

//Acceleration Profiles for G187 P[x] in percent of maximum machine acceleration.
float LookupProfile(uint8_t Profile) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to planner.c as static inlined?
and the return value is either 0 or 1 since you assign the value to Profile before returning it? Use return lookup(profile); instead?
BTW I do not use camel cased or upper case names in the core.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving it to planner.c as static inlined would make it very hard to find if you wanted to have other profiles instead of the generic placeholder 20% ones.

I shied away from making it yet another list of $ settings because it would likely mean a whole slew of settings for however much profiles you wanted. having the lookuptable in settings.c makes it findable though.

maybe move it to the driver my_machine.h because it is a compile time setting?

Copy link
Contributor

@terjeio terjeio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am starting to believe that this PR should be deferred until I get an overdue settings revision done. This so that I do not run into issues later on. I'll look into this in the next few days.

planner.c Outdated
@@ -348,9 +348,28 @@ static inline float limit_acceleration_by_axis_maximum (float *unit_vec)
if (unit_vec[--idx] != 0.0f) // Avoid divide by zero.
limit_value = min(limit_value, fabsf(settings.axis[idx].acceleration / unit_vec[idx]));
} while(idx);
#if ENABLE_ACCELERATION_PROFILES
limit_value *= lookupprofile(gc_state.modal.activeaccelprofile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The profile factor should be passed from gcode.c in the plan_block_t structure. And set it in the plan_data_init() too, perhaps to 1.0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rewrote it so it uses the plan_block_t structure and plan_data_init() function.

How it should now work is the machine initializes with active profile 1 - 1.0 factor. in gcode.c (including reset handling)
plan_data_init() looks up the current factor with the lookupfactor() function.
plan_block_t now has storage for the current_factor and gets it from pl_data->current_factor to calucalte adjusted acceleration limits via limit_value *= block->acceleration_factor;

hope i didnt mess that up too badly

settings.h Outdated Show resolved Hide resolved
settings.h Outdated
@@ -714,6 +718,9 @@ typedef struct {
float steps_per_mm;
float max_rate;
float acceleration;
#if ENABLE_JERK_ACCELERATION
float jerk;
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another potential problem we have to be aware of, the area reserved for global settings may overflow when many axes are configured. I have already switched to claim settings storage for a second PWM spindle from above the area reseved for the core. Perhaps the jerk settings should as well? I'll have to think about that. See nvs.h.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just commited a version with updated settings structures and that adds a permanent field for jerk. I have also reserved ten new axis settings for the core, jerk beeing the first assigned.

If you can update your PR against this version then I will be able to merge it without risking issues with the settings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently at work, will take a look and push latest revision tomorrow night or maybe wednesday!
Thanks for all the work! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved the conflicts. :)

@terjeio
Copy link
Contributor

terjeio commented Dec 26, 2024

Is this nearly ready for merge now?
FYI settings.c is out of sync with the core, one removed function is added again (set_offset_lock) and at least one modified one is duplicated by adding the earlier code (set_homing_enable).

Cleaned up out of sync functions. Most likely a remnant from resolving the merge conflict.
@Dietz0r
Copy link
Contributor Author

Dietz0r commented Dec 26, 2024

Is this nearly ready for merge now? FYI settings.c is out of sync with the core, one removed function is added again (set_offset_lock) and at least one modified one is duplicated by adding the earlier code (set_homing_enable).

The out of sync file might have been from cleaning up the merge conflicts, my apologes.
I just did a test compile to make sure it works. Found one missing declaration.
It does compile but i didnt have time yet to verify that the new G187 code works as it should.

So apart from physical testing i guess it's ready?

edit: just wait a sec, found another issue

@Dietz0r
Copy link
Contributor Author

Dietz0r commented Dec 26, 2024

Okay, seems to be looking good now on my end.

Edit:
Managed to find a spare teensy and did some debugging on it.
Jerk works as expected on gcode files. The setting limit calculations were causing issues so i removed them and adjusted the setting description for "sane" values.
The jogging issue remains. Not sure why but the machine is adamant about going as slow as possible when it reaches the mm_remaining * speed < current_accel / jerk point on a decelleration ramp but it works fine in gcode?

G187 implementation is currently having 2 issues. It throws an error36 after the "ok" when changing p-values and the controller crashes when issuing any movements with it enabled.

It's late now and i will continue debugging later.

planner.c Outdated
@@ -339,7 +339,7 @@ inline static float plan_compute_profile_parameters (plan_block_t *block, float
return nominal_speed;
}

static inline float limit_acceleration_by_axis_maximum (float *unit_vec)
static inline float limit_acceleration_by_axis_maximum (float *unit_vec,)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray comma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, removed.

settings.h Outdated
@@ -712,7 +712,9 @@ typedef struct {
float dual_axis_offset;
float homing_seek_rate;
float homing_feed_rate;
#if ENABLE_JERK_ACCELERATION
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this #if/#endif, it will trigger a settings reset when enabling/disabling jerk.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@Dietz0r
Copy link
Contributor Author

Dietz0r commented Dec 27, 2024

Also fixed the G187 Unused P Value error. The crash on motion command still persists. :/

Edit: Found the issue for the crashes. The plan_data_init() doesnt initialize it.
image
(this is rewritten code that calls the lookupfunction from inside the block)
even when written as:

#if ENABLE_ACCELERATION_PROFILES
    plan_data->acceleration_factor = 1.0f;
    debug_printf("plan_data accel factor: %f", plan_data->acceleration_factor);
#endif

it stays at 0 and the debug print doesnt get called either.
but i added it to the plan_line_data_t typescructure. and it's also in the init(). any idea why @terjeio ?

@terjeio
Copy link
Contributor

terjeio commented Dec 27, 2024

No crashes for me, but then I have modified your code a bit, in gcode.c:

Simplified this a bit, the FAIL macro is a return statement so no code will be executed after.
And p < 1 is not neccesarily a negative value...
gc_state.modal.acceleration_profile holds the factor, should be renamed to match plan_data.acceleration_factor.

#if ENABLE_ACCELERATION_PROFILES

        case NonModal_SetAccelerationProfile:

            if(gc_block.words.e)
                FAIL(Status_GcodeUnsupportedCommand);

            if(gc_block.words.p && (gc_block.values.p < 1.0f || gc_block.values.p > 5.0f))
                FAIL(Status_GcodeValueOutOfRange);

            gc_state.modal.acceleration_profile = lookupfactor(gc_block.words.p ? (uint8_t)gc_block.values.p - 1 : 0);
            gc_block.words.p = Off;
            break;

#endif

Copying the factor to plan_data passed to the planner is missing in your code:

    // Initialize planner data struct for motion blocks.
    plan_line_data_t plan_data;
    memset(&plan_data, 0, sizeof(plan_line_data_t)); // Zero plan_data struct
    plan_data.offset_id = gc_state.offset_id;
    plan_data.condition.target_validated = plan_data.condition.target_valid = sys.soft_limits.mask == 0;
#if ENABLE_ACCELERATION_PROFILES
    plan_data.acceleration_factor = gc_state.modal.acceleration_profile;
#endif

…e!) added the line for initilizing the acceleration_factor, renamed acceleration_profiles variable to acceleration_factor to match the rest of the code
@Dietz0r
Copy link
Contributor Author

Dietz0r commented Dec 27, 2024

image
tested and working ... this took a while <3 thanks for all your help

@terjeio terjeio merged commit b0322fd into grblHAL:master Dec 30, 2024
terjeio added a commit that referenced this pull request Dec 31, 2024
… in G0 and G80 modal states. Ref. issue #644.

Added optional support for 3rd order acceleration (jerk) and G187 gcode. Ref. pull request #593.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants