Open paukstelis opened 6 years ago
One way that could start is by using I2C for motor controller comms. However, the machine model needs to be defined first: a) all motors are now dc motors (with encoders) b) XY motors are dc motors and ZE are steppers c) XYZ motors are dc motors and E is a stepper motor
Next, the architecture of the motor controller communication needs to be established: 1) fire-and-forget: motor controller handles all the motion pattern (accel/cruise/decel logic) 2) similar motion segments: accel/decel and cruise as independent commands issued to the controller 3) babysitting: step/direction commands, instead of a signal, a message.
I would say the most extreme would be a1 combination and b3 the most conservative one (but this one may require something like Kilpper's step_compress to be a viable choice though).
I am assuming the existence of a motor controller processor plus the main one running Marlin. That is again another design choice, but I reckon most of us will feel more comfortable doing baby steps. That, in turn, may allow making fewer hardware changes to existing printers while still getting most of the expected benefits.
From what I remember of the discussion, my impression was that 3 would be easiest to implement in the sense that the motor controller's feedback to firmware would essentially be to tell it to add/subtract X number of steps to/from the planned move.
Peek at #9935 for an interesting approach. It's probably not applicable here, but it's worth a look as a control model.
Maybe I'm mistaken, but couldn't a lot of what is present in /modules/I2CPositionEncoder (2.0) be used for approach 3? Looks like it is designed for magnetic encoders but with some settings for rotary encoders. Couldn't find the source for Aus3D encoder modules to see everything it is expecting over i2c, but seems like a simple first step to getting feedback to Marlin.
@thinkyhead If I understood right, there was a bit of a confusion as to what servo meant for different people on the list, but eventually they wanted to use a regular RC servo driven by a PWM signal, so no closed-loop from Marlin point of view.
I have used grbl-servo for my 2 axis drawing machine https://github.com/misan/4xidraw in the past for exact that same purpose, having an additional "axis" that controls an RC servo.
That is why I posted about the different possible ways it could be decided to tackle the control of closed-loop motors.
In my opinion, the best way is not going to be the simplest one, so it may make sense to choose a sub-optimal option that can be up and running with fewer changes, so we can start getting some of the advantages of closed-loop motors ASAP.
@paukstelis magnetic encoders are definitely a viable solution for closed-loop motor control. Some models do support I2C. In fact, yet another posible choice, lets call it (d)
d) only stepper motors
could be made closed-loop by adding the encoders to the mix. However, the way the loop is closed in such a case is somehow limited by the driver electronics and the error-correction algorithm selected. Plus the encoders could help too for dropping axes' end-stops.
I have used the cheapest AMS magnetic sensors (AS5600) in my project too https://github.com/misan/dcservo/blob/master/dcservoProMicroMagneticEncoder.ino#L85, and they work ok for low-speed operation (<480RPM)
In fact, AS5600 is designed for hi-fi volume controls and AS5601 for replacing mechanical rotary encoders (as it does include push-button action besides angle sensing). These two chips have, however, a fixed I2C address.
Approach 3 meant the steps are communicated to the motor controller using an I2C message. However, because the latency of a single message is measured in hundreds of microseconds, it is not possible to use that for single step messages that need to happen only tens of microseconds apart from each other. So a more compact type of messages would be needed. Still, that approach would assume closed-loop control code (and encoder reading) happens on an independent processor (different than the one running Marlin) but connected to it by I2C bus.
@misan I was thinking along the lines of using I2CPositionEncoder to communicate with the independent processors (pro micros) to relay motor position and correct steps if necessary (sticking with the current STEP/DIR method). That seems to be how the current implementation works after checking to see if some error threshold is met. I guess with those I2C speeds you would make some gross corrections, but not the kind of fine closed loop control one would like.
EDIT: here is their firmware for the encoder modules: https://github.com/Aus3D/Magnetic-Encoder-Firmware
@paukstelis The advantage of having another processor to handle control loop is the main one (running Marlin) can forget about the whole thing. That would mean the encoder is read by the motor controller, which takes any required action to keep the position error low.
Marlin would only know about error conditions that compromise the print, like an excessive following error.
Moving the loop control within Marlin logic while not impossible nor illogic is not the course I would recommend, as it will put more hard real-time workload on Marlin.
After reading through quite an excessive amount of acceleration/jerk/junction/LA/etc. related issues and pull requests over the last few months, I can tell that implementing closed loop control into Marlin and keeping it working well is going to be really hard as there seems to be a lot of logic (ie. Linear Advance) relying on step-level latency to work well.
I wanted to propose a Trinamic dcStep feature request some time ago, so that a stepper driver could slow down (and let Marlin know) when needed, slowing down other axes as well (connecting multiple drivers via DCIN
pins), even leaving the whole acceleration logic to the driver. Kind of like an encoder attached to a DC motor. But then I realized that the melted plastic would ooze out as LA adjustments would be slowed down too. Or that autotemp would likely overcompensate. Or that one of the many (sub)systems Marlin has wouldn't account for external slowdown.
Technically speaking, Marlin already has support for I2C_POSITION_ENCODERS
, but I don't really know if anybody uses the code and how well it works with recent planner rewrites. Or if there's any chance that it could work with a DC motor without STEP/DIR. If not, I guess something like ODRIVE or PTHAT could be used.
@comps What I have been working on is on a cheap way to introduce closed-loop dc motors using the step/dir pins https://github.com/misan/dcservo/blob/master/README.md
Not ideal, but a first step.
Not different from ODRIVE but I have not developed a board nor I support brushless motors (a matter that adds another layer of choices on this topic). Are brushless motors better than dc motors? You bet! But driving them requires more complex electronics unless they already have a built-in driver.
But as I mentioned above, I do not think step/dir to be the best interface in the long run. But first of all, Marlin communitiy needs to define what type of closed-loop solution they want to support.
Marlin communitiy needs to define what type of closed-loop solution they want to support
Usually we wait for a reasonably-priced product to appear on the market, and then we make sure to support that solution. If there isn't any such product, then we usually wait until someone has their own working implementation (that also isn't too costly) and then they will post a PR for us.
As for the "type" of closed loop solution, an encoder that's accurate enough to actually work is the first thing, and then we'd simply add code to periodically poll it (maybe 10 times a second) and if the position has drifted far enough, then apply a correction to the planner position.
FTR, there are a few kinds of existing "non-STEP/DIR" interfaces close to the Marlin ecosystem that support closed loop control:
So it seems to make sense to split the planner into
Then the software "motion controller" could be replaced by an ODrive wrapper / TMC wrapper / something else (ie. DIY motor driver board) that would forward the parsed movement logic via the target protocol.
Ah well, now for somebody to write the code.
@paukstelis is this still relavant?
@paukstelis is this still relavant?
I think so, but its not clear where it is on the relevance scale. I do think that when most hardware moves to 32-bit, non-AVR there will be more exploration into closed-loop control. Discussions on how best to implement will still be needed.
if this should be implemented the best bet is that someone submits a PR
I'm working on board similar to nano zero or mechaduino with magnetic encoder and tmc2160/5160 drivers. So i think we should discuss how to interface it with marlin
Hey guys, any development or tips on this? i'm trying to upgrade an old stratasys machine that have a really good dc servo on the extruder.
Hey guys, any development or tips on this? i'm trying to upgrade an old stratasys machine that have a really good dc servo on the extruder.
I made a workaround adding one arduino pro mini for each servo, which reads the step signal and work the servo alone, no changes to marlin and quite easy to do, code was already available online. i guess its possible to control more than one servo with one pro mini, but since i had lots of them here i just used two.
That's the approach most have taken to this point. More recently I've used STM32F103C (Bluepill). You can use hardware timers to read rotary encoders and you can do 3 axes with a single bluepill.
Hey guys, any development or tips on this? i'm trying to upgrade an old stratasys machine that have a really good dc servo on the extruder.
I made a workaround adding one arduino pro mini for each servo, which reads the step signal and work the servo alone, no changes to marlin and quite easy to do, code was already available online. i guess its possible to control more than one servo with one pro mini, but since i had lots of them here i just used two.
@italocjs can you please expand a bit on this? This closed loop feature doesn't appear to be documented. I have a machine with a linear encoder on the X axis that I would like to use with the stepper motor.
I guess I just connect the stepper outputs from my Marlin controller, to another controller, and this second controller accepts these inputs and implements the necessary control algorithm? You say code was already available online, can you please provide a link? I would be most grateful.
I am happy to write up some documentation to add to the guides
@thinkyhead, based on our discussions at ERRF, I thought I would open a FR for DC servo/encoder support. I know misan has ideas on how this could be approached.