Skip to content

[2.0] Closed Loop Controller Support#11772

Merged
thinkyhead merged 2 commits intoMarlinFirmware:bugfix-2.0.xfrom
SJ-Innovation:bf2_ClosedLoopController_Support
Sep 10, 2018
Merged

[2.0] Closed Loop Controller Support#11772
thinkyhead merged 2 commits intoMarlinFirmware:bugfix-2.0.xfrom
SJ-Innovation:bf2_ClosedLoopController_Support

Conversation

@SJ-Innovation
Copy link
Contributor

Description

Added support for a small external X-Y closed loop controller to be activated or deactivated by the main controller. Using a single wire for the control signal and another for the return "move complete" signal to signify whether or not the move was able to be made successfully.

Benefits

When properly set up, entirely eliminates motor stalls and ruined prints with slipped steps. The closed loop controller recognises the skipping steps and applies sufficient steps to return the printhead to the position expected by the main open loop controller.

@thinkyhead thinkyhead force-pushed the bf2_ClosedLoopController_Support branch from 6a2c010 to 97bb15f Compare September 10, 2018 05:14
@thinkyhead
Copy link
Member

  • The code G8 has a pre-defined meaning for CNC. Although it's only applicable to lathes we might still want to choose a different code for the controller reset.
  • Should the init_closedloop function set the CLOSED_LOOP_ENABLE_PIN to some definite state (HIGH or LOW)?

@thinkyhead thinkyhead force-pushed the bf2_ClosedLoopController_Support branch 3 times, most recently from 5654f57 to c8cb492 Compare September 10, 2018 05:24
@SJ-Innovation
Copy link
Contributor Author

Added a defined state to the enable pin, one wouldve thought it would default low; but i guess you can never be too careful.

Im open to change the GCode used. Perhaps to an M-Code as this is an auxiliary function. Im thinking M12 in that scenario? As its totally unused by 3D printing and CNC alike.

@SJ-Innovation
Copy link
Contributor Author

Derp. Sorry xD

@thinkyhead thinkyhead force-pushed the bf2_ClosedLoopController_Support branch from 516c45d to 53b8c3b Compare September 10, 2018 08:18
@thinkyhead thinkyhead merged commit 5d5cd13 into MarlinFirmware:bugfix-2.0.x Sep 10, 2018
@thinkyhead
Copy link
Member

No worries. Merged!

@TheSFReader
Copy link
Contributor

Sorry for the perhaps dumb question, by why does are you only using on X-Y ? Isn't it possible to use it on other axes/pseudo-axes ?
Do you use a single controller for all axes (X/Y) ?

@SJ-Innovation
Copy link
Contributor Author

@TheSFReader
Not a dumb question at all! You could use it for any number of axis, as long as the closed loop controller accepts step/dir inputs as well as the control signal, and outputs the "Move Complete" signal whenever the set position is equal to the real position. You could easily add Z and extruder control to it, or even use with the pylons of a delta printer. Ive got some board designs in the pipeline for making this its own project, but wanted the software compatible first.

The reason I only described XY is those are the only 2 axis' i use it for on my setups as theyre the ones more likely to stall during a print.

@Sineos
Copy link

Sineos commented Sep 10, 2018

Is there anything like readily available hardware supporting this?

@SJ-Innovation
Copy link
Contributor Author

Nothing yet, except my controller thats in the pipeline. Coming soon.

@thinkyhead
Copy link
Member

I find it very interesting that the external controller itself does the step correction on the motors. I look forward to seeing it in action.

@SJ-Innovation
Copy link
Contributor Author

Its on the printer i have with me at the moment, in the morning ill take a video of it doing its thang. The current hardware setup is a little bit sketchy, as is the software running on the controller. At the time i built it as a "lets see if this works" principle. I did, but then Uni got in the way and i never got round to cleaning it up. Thats what im doing now.

@comps
Copy link
Contributor

comps commented Sep 10, 2018

If this works on a single-step level (meaning single STEP pulse), it could probably be easily adapted for Trinamic dcStep, which also tries to prevent lost steps by slowing the motor down (like a DC motor), pulling the DC_OUT (DCO) pin low to tell the STEP generator to wait a bit.

See ie. the TMC2130 datasheet, section "18.3.2 DCO Interface to Motion Controller".

Unfortunately, dcStep pins are not easily available on the pololu-style boards, so some precision soldering would be needed for the widely-available TMC2130.

@SJ-Innovation
Copy link
Contributor Author

This works on a potentially even lower than single step level depending on the encoder used. Ill explain all this is my highly professionally made video, but yes that was the eventual goal. Ive never really found much in the way of issue with the current setup though, at most it loses about 5 steps before the applied correction force is enough to bring things back into line. It would certainly be more elegant to go about it the dcStep way though. Ill look into it!

@paukstelis
Copy link

Still waiting to see this video and get some description of controller....

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Oct 15, 2018 via email

@paukstelis
Copy link

Understandable. Just so I understand, the control signal just flags the controller if it should send the Move Complete signal?

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Oct 15, 2018 via email

@paukstelis
Copy link

I have a DC motor closed loop XYZ system based on the work of @misan and I'm working on a new printer that uses DC motors with encoders for X & Y. Each axis has a MCU tracking step/dir, so I'd either have to daisy chain them or add a second instance in Marlin. I'm guess I'm curious if this is something you just turn on/off every once in a while through gcode, or if you are constantly checking for correct position after you send M12 S1. If its the later, how are you resetting the "Move Complete" signal after it triggers?

@misan
Copy link

misan commented Oct 16, 2018

@paukstelis I reckon this feature is not needed nor helping if you already have a closed-loop controller. It is intended to correct missing steps by adding additional step pulses to set the motor back on track with the info provided by an encoder, but in your case, additional step pulses would set the motor to the wrong position.

@paukstelis
Copy link

@misan I was thinking that its utility might be more in that it stops sending step pulses until axes are synced. I've seen cases where if there (intentional) large deviations from the target position leads to issues just because all the other axes are doing their thing.

@SJ-Innovation
Copy link
Contributor Author

This addition has little value if the motors are already close looped by another device that has its own control logic and doesnt need to report to Marlin. Your DC motors are a perfect example of this @paukstelis, theres no need to use this feature.

@misan Your assumption is correct, however it is not Marlin that issues the extra pulses at all. Marlin doesnt know/care that the closed loop controller even exists, as all it recieves as feedback is the "Move Complete" pin which, as @paukstelis correctly assumed, is just a "make sure everything makes sense" functionality. If using a CLC similar to mine it is entirely unneeded, just a nice safety feature to have.

The docs a videos are coming soon, in which ill referenace and explain in more detail, but i cant set a specific date as im extremely busy.

@misan
Copy link

misan commented Oct 16, 2018

@SJ-Innovation So what Marlin does is to wait till a "move complete" signal is activated on each axis involved. Other extra hardware would take care of extra steps if needed till movement reaches the intended encoder count, right?

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Oct 16, 2018 via email

@misan
Copy link

misan commented Oct 16, 2018 via email

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Oct 16, 2018 via email

@SJ-Innovation SJ-Innovation deleted the bf2_ClosedLoopController_Support branch January 2, 2019 20:01
@paukstelis
Copy link

paukstelis commented Jan 24, 2019

I decided to go ahead and try this out, but noticed what I consider to be a minor flaw. The planner is looking for a signal high to avoid idle, but it doesn't account for the current enabled state. I built my controllers so that they would only report if he enable pin is activated. If I turn on my RAMPS board without the motor drivers on, Marlin will never complete loading because the planner stalls.

A simple fix in planner.cpp:

#if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
      || (READ(CLOSED_LOOP_ENABLE_PIN) && !READ(CLOSED_LOOP_MOVE_COMPLETE_PIN))
#endif

EDIT: This fix actually allows you to turn the closed loop control on and off. The current code forces it to be on at all times.

@SJ-Innovation
Copy link
Contributor Author

Good shout! My controller outputs a Move Complete signal even when just passing through (open loop mode) but this makes it more compatible with multiple platforms. Will add and submit a PR

@SJ-Innovation SJ-Innovation restored the bf2_ClosedLoopController_Support branch January 24, 2019 15:09
@SJ-Innovation
Copy link
Contributor Author

PR #13005

@marcio-ao
Copy link
Contributor

@SJ-Innovation: Is your hardware open-source? We have been experimenting with linear encoders, I got as far as implementing some Verilog for an Lattice FPGA for inserting steps based on encoder position, but I haven't had a chance to test it on an actual printer.

If you've made progress on this front, I would be interested in knowing how you did it.

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Apr 2, 2019

@marcio-ao My solution is open, but is very hacked together for the time being so i dont feel comfortable releasing it to the world at large.

I do not use linear encoders, in fact i use high step count rotaries directly attached to the shaft of the stepper motors. This does mean that belt backlash still affects position, but is a much simpler implementation. (EDIT: And ive found that belt backlash isnt much of an issue now thanks to your awesome M/G425 :p)

The motors i use: Dual Shaft Stepper have a second short shaft on the back, to which i bind the encoder.

The encoders i use: AMT102 are configurable between 400 and 8192 steps per rev.

For axis correction, i use an external STM32F0 controller, they have internal timers that are capable of counting the encoder steps without use of the CPU core at all. This means that missed encoder steps are virtually nill. As in ive never had a missed step in the 8 months ive been printing with this setup... The controller corrects for the position deviation using 2 methods; when close (within 3 steps of desired position) the steps from the input are directly mapped to the output with a tiny integral term to correct for the small deviation over time... When far it switches to a totally separate ramp generator to generate a move similar to the planner in marlin, but stripped back. All the while it updates its target position based on the step and dir inputs from the main controller.

In case you're interested, ive literally just sent off PCBs to a fab company for my closed loop implementation as part of my modular STM32F7 control board interface. Once ive got the boards and some preliminary firmware written, id be more than happy to collaborate.

@misan
Copy link

misan commented Apr 2, 2019

@SJ-Innovation Yours is definitely an interesting approach: mixing and matching Marlin's and your own ramp generator. I would like to learn more about it. Is there any link you can share about it?

@marcio-ao
Copy link
Contributor

@SJ-Innovation: If you end up with spares, we might be interesting in purchasing a PCB, or kit, or even an assembled board to test out with linear encoders.

If your technique works, one possibility might be to port it over to a Lattice FPGA and see if their are any advantages to doing so. So far I have a rudimentary design with some similarities to yours. I have a encoder pulse counter and logic that successfully keeps track of the target position and computes an error term. I also have some logic that attempts to insert steps into the pulse train, but I do not have a ramp generator. Certainly a microprocessor based implementation like yours would be easier to debug and iterate! :)

@SJ-Innovation
Copy link
Contributor Author

SJ-Innovation commented Apr 2, 2019

@misan Most of the ramp generation is performed by the main controller running marlin, that way we dont need to re-implement things like junction deviation and S-curve in the closed loop controller. The only time the secondary ramp generation engages is when the error between the real and setpoint positions exceeds a certain value. At that point, i run on the assumption of "who gives a damn about keeping to the nice ramp, we need to correct NOW". I developed the approach for my own controller, once ive received my boards ill be focussing on making it a more expandable system.

@marcio-ao I'll most likely have spares and would be interested in getting you set up with some, the closed loop boards i use fit my modular controller standard which i am soon to be adding to Marlin. I would be very interested in seeing this porting to FPGA as that was my original intention but I lack the FPGA experience to make it work. Given the high performace of even cheap STM32F0 controllers, it seemed logical to use what I was experienced in. Ill keep you posted of future developments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants