# Question on torque and velocity control

I am trying to implement a 1 axis artificial spring using a 3 phase stepper motor, a linear stage and simpleFOC. I have the algorithm working where I set the position and can control the ‘spring constant’ with changing the voltage and using voltage torque control. However, when the spring constant is set to a low value i.e. low voltage, the velocity with which the stage returns to the set position is much slower. Is there any way that I can control velocity independent of the torque loop?
Also a related question which might be pretty basic. For a given voltage in the torque loop, how does the algorithm arrive at the velocity of the motor. Is this determined by the kV of the motor?

The velocity is sometimes provided by the angle sensor directly, and sometimes it is calculated by measuring the angle sensor/encoder or whatever at adequate frequency and calculating it. There is a low pass filter I think.

I don’t know what’s up but depending on how you are changing the voltage, you may be de facto changing the effective P constant of the PID controller that is involved in angle control. I forget if there are two lined up, velocity then angle or not. You could add code to adjust the P constant of the PID controller(s) to compensate for voltage changes. However that won’t work in all cases and PID controllers have limits, if you go too far it will oscillate. If you need more response time, you have to use a different regulatory mechanism, PID controllers are just a bit crude like that, they are just a thing that works, they are not optimal or whatever.

@ssuresh What you need is to decouple torque production and motor velocity. The easiest and most accurate way to achieve this is to control motor torque through current limiting, which SimpleFOC supports if your driver board has current sensing on the motor phases. When you do this, you can specify a value of Iq to the motor, and the SimpleFOC code will use the internal current control loop to target this value, regardless of motor velocity. Iq maps linearly to motor torque, so you can easily set your “spring constant” by specifying Iq. You could make Iq a function of position, velocity, etc, simulating a spring very well.

What is the driver board you are using to control the motor? What microcontroller are you using?

Have you tuned the voltage-based current limiting yet? Do that first. Then use MotionControlType::torque and motor.move(-motor.shaft_angle * spring_constant - motor.shaft_velocity * damping);
Higher spring constant should bounce back and forth faster, higher damping will come to a rest more quickly.

1 Like

Thanks @wrcman555 @dekutree64 @Anthony_Douglas for your answers. It looks like there may be multiple ways to implement the springiness - one is to use the P term on the PID as suggested by @Anthony_Douglas , the other is to be in position mode and use the voltage (or current ) as function of position as suggested by @wrcman555 and the third is to just use the torque mode and set the torque it to be a function of position ( bypassing the PID loop for velocity and position) . Thanks for the very interesting ideas and I will try all of these to see which works best for this setup. I am using the SimpleFOCshield driver and an Arduino due.

1 Like

I would point out that those all appear to be essentially identical. The P gain is the relationship between the error and the torque, basically. The other two ways you discussed also change that relationship in basically the same way, I think?

In my project I had a similar requirement and solved it in the way proposed by @wrcman555. Works perfectly fine for me.

1 Like

The way to do this is what was suggested, control the motor in torque mode and use whatever controller you need on top of that, implemented by you in the void loop. I would suggest you use a PD position controller where the output of this controller feeds the SimpleFOC torque controller. This way you have no weird artifacts in terms of speed or anything like that.

I started working on a similar code section again in my program and, despite that it works “somehow” quite well, I am at the point that I do not really understand some basics here. Maybe someone can enlighten me. So far it is logical, with MotionControlType::torque and TorqueControlType::foc_current, more current produces more torque. More torque leads to higher acceleration of the motor. How fast it accelerates, I can control through the current PID ramp params. That’s what I do now. What I cannot control though is the the final velocity. In theory, without load, the motor would accelerate until it reaches its physical limits if my understanding is correct. What, if I need high torque at low speeds, but with a fairly steep ramp up?

… Replying to myself: After looking at the SFOC code I believe there is no bzuilt-in way. What I guess I would need to do is to limit the torque in my loop function when the max speed is reached. The limit being defined as current_sense->getFOCCurrents(electrical_angle).q; Does that sound correct?

In torque mode yeah, the current or voltage setting affects acceleration. It combines with the P term as far as I can tell. This makes the tuning of the pid slightly more complicated as it is the combo of them in the case of voltage control, I think the current control mode simply calculates the voltage from the resistance of the motor in some way.

In other words, the de facto P gain of the system, in terms of volts above the back emf that is applied, per unit of error (actual value minus setpoint, probably set RPM vs actual RPM). The actual units used in PID controllers is often arbitrary and very confusing, I try to use actual units but they are usually just integers or floating point number and you have to look right in there to see what they really mean.

It will also change if you change the power supply voltage. This can be confusing as the system can be tuned, but if you change one of these three things it could start to oscillate again.

I’m probably not a good person to listen to on this, it was a long time ago now that I last played with this stuff.

You are limited by the properties of you motor, fundamentally. You can get torque at low speed but energy efficiency will end up being low. You cannot escape the speed vs efficiency curve of the motor. Thus it will tend to overheat.

Some motors will have a more suitable curve, and you can also use a motor capable of more heat dissipation, or put compressed air through the motor or something. Stepper motors have great torque to speed ratio, much higher than most motors but they are hard to drive with FOC due to the high pole count.