Some questions about settings for big motors: driving a Fanuc S420F Robot Arm with ODrives, Rpi and a wired Xbox controller

Hi all.
I have several questions about my project and I hope someone can help with any or all, I hope it’s OK to put them all together. Trying to search as much as possible to see if the answers are already up here but there’s a lot I don’t understand about the details of motor control, so I’m moving a lot by trial and error.

I have 3x 56V Odrive boards updated to 0.5.1 firmware, odrivetool running on a Raspberry Pi 3 A+, a wired xbox 360 controller, and a 6-axis Fanuc 420F robot arm. The goal is to get the xbox controller moving the arm around at first so I can use it under manual control, and later to integrate the arm into linuxcnc (which I’m fairly familiar with) and maybe ROS (which I don’t know at all).

I’ve bodged a python script to tie velocity control to the thumbsticks of an xbox360 controller, using native protocol over usb, so that e.g. 20% left moves one motor clockwise slowly, 100% left does so quickly, 20% to the right goes anticlockwise etc. I think this will give quite intuitive arm control. Also have the new ODrive_GUI running which is a great help in learning which parameters go where and do what, even at this stage in its development.

The Fanuc motor I have on the development rig (A06B-0501-B751/Model 10) is 1.6kW , 2000rpm, 8 pole, 144V, 11A stall current and 12Nm stall torque according to the plate. The arm has 3 of these and 3 larger motors (A06B-0502-B751/Model 20S) - 3kW, 2000rpm, 8 pole, 146V, 20A stall current and 23Nm stall torque. I realise these might be a bit bigger than what the ODrive is meant for, but if I understand it, they might work but only up to about 1/3rd top speed, which would be fine for the moment.

The encoders are ‘ABS Pulse Coder type A860-0320-T111’ - 2000 count quadrature output with index pulse, differential output - this is converted to single-ended output using super cheap differential receiver IC ‘AM26C32’, just on a breadboard at the moment, which the ODrive seems to read OK.

I’ve had the ODrive run its calibration routine on the Model 10 motor many times now, and it usually seems to succeed and can be put into closed loop control, and run OK in velocity mode.

Questions/problems at the moment.
I can’t seem to get it to turn any faster than about 8 revs/sec. Torque is OK at this speed and feels like it should turn the arm’s input gears at least under no payload, though I’ll want to increase that. If I set input_vel to 1 rev/sec, I can easily stall the motor with a light grip, torque slowly builds up until I can’t resist the motor any more, and when I let go there’s a bit of quick movement and back to 1 rev/sec.

So…what value to change to get high torque at low speeds?

I’ve tried increasing max vel settings but no matter what value goes into input_vel the motor doesn’t spin faster than about 8rev/sec. Sometimes in playing with position mode, it will jump to a position violently, seeming to go far faster than when in velocity mode. Which value is determining max velocity?

I’ve read here and there on this forum that ODrive input current isn’t closely related to output current. My power supply is 48V, 200A so I don’t think it’ll blow up, but I don’t want to risk burning out the motors. Should I limit output current to the motor’s rated stall current?

And lastly for now, I can’t seem to get the ODrive to respond in closed loop control without doing the full calibration sequence. This is fine on the bench but I can’t decouple the motors from the arm every time it’s turned on. Even after a save and soft reboot, I can’t get a response to requested_state = CLOSED_LOOP_CONTROL - any ideas what might be causing this?

Thank you in advance for any help, let me know if I can provide any more info.

Ok, here we go:

I can’t seem to get it to turn any faster than about 8 revs/sec.

48V / 146V * 2000rpm / 60 * 0.75 = 8.2 rev/sec. Right on the expected value.

So…what value to change to get high torque at low speeds?

In velocity mode, controller.vel_gain and controller.vel_integrator_gain. In position mode, controller.pos_gain also has an effect. And of course controller.torque_limit and motor.current_limit

Which value is determining max velocity?

controller.vel_limit, but in this case, it’s your bus voltage. I wouldn’t set a vel_limit over about 7rev/sec to be safe.

Should I limit output current to the motor’s rated stall current?

In the world of industrial robotics, that would be considered a conservative limit. Peak current is probably 3x, but I strongly encourage you to test different currents at stall and actually measure the temperature rise to understand how they’re going to behave. You can also use motor thermistors, see the docs.

48V @ 200A is 9.6kW, so as long as you’re under this power you’re ok. Should only happen if you request hard accelerations at high speeds.

And lastly for now, I can’t seem to get the ODrive to respond in closed loop control without doing the full calibration sequence.

I’m surprised it doesn’t have absolute encoders, but you can have it do an index search instead of a full calibration. See “Encoder with an Index Signal” here https://docs.odriverobotics.com/encoders

1 Like

Thank you so much, that’s really helpful. I thought that might be the case regarding the max velocity but wasn’t sure I had understood…where does the 0.75 come from there?

So I can try motor.current_limit up around 25A-30A (50A-60A for the bigger motors) and tune controller.vel_gain and controller.vel_integrator_gain according to the Docs:Tuning section.

To test different currents at stall…these motors all have DC brakes that release when 48V is applied, so I could leave the brakes on to test this by sending a velocity setpoint and look at how quickly they heat up under these circumstances?

It does have absolute encoders, though from this discussion they keep position using a battery backup, and on a powerup request signal, they output quadrature pulses to count up to their last stored position before returning to normal quad output.

I’m not sure I could use that feature with the ODrive, but the index/Z pulse shows up on my oscilloscope going into the Z pin of the ODrive board so should be being seen. I’ll go back through the encoder calibration page, I thought that would be included in the axis_state_full_calibration_sequence but it looks like I’ve missed a couple of points.

Again, thank you.

Because of the ODrive architecture, we’re limited to ~70 or 80% of the bus voltage (couldn’t remember which so I split the difference).

Sounds reasonable.

It does have absolute encoders, though from this discussion they keep position using a battery backup, and on a powerup request signal, they output quadrature pulses to count up to their last stored position before returning to normal quad output.

Hmm, that should work, as long as it’s counting pulses in the background. ODrive firmware doesn’t support it yet, though, you’d have to add it.