Infinite rotation with circular position control

Hi all

Just to give a little background, I am trying to create a camera motion system where a motor pulls a camera dolly along a track:

The motor has a worm gear and thus needs to rotate a lot. The idea is also that I can add more tracks and make the hole system much longer.

Therefore it makes sense to me to control the motor in circular position mode. I read some of the info here and here

I start with the following commands in odrivetool:

calibration

In [6]: odrv0.axis0.requested_state=4

In [7]: odrv0.axis0.requested_state=6

In [8]: odrv0.axis0.requested_state=7

In [9]: odrv0.axis0.requested_state=8

set circular mode

In [10]: odrv0.axis0.controller.config.circular_setpoints = True

First thing I notice now is that pos_estimate and pos_circular are not the same. It would be nice if this was the same because after calibration I would expect the axis to be at zero, but if I now sent a new pos_input of 0 the axis will suddenly start to move. But okay I can work around this…

In [11]: odrv0.axis0.encoder.pos_estimate
Out[11]: 0.021331787109375

In [12]: odrv0.axis0.encoder.pos_circular
Out[12]: 0.7835273742675781

next I set the range and the input mode I set to input_mode_trap_traj

In [13]: odrv0.axis0.controller.config.circular_setpoint_range=1

In [14]: odrv0.axis0.controller.config.input_mode=5;

Now I try to sent some commands to keep the motor to rotate. I tried to make the input_pos higher. Sending 0.5 and next 1.5 does not create a rotation but I understand that this is normal in position mode.

In [17]: odrv0.axis0.controller.input_pos=0

In [18]: odrv0.axis0.controller.input_pos=0.5

In [19]: odrv0.axis0.controller.input_pos=1.5

In [20]: odrv0.axis0.controller.input_pos=1

Next I tried sending some incremental_move() commands, because I want to have the motor allways moving in the same direction, but the axis just moves back and forward…


In [23]: odrv0.axis0.controller.move_incremental(0.5,True)

In [24]: odrv0.axis0.controller.move_incremental(0.5,True)

In [25]: odrv0.axis0.controller.move_incremental(0.5,True)

In [26]: odrv0.axis0.controller.move_incremental(0.5,True)

So my question: what do i need to sent to allways have the same rotation in the same direction? I’m a bit confused because I thought the hole idea of the circular pos mode is to keep the rotor spinning with the same amount of steps, and never have a problem with overflow (like the wheels of a robot…). But I dont really understand what I have to sent to the odrive in order to keep the motor spinning in the same direction…

Or does this only work with the step/direction method by sending signals to some GPIO pints?

any help appreciated

1 Like

No, i don’t think circular position is what you are after. Try using incremental moves with ordinary position mode.

minor note: it’s hard to see what you are doing when you use the enum values instead of names :stuck_out_tongue: , e.g. ‘8’ instead of AXIS_STATE_CLOSED_LOOP_CONTROL. If you don’t want to type it out, you can use the ‘tab’ key. i.e. AX<tab>C<tab> is five keystrokes.

Really nice camera rig though! :+1: Is that for 3D scanning or what?

Yeah ordinary position mode works, already tried that. Just wondering (also for future projects) how this cicrular position mode works to avoid the risk of a position value becoming too big…

Great tip, I learned something!

Thank you! I still need to work on it though, the movement is a bit jittery, probably due to some stick slip. I will probably get rid of the rope and add the motor on the camera dolly itself (most professional rigs seem to work like this).

It’s funny, almost everyone who sees the rig asks me if it is for 3D scanning… (perhaps that is a reason by itself to try it at some point.) But my main goal is to make some cool 3d printing time-lapses: while the printer is printing the camera will move very slowly around the print bed.

1 Like

Try moving in increments that is smaller than 1/2 of the circular setpoint range. If you move by the same or larger amount, it will associate it with the “other side” of the circle.

2 Likes

Just tried to do the same as before, but this time only with 0.3 increments.

In [22]: odrv0.axis0.requested_state=AXIS_STATE_ENCODER_OFFSET_CALIBRATION

In [23]: odrv0.axis0.requested_state=AXIS_STATE_CLOSED_LOOP_CONTROL

In [24]: odrv0.axis0.controller.config.circular_setpoints=True

In [25]: odrv0.axis0.controller.move_incremental(0.3,True)

In [26]: odrv0.axis0.controller.move_incremental(0.3,True)

In [27]: odrv0.axis0.controller.move_incremental(0.3,True)

In [28]: odrv0.axis0.controller.move_incremental(0.3,True)

In [29]: odrv0.axis0.controller.move_incremental(0.3,True)

In [30]: odrv0.axis0.controller.move_incremental(0.3,True)

In [31]: odrv0.axis0.controller.move_incremental(0.3,True)

In [32]: odrv0.axis0.controller.move_incremental(0.3,True)

In [33]: odrv0.axis0.controller.move_incremental(0.3,True)

The behaviour is now something like, 2 times a rotation to the right, one time a rotation to the left, 2 times a rotation to the right, one to the left and so on …

So still does not work, direction still alternates. I will move again to the simple position control mode, but I don’t think this circular control mode works correctly right now (that or I still don’t get it)

Ok thanks for letting us know, we’ll look into it.
EDIT: I think move_incremental is unlikely to be broken, but trap_traj does not support circular position mode.
So either use linear mode, or use position mode without trajectory.

1 Like