ERROR_MODULATION_MAGNITUDE when doing index_search

Hello all,

I am currently trying to use the odrive to controll this motor in combination with a AMT-102 powered by a 48 volt lipo battery.
The motor does work fine when callibrating after setting vel_limit and current_limit higher.

The problems begin after a reboot.
When I want to do a index search I get these erros

axis0                                                                                                                    
 axis: Error(s):                                                                                                           
  ERROR_MOTOR_DISARMED                                                                                                    
  ERROR_MOTOR_FAILED                                                                                                   
 motor: 
Error(s):                                                                                                         
ERROR_MODULATION_MAGNITUDE
encoder: no error                                                                                                       
controller: no error 

So then I want to do a full calibration to get it working again but then I get these errors.

axis0
  axis: Error(s):
    ERROR_BRAKE_RESISTOR_DISARMED
    ERROR_MOTOR_DISARMED
  motor: Error(s):
    ERROR_BRAKE_CURRENT_OUT_OF_RANGE
  encoder: no error
  controller: no error

After a reboot and full calibration I can move the motor again without any issues.

What is wrong here?
I cannot do full calibrations every time the odrive reboots since these motors will be used to steer a robot.

If you are using it for steering, then I’d recommend an absolute encoder… That way you don’t need to do any calibration or index search at all after reboot.
It seems an odd motor choice for steering too… Is it direct drive or geared eg with a rack & pinion?

Are you using the latest 0.5.1 firmware? They changed how the brake resistor is controlled, and it usually works a lot better now.

However, I’d guess that your problem is being caused by the high current inducing a transient noise spike into your encoder wiring, which is triggering an index pulse when it shouldn’t be there (and consequently the calibration is invalid, which can cause errors like the ones you’ve been getting).
Check that your index search always stops in the same place. If it doesn’t, try adding some 22nF capacitors to GND on each of the A,B,Z lines as others have done on here.

but really, for steering, I’d recommend an absolute encoder in combination with a high torque, relatively low speed motor such as 8318 kv100, or ideally something even wider with even more poles.

Out of interest, how big is your robot??

It is geared with a planetary gearbox at a 153:1 ratio (153 rotations of the motor is 1 wheel rotation) and we cannot add an absolute encoder because of the contruction of the leg. The encoder cable is a shielded ethernet cable.

The firmware I use is 0.4.12 since I do not know how stable 0.5.1 is.

When the index calibration is requested the motor does not even move a little bit. It directly give those errors.

The motors that we use are once we already had laying around and it is in the test fase if the motors will work.

The robot is BIG. ~1200 kilo’s with 4 legs that can rotate independently from each other.

Ok, it sounds as if the index search is not working at all, because it sees a pulse immediately due to noise and stops. Try adding the capacitors, or putting a scope on it to see if you need an RC filter instead.
That said, you say the errors come directly from index search, which would suggest that the drive is struggling to move the motor in open loop to find the index (which makes sense if you have a lot of load on it). You could try increasing the current used for the index search, perhaps… But modulation_magnitude errors normally mean that the current controller was unable to increase the current any more.
Unless you are able to move the motor by hand somehow to the index pulse, then you are going to NEED an absolute encoder.

They can come in very small packages (often just a single chip). The most commonly used one with ODrive is AS5047P. You stick the magnet to the shaft (e.g. with superglue!) and mount the board such that the magnet floats a few mm above the chip. You should be able to make 3D printed housing for the board that is no bigger than the AMT102 encoder. In the worst case, you’d have to shorten the motor shaft to mount it in exactly the same position, I suppose.

The index search works with a full calibration but not after a reboot. That is the frustrated thing about it, but it seems that after changing motor.config.calibration_current to a higher value it works without the leg connected.

Maybe a stupid question but does the Odrive keep the position after multiple rotations with an absolute encoder? I couldn’t find that in the documentation.

Most ‘absolute encoders’ are only absolute to within one turn - they wrap around back to zero. The ODrive can’t store the multi-turn offset, as that would mean writing to EEPROM continuously, which would wear it out (plus in the event of a power failure, it would corrupt the data)
It’s possible to get ‘absolute multi-turn’ encoders though, but these are expensive industrial beasts.
Or, use another absolute encoder at the other end of the gearbox to work out which ‘turn’ the motor encoder is on.

That is indeed odd. full_calibration is simply motor_calibration (which measures motor resistance & inductance) followed by encoder_offset_calibration (which is needed to find a commutation reference) So are you saying that encoder_offset_calibration works even /with/ the leg connected? Or do you have to disconnect the leg?
I suppose index_search might not initialise the commutation reference if encoder_offset_calibration has been done that boot, because the drive already has it. So this could still be an issue with noise on the index input.
Make sure you have set encoder.pre_calibrated=True after you do the encoder_offset_calibration but before you save the config.

I’ve personally never managed to get index_search to work properly, and I’ve heard a number of people having issues with it. And as a control engineer, I struggle to see how it could ever really work with a motor still attached to a load, since the drive will be unable to produce much torque until it has an absolute position reference.
For servo control on PMSM/BLDC motors, I have always used absolute encoders as a matter of course.

Wow, that’s one dangerously large robot. Do you have any public documentation/photos? I’d love to see it.
edit: I think I found it :stuck_out_tongue:.
By legs, you mean castor style wheels with motors to orient them, like a ‘swerve drive’. I can see why you might need a LOT of torque for steering now, given the application.

Is there no way for you to put the encoder on the back of this motor, by gluing the magnet to the stub-shaft, and having a small hole in your mounting plate for the chip?

Multi turn offset is not needed since we keep the absolute position on the MCU that controls the odrive.

There is no way to add a encoder in the leg. The gearbox used is also the mounting mechanism for the leg

When I was testing on the robot itself with legs attached on a bridge I did get some lucky tests with a working index calibration, but most of the time I needed to do a full calibration every time.

For the absolute encoder I need it to work with trajectorycontrol that I can say go to encodercount 16420.

The only documentation we have is a bit out of date this is the link

The steering is back in development fase so the robot cannot stand on the floor but tests have shown that we should have enough torque. 2 people could not stop the motor.

After looking at the motor placements we do have a lot of room above the motor. The motor shaft is super flush with the outside but mounting a magnet must be possible

Yes of course. It will work like any other encoder. The only difference is that encoder counts will always be aligned to motor turns, i.e. positions 0-16383 will always map to specific angles about one motor revolution. But 16420 (with a 14 bit encoder) would map to the same angle as position 36, plus 360 degrees. If you then reboot the drive, it would be back at position 36.
To know what the wheel angle is without any calibration, you would need a second encoder, or be able to assume that it hasn’t moved by more than half a motor revolution since you were last powered on.

I hope your E-Stop works. You don’t want to be chopping anyone in half. :stuck_out_tongue:

Cool, so you should easily be able to mount an absolute encoder then. :slight_smile:
Note that you will need to upgrade your firmware to use them though.

So if the current encoder I use has 8192 counts and I say go to 12288(1.5 rotations) it would be the same as with the absolute encoder that the motor rotates 1.5 times.
As for the moving while it is unpowered. Unless you force the wheel it will not move and everyone here knows not to move the motor. And if that still happens we can recalibrate it on the MCU

Yeah, we have 2 E-stops. One hardware that disconnects the batteries and one software based that sends a emergency command to every MCU.

If that is needed then so be it. If 0.5.1 is stable enough it is ok

The difference is that when you boot up, the position will not be 0. It can start from any position 0-8191.
If you use set_linear_count(0) and then say go to 12288, then it will move by exactly 1.5 turns. Otherwise you’d have to take the current position and add 12288

I’d recommend that you start testing it now.
It’s stable, but there are differences in the commands. You don’t use a special trajectory planner anymore for example, you use the trap_traj input mode instead.
CAN communications are much improved, too.

Is there any chance that this encoder works?
I will say to my boss that we need to buy those encoders then. To do a full calibration every odrive boot is a bit unwanted and possibly impossible once the robot is on the ground

Tomorrow I will check the new firmware if it works. We now use the controller.move_to command via ASCII.

That encoder uses SSI interface, which is a differential-signalling industrial protocol. It’s not currently supported by ODrive. It only supports SPI connected absolute encoders.
However, if you can wait a few months, Oskar has a new revision of the ODrive hardware in the works, which mounts directly to the back of a motor and has an absolute encoder included on board. It should reduce your wiring complexity significantly.

That command might be gone. You would set input_pos instead, but first set controller.input_mode to INPUT_MODE_TRAP_TRAJ.

After some testing with the new firmware I came to the conclusion that the index line was noisy after all even with a shielded cable. After fixing it with capacitors the errors were gone.

So in the end it was noise. Maybe a idea to add that to the troubleshooting docs.

2 Likes