I’d like to have a motor with zero velocity but a constant resistance to movement (so basically a knob). I’m trying to do this using
TorqueControlType::foc_current but I’m failing to control anything but velocity.
How can I maintain zero velocity but set a certain “resistance”? I thought that would be done by specifying the current via
Assuming you have closed loop working (i.e a sensor that knows the motors position) this seems like:
motor.controller = MotionControlType::angle;
is what you want. You’ll want it to keep it at the current angle. In this mode when you set
motor.move(x) the x means a position (in radians). If you keep x constant it’ll want to stay at that angle. Any deviation from the angle will result in the motor wanting to return to that angle e.g. if you try to force the motor away from that position. You can play around with the PID settings to control the stiffness.
You might get fancy and move from the default
TorqueControlType::voltage to something else (e.g.
TorqueControlType::foc_current) but you may not need that. The important thing is to try
motor.controller = MotionControlType::angle;
In closed loop you need to tune a velocity and an angle PID set of values. It sounds complex, but you’ll work it out. I find it easier to start with
motor.controller = MotionControlType::velocity; and tune the velocity PID once you get a nice velocity response, switching to angle and tuning the angle PID is super easy.
The desired behavior is not to maintain a certain angle/ position though, it’s just to provide some resistance to movement, i.e. simulating mechanical friction.
I would probably do MotionControlType::velocity with a target of 0, to simulate drag. If you set the PID limit low, then it will be a consistent force after a certain amount of error.
It’s a surprisingly difficult problem… how to oppose motion without springing back when you let go. My first thought is to use angle mode and have the target lag slightly behind the measured angle, so as you force it to move, the target gets updated to where it will only spring back a small amount.
Or have it lag in time. Save a history of the measured angle over the last hundred milliseconds or so, and set the target to the oldest angle in the buffer. The faster you move, the more resistance it will give, but if you hold it still for the duration of the buffer, the spring-back force will fade away and it won’t move when you let go. But that will still spring if you let go while turning it quickly, and possibly could have feedback effects causing the knob to drift on its own.
You could use velocity mode with target 0 and only use the P factor in the PID (the I factor accumulates and causes spring-back), but resistance proportional to velocity means moving very slowly will give very little resistance.
someone else asked a very similar question a while back, I’m sure you can dig that up. I suggested simply use angle mode and making the set point wherever the knob was a fraction of a second ago. This would not be like mechanical friction but more like viscous drag with some elasticity. Basically I would try to set the setpoint for position based control some distance from the actual position, to create the anti-rotational force. As the knob slows down when you stop turning it, it would spring back slightly. Some kind of function which made the setpoint come very close to the actual motor position or perhaps slowly catch up to the actual position could work I guess. Actual true mechanical friction analog might be pretty hard to mimic. That’s a force that does not depend on position and does not change in the same way with speed, in fact I think in the ideal case iirc friction does not depend on speed.
If you tried to make it just like mechanical friction I think with any pid controller it would end up oscillating around at least a bit, because you basically have to have a very high p gain close to a zero error. If you plot corrective force vs error, it has to dip down to a low level when the error is zero… you want it to be significant even with almost no displacement, that’s what mechanical friction does. Stiction makes this even worse. I don’t think you can get that with a motor and sensor buy you could get some wacky hybrid that gives tactile feedback for sure.
I wonder if some of the approaches suggested above might benefit from Anti lock brakes (ABS) strategy. I.e apply rhythmic pulses of braking.
Thanks all, this is very interesting - I’m going to use “haptic texture” with dimps every 5 degrees or so, which for my purpose will be good enough at approximating friction.