Ahoy !
I'm going to implement some form of Encoders for the RoboClaw service and I'd like to align with previous work and future plans.
Doing a quick google https://www.google.com/search?q=myrobotlab+encoder
- http://myrobotlab.org/content/rotary-encoders-using-gray-code All about Gray
- https://github.com/MyRobotLab/pyrobotlab/blob/master/home/Mats/Gray.py
- The soon to be prevalent http://robotlab-x.org/content/code-cui-amt203-absolute-encoder
And of course the always useful Wikipedia page - https://en.wikipedia.org/wiki/Rotary_encoder
There are a gazillion ways to implement an encoder - magnetic, optical, even mechanical switches.
But most implementation typically fall into only a couple of categories : Absolute & Relative
The Motor & Servo interface vary a little -
Servo's use moveTo(pos) - while Motors use move(duty)
with encoders potentially Motors can start using the moveTo(pos) too.
I know DiyServo was basically an implementation of this - it would be nice to know the successful parts and the problems so far (if any)
Motor Positioning Systems.
The use of a Proportional Integral Derivative (PID) control loop to control the speed of a motor has been around for a long time, and there is a very good implementation of the PID and multiple PID service in MRL.
Positioning of a motor that takes tie to travel, is a bit more of a problem.
Most people attempt to use the PID loop to set the position of the motor with result that vary from barely acceptable to disastrous.
The reason for this is there is really two problems to be solved and most people attempt to solve it in one step.
First is the distance the motor is from the desired position the current position is.
The second is how fast is the motor going to travel to get there.
Knowing where the motor output position is, is the domain of the encoder, be that an absolute encoder, a pot or an indexed quadrature counter.
Once the position error is known, we need to set a motor speed to get to the position.
Most will use this error amount to set the power being sent to the motor, this is a bad method as it is not taking into account any variation in load on the motor or what the actual speed is. at the very least it will result in under shoot, or potentially over shoot. When there is a lot of under shoot, most people add some integral to the equation and that will result in over shoot, especially if the distance traveled is large. this is also know as integral wind up.
What we need to do is control the speed of the motor as a separate function, this means using our encoder to determine not only the current position, but also the speed of the motor.
That was the positioning system can request the motor run at a set speed and a PID loop can be used to control the power to the motor to archive a speed. If the motor is running too slow, it would increase the power, if the motor is two fast, it would reduce the power or even reverse the power to the motor to act as a break.
Since the output speed can be archived in a relatively short time, the PID loop is ideally suited to this application. For the positioning loop, a simple proportional loop with a maximum output is best suited.
In any case the positioning encoder needs to return two values:
1) The current position.
2) the rate of change of position, or speed and direction.
Any encoder service we create must return both of these values.
Wow .. Perfect ! Thanks so
Wow .. Perfect ! Thanks so much Ray, this was enlightening and so very useful.
Ok, check - EncoderData will return
And what you say about "separate" problems makes sense.
I'm still unsure if Encoder is going to be a "service" or just and interface and data definition between services.
At the moment I'm thinking more of a data interface between Motor and its MotorController (subject to change).
Another nuance to consider when trying to accomidate more than just one system, is where the PID is calculated. Roboclaw has the ability to manage speed and calculate the pid "onboard" - while other systems where the encoder & pid is not part of the controller the PID must be calculated & speed maintained by mrl.
I'm glad you brought up the point regarding speed vs position and will look into those details when I begin implementing an "offboard" implementation.
For the first pass, I'll attempt to utilize Roboclaw's capabilities, but in the back of my head I'll try to plan for other motorcontrollers.
RC's interface does not "stream" encoder data - (most likely, because of the afformentioned fact of their system handling the pid) - and you must request to "read" it "on demand".
To begin to get the responsive UI data which approaches Ion Studio - I've got to start a thread which continually "polls" the encoder data.
This is my next task.
update rate counts
Hello Grog,
this link is to the source code for a dual motor controller I created using an Arduino Nano.
https://github.com/Cyber-One/Small_Projects/tree/master/I2C_Dual_Motor_Controller
This is a fast running dual PID loop setup with a very fast update rate.
One of the things I found with positioning systems, is the speed of the controller reaction can be critical.
https://youtu.be/3vIJzb_Ovzk
<iframe width="560" height="315" src="https://www.youtube.com/embed/3vIJzb_Ovzk" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
You may note that during the demo, the position was set and the controller was allowed to settel so as to show the speed it ran to the target and stopped at the target position. The encoder in this case was a pot.
Most likely why systems such as the roboclaw and the sabertooth work so well is they are a high speed stand alone system. Un fortunately they are also expensive.