Torsional Spring Replication?

Hi! I am working on a project trying to simulate a torsional spring using a motor. We want to adjust the stiffness of the simulated torsional spring in order to produce different results in our project by changing the torque of the motor. I currently plan on using the Odrive Pro to do this.

Does anyone have recommendations or advice on using the ODrive Pro? Is it good for adjusting torque values? I saw that the GUI has a torque control setting, any tips on using it? Thanks!

Hi! ODrive is definitely a great choice for this! The ODrive supports precise torque, velocity, and position control. Note you’ll need to know your motor’s torque constant (Nm/A) to ensure torque accuracy. Typically, the torque constant is 8.27/KV, where KV is the speed constant in RPM/V (a more commonly provided motor value).

You can specify a direct torque value in the GUI (or over USB, UART, or CAN), that’s typical. Note though that this will be a constant torque, and not a position-dependent torque as a torsional spring will provide. To simulate this, you can put the ODrive in position control mode with a vel_integrator_gain of 0 and a vel_gain of 1. Then, your pos_gain will be the spring constant, in units of Nm/revolution. If you have a desired spring constant in the units of Nm/rad, you can multiply it by 2pi to get Nm/revolution. However, if you just want a constant torque, then you can simply set the torque from your external motion controller (computer, microcontroller, etc).

Hello, thank you for this reply! Could you explain this a little bit more please? It sounds like it is exactly what we are looking to do within our project, thank you!

How does changing the velocity integrator gain and velocity gain allow the position gain to act as a spring constant? Is there a derived equation to represent this system? I understand that this is a series of PID Controllers placed together and how the system functions in that manner, but would like a little clarification on how changing these variables will allow the position gain to act as a spring constant.

EDIT: Disregard, made a mistake here, will update soon :slight_smile:

Hi! So:

To oversimplify, the position controller generates a velocity setpoint, and the velocity controller generates a torque setpoint, which is then executed by the ODrive’s torque controller.

The velocity controller equation is:
Torque setpoint (Nm) = vel_error (rev/s) * vel_gain (Nm/rev/s) + ∫vel_error (rev/s * s) * vel_integrator_gain (Nm/rev/s * s)

The position controller equation is:
Velocity setpoint (rev/s) = pos_error (rev) * pos_gain (rev/s/rev)

If you set vel_integrator_gain to 0, then this simplifies to

Torque setpoint (Nm) = pos_error * pos_gain * vel_gain

Then with vel_gain == 1, this simplifies further to:

Torque setpoint (Nm) = pos_error * pos_gain

The torsional spring equation is T = k * θ, where T is torque in Nm, k is spring constant in Nm/radian, and θ is angular displacement (in radian). This is exactly the same as the prior Torque setpoint (Nm) = pos_error * pos_gain, (pos_gain == k, pos_error == θ), except with the unit of turns in radians instead of revolutions.

So e.g. if you set vel_integrator_gain to 0, vel_gain to 1, and pos_gain to 10, then in closed-loop position control with a position setpoint of 0, your system will behave as a spring with a torsional constant of 10 Nm/rev (or 2pi*10 Nm/rad)

Thank you!

EDIT: I made a mistake here, will update soon :slight_smile:

Okay, thanks!

Hi! Sorry it took me so long to reply.

My error was forgetting that the vel_error was vel_target - vel_actual :slight_smile:

In this case, vel_gain will act as a damping coefficient, so instead of setting vel_gain to be 1, you will have to set vel_gain very low, then multiply pos_gain by 1/vel_gain.

For instance, instead of setting vel_gain to 1 and pos_gain to 10, you’d have to set vel_gain to 0.001 and pos_gain to 10/0.001 = 10000 to get the same 10 Nm/rev torsional spring constant (and you will have the additional damping coefficient of 0.001 Nm/rev/s from vel_gain, but this is likely low enough to be ignored).

Some more info on the math here: