Stopping motor while motor is moving to new position

Hi all,

Im currently trying to build a very simple camera motion control system. It is basically just a camera mounted on a little 3d printed dolly that rolls on a track and is being pulled by a rope (connected to a motor pulley).

The idea is that every so often, when a counter hits a certain value, the motor rotates a little bit and thus pulls the camera further at a very slow speed. As a safety measure I would like to install a microswitch right before the motor. When the dolly hits the microswitch, the motor should stop (but still hold the position). So this will very likely happen in the middle of a new position command.

The odrive is controlled with arduino. Everything seems to be working (still testing offline, nothing connected to a camera yet…) but I dont feel confident in my current solution.

I tried to implement it by setting the speed to zero once the microswitch is pressed. I also read the motor position at this moment and tell the motor to go to that position (but it should off course stay in place now).

could anyone tell me if this is a good way to stop in the middle of a move?
Also I wonder if I can do an incremental move with arduino? It seems like the TrapezoidalMove is using an absolute position, and I worry about it overflowing…
All advice welcome

motor parameters:

// Setting motor parameters
  odrive_serial << "w axis0.controller.config.vel_limit " << 10000.0f << '\n'; //this is counts/s
  odrive_serial << "w axis0.motor.config.current_lim " << 20.0f << '\n'; //max is 60A
  odrive_serial << "w axis0.motor.config.calibration_current " << 10.0f << '\n'; //to increase torque during calibration? //see https://docs.odriverobotics.com/api/odrive.motor.error
  odrive_serial << "w axis0.controller.config.control_mode " << 3.0f << '\n'; //control mode
  odrive_serial << "w axis0.controller.config.input_mode " << 5.0f << '\n'; // input mode trap trajectory
  odrive_serial << "w axis0.trap_traj.config.vel_limit " << 2000.0f << '\n'; // some values chosen after some trail and error
  odrive_serial << "w axis0.trap_traj.config.accel_limit " << 200.0f << '\n';// some values chosen after some trail and error
  odrive_serial << "w axis0.trap_traj.config.decel_limit " << 200.0f << '\n';// some values chosen after some trail and error

code to control motor position:

if (counter == counter_treshold && endstop_value==HIGH){ //enstop_value high means the microswitch is not pressed
    
      //take picture
      
      //tell motor to rotate
      motor_position+= motor_counts_for_one_move;
      odrive.TrapezoidalMove(0, motor_position); //tell motor 0 to go to the new motor position
      
      counter=0; // reset counter
    }

  if (endstop_value==LOW){ //if microswitch is pressed, motor should immediately stop rotating

      // tell motor to stop
      odrive.SetVelocity(0 ,0.0f);

      // tell motor to stay at this position
      delay(100);
      odrive_serial << "r axis0.encoder.pos_estimate\n";
      odrive.TrapezoidalMove(0, odrive.readFloat());
  }```

Yes, pretty sure you can update the position input in the middle of a trapezoidal move (unless you have really old firmware…)

The easiest way to do what you want would be:
axis.controller.input_pos = axis.encoder.pos_estimate (i.e. set inpit position equal to current encoder value)
If you experience some overshoot, this is probably due to communicattions delay. To make it smoother you could add a proportion of the current velocity e.g. if you think the command is taking 0.01s to execute:
encoder.pos_estimate + encoder.vel_estimate*0.01

Also, might I suggest using a timing belt with a pulley at either end instead of a “rope” - a rope is not good for stopping. :grin:

1 Like

haha yeah your totally right! But its actually a more complicated setup than what you see on the sketch. The tracks also make a curve, so its not so easy to mount a timing belt that follows along that curve.

thanks for the answer, I will try it later.
You don’t happen to know if arduino can let the motor do incremental moves as well? (as explained on bottom of the page here: ODrive.Controller | ODrive ).
I have no idea how to do this with arduino code…

Couldn’t you still use a loop of rope that is constantly under tension though? :thinking:

I’ve never used the Arduino libraries, but you can move to encoder.pos_estimate + pos_increment for an incremental move.

Consider homing off the switch in the first place, then you know never to command a negative value.