Announcement

Collapse
No announcement yet.

DC Motor Encoders are not getting Reset.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DC Motor Encoders are not getting Reset.

    We are a rookie team and experimenting with encoders. Here is our simple program to RunToPosition using encoders with Count set to 5503. Encoder count 5503 equates to 24 inches. We are working with the PushBot.

    The op_more runs the first time, but if we stop it and hit the Play button again, we see that the encoder count remains around 5503 and is not reset. The motors do not move. If we select a different op_mode(but do not run it) and then return to the DriveWithEncoders op_mode, the encoder count still shows around 5503. We even added code to reset the encoders in Start and Stop methods as well; but they still do not reset.

    If we choose a different op_mpde and run it, and then return to our DriveWithEncoders op_mode, it works again.

    Maybe we are doing something incorrect, but we have reset it in init, start and stop methods. Please let us know if you see why.

    Also, when the op_mode works and the motors stop after the encoder count matches our count, we can hear humming from the motors. Is that normal? Will the motors burn out because of this.

    This is our first year using Tetrix, so pardon our ignorance if the answer is clear to you!



    /**
    * Created by ashnakhetan on 9/23/15.
    */
    public class DriveWithEncoders extends OpMode{
    DcMotor rightMotor;
    DcMotor leftMotor;

    final static double counts = 5503;


    public void init() {
    leftMotor = hardwareMap.dcMotor.get("left_drive");
    rightMotor = hardwareMap.dcMotor.get("right_drive");

    rightMotor.setDirection(DcMotor.Direction.REVERSE) ;

    leftMotor.setChannelMode(DcMotorController.RunMode .RESET_ENCODERS);
    rightMotor.setChannelMode(DcMotorController.RunMod e.RESET_ENCODERS);

    }

    public void start(){

    leftMotor.setChannelMode(DcMotorController.RunMode .RESET_ENCODERS);
    rightMotor.setChannelMode(DcMotorController.RunMod e.RESET_ENCODERS);

    leftMotor.setTargetPosition((int) counts);
    rightMotor.setTargetPosition((int) counts);

    leftMotor.setChannelMode(DcMotorController.RunMode .RUN_TO_POSITION);
    rightMotor.setChannelMode(DcMotorController.RunMod e.RUN_TO_POSITION);

    leftMotor.setPower(.5);
    rightMotor.setPower(.5);

    }

    public void loop(){
    telemetry.addData ("01", "Motor Target: " + counts);
    telemetry.addData ("02", "Left Motor: " + leftMotor.getCurrentPosition());
    telemetry.addData ("03", "Right Motor: " + rightMotor.getCurrentPosition());

    }

    public void stop(){
    leftMotor.setChannelMode(DcMotorController.RunMode .RESET_ENCODERS);
    rightMotor.setChannelMode(DcMotorController.RunMod e.RESET_ENCODERS);
    }
    }

  • #2
    Upgrade to the latest release and your encoders will reset properly.

    In the release you have the init button isn't implemented yet, so init(), start(), and loop() all run right after each other. The reset encoders command never has a chance to be processed by the hardware.

    Now that the init button works; init() will run then there will be a delay until you press the play button. That will give your encoders a chance to reset. You can also remove the call to reset encoders in your start() method. They're not needed.
    Last edited by Jonathan Berling; 09-23-2015, 10:03 PM.

    Comment


    • #3
      Hopefully this can work for you to get you started. There has to be enhancements to this code to do more than one move.

      Code:
      package com.qualcomm.ftcrobotcontroller.opmodes;
      
      import com.qualcomm.robotcore.eventloop.opmode.OpMode;
      import com.qualcomm.robotcore.hardware.DcMotor;
      import com.qualcomm.robotcore.hardware.DcMotorController;
      import com.qualcomm.robotcore.util.Range;
      
      /**
       * Created by Aluminati on 9/23/2015.
       */
      public class BasicEncoderOp extends OpMode {
          private DcMotor motorLeft;
          private DcMotor motorRight;
      
          // These must be adjusted based on the robot built
          private static final double countsPerRotation = 1120.0;
          private static final double wheelDiameter = 4.0;
          private static final double gearRatio = 1.0;
          private static final double circumference = wheelDiameter * Math.PI;
          private static final double countsPerInch = countsPerRotation / circumference * gearRatio;
          private static final double countsPerDegree = 29000.0 / 5.0 / 360.0;
      
          private static final double distanceToMove = 24.0;  // inches
          private static final double powerToUse = 1.0;       // Positive forward, negative backwards.
      
          // To go straight, Left Counts increases, Right Counts decreases
          // To go backward, Left Counts decreases, Right Counts increases
          private static final boolean leftReversed = false;
          private static final boolean rightReversed = true;
      
          private enum States
          {
              STATE_DO_MOVE,
              STATE_WAIT_FOR_ENCODER_RESET,
              STATE_WAIT_FOR_MOVE_START,
              STATE_MOVING,
              STATE_DONE
          };
      
          private States currentState;
      
          public BasicEncoderOp() {
      
          }
      
          @Override
          public void init() {
      
              // The strings must match names given in Settings->Configure Robot
              motorRight = hardwareMap.dcMotor.get("right");
              motorLeft = hardwareMap.dcMotor.get("left");
      
              // Set the drive mode to run to a specific encoder value
              setDriveMode(DcMotorController.RunMode.RUN_TO_POSITION);
      
              setDrivePower(0.0, 0.0);
      
              currentState = States.STATE_DO_MOVE;
          }
      
          // This is generally the "forever" loop in RobotC. But don't do a forever loop
          // The FTC App will constantly call this loop code.
          @Override
          public void loop() {
      
              // Do operation based on the current state.
              switch (currentState) {
                  case STATE_DO_MOVE:
                      doMove();
                      break;
      
                  case STATE_WAIT_FOR_ENCODER_RESET:
                      waitForEncoderReset(true,distanceToMove,powerToUse);
                      break;
      
                  case STATE_WAIT_FOR_MOVE_START:
                      // Check to see if the robot has started moving
                      waitForMoveStart();
                      break;
      
                  case STATE_MOVING:
                      // Check to see when the robot has finished moving
                      moving();
                      break;
      
                  case STATE_DONE:
                      // Do Nothing
                      break;
              }
      
              telemetry.addData("1 Left Current", motorLeft.getCurrentPosition());
              telemetry.addData("2 Right Current", motorRight.getCurrentPosition());
          }
      
      
          public void doMove()
          {
              // In order to move, the motor encoders must get reset
              // After they are reset, then the move is started
              // Stay in the moving state until target encoder values
              // are reached. Then go on to the next script step
      
              // In order to move, the encoders have to reset to 0
              // which takes one cycle. Then once they are at 0,
              // then the mode has to set to run to position
      
              // Reset the encoders and set the state to STATE_RESET_ENCODER
              // once the current position are 0, then power will be applied
              // to the motors.
              setDriveMode(DcMotorController.RunMode.RESET_ENCODERS);
              currentState = States.STATE_WAIT_FOR_ENCODER_RESET;
          }
      
          /**
           * Returns true if the encoders are reset. Encoders are fully reset when the target position
           * is zero. The current position will reset to 0 fairly quick.
           * @return true if the encoders are reset
           */
          public boolean encodersAreReset() {
              return (motorRight.getTargetPosition() == 0 && motorLeft.getTargetPosition() == 0);
          }
      
          /**
           * Returns if the encoders are zero. This is used to see if movement has started. It
           * assumes that the encoders were reset prior to making this call. If movement has started
           * and the isBusy flag works, then you know movement is done when isBusy is false.
           * @return true if current position of both motors are not zero
           */
          public boolean encodersAreZero() {
              return (motorRight.getCurrentPosition() == 0 && motorLeft.getCurrentPosition() == 0);
          }
      
          /**
           * Check to see if the encoders are reset. Once they are reset, then the target positions
           * are set based on the desired movement. It then transitions to the START_MOVING state.
           */
          public void waitForEncoderReset(boolean straight,double distance,double power) {
              if (encodersAreReset()) {
                  // Encoders are reset so now power can be applied.
                  int counts = 0;
                  int countsLeft = 0;
                  int countsRight = 0;
      
                  setDriveMode(DcMotorController.RunMode.RUN_TO_POSITION);
                  counts = (int) Math.round(distanceToMove * countsPerInch);
                  if (straight == true)
                  {
                      // Determine the number of counts for the distance to go
                      counts = (int) Math.round(distance * countsPerInch);
                      // If power is less than 0, then go backwards
                      // If power is greater than 0, then go forward
                      if (power < 0)
                      {
                          counts = -counts;
                      }
      
                      // A local variable is used to know whether
                      // the motor is "reversed" versus settin a motor direction.
                      // Therefore the target counts will be positive for one side and negative for the
                      // other.
                      if (leftReversed)
                      {
                          countsLeft = -counts;
                      }
                      else
                      {
                          countsLeft = counts;
                      }
                      if (rightReversed)
                      {
                          countsRight = -counts;
                      }
                      else
                      {
                          countsRight = counts;
                      }
                  }
                  else
                  {
                      // Determine the number of counts for the degrees to turn
                      counts = (int) Math.round(distance * countsPerDegree);
      
                      // If power is less than 0, then go left
                      // If power is greater than 0, then go right
                      if (power < 0)
                      {
                          counts = -counts;
                      }
      
                      // To go left and left side NOT reversed, then left counts should be negative
                      // which if power is less than 0 then they already be negative
                      if (leftReversed)
                      {
                          countsLeft = -counts;
                      }
                      else
                      {
                          countsLeft = counts;
                      }
      
                      // To go right and right IS reversed, then right counts should be negative
                      // but for going right the counts are positive so take the opposite sign if
                      // reversed
                      if (rightReversed)
                      {
                          countsRight = counts;
                      }
                      else
                      {
                          countsRight = -counts;
                      }
                  }
                  motorLeft.setTargetPosition(countsLeft);
                  motorRight.setTargetPosition(countsRight);
                  // Encoders control the direction of the motor so just send positive power
                  setDrivePower(Math.abs(power),Math.abs(power));
                  // Next step to is verify the robot is moving
                  currentState = States.STATE_WAIT_FOR_MOVE_START;
              }
              // Encoders not reset, so do nothing - keep current state
          }
      
          /**
           * This is the third state for movement. This is to verify that movement has started by checking
           * that the encoders are not zero. If the isBusy works as I think it is suppose to work, the
           * isBusy flag will transition to false to true and return to false when the movement is done.
           * So don't check for isBusy false until it is seen to transition true. But since it does not
           * behave that way, this state is not really necessary.
           */
          public void waitForMoveStart() {
              // If the encoders are not 0 then moving has started
              if (!encodersAreZero()) {
                  currentState = States.STATE_MOVING;
              }
          }
      
          /**
           * The fourth and final state of motion. This checks to see if the both motor encoders have
           * passed the target values. This assumes overshoot will happen. Ideally the isBusy could be
           * checked and wouldn't have to depend on overshoot.
           */
          public void moving() {
              if ( (Math.abs(motorLeft.getCurrentPosition()) > Math.abs(motorLeft.getTargetPosition())) &&
                      (Math.abs(motorRight.getCurrentPosition()) > Math.abs(motorRight.getTargetPosition()))) {
                  // Robot is done moving - go to the next step in the script
                  setDrivePower(0.0, 0.0);
                  currentState = States.STATE_DONE;
              }
          }
      
      
          /**
           * Sets the drive mode for each motor.
           * The types of Run Modes are
           *   DcMotorController.RunMode.RESET_ENCODERS
           *      Resets the Encoder Values to 0
           *   DcMotorController.RunMode.RUN_TO_POSITION
           *      Runs until the encoders are equal to the target position
           *   DcMotorController.RunMode.RUN_USING_ENCODERS
           *      Attempts to keep the robot running straight utilizing
           *      the PID the reduces the maximum power by about 15%
           *   DcMotorController.RunMode.RUN_WITHOUT_ENCODERS
           *      Applies the power directly
           * @param mode
           */
          public void setDriveMode(DcMotorController.RunMode mode) {
      
              if (motorLeft.getChannelMode() != mode) {
                  motorLeft.setChannelMode(mode);
              }
      
              if (motorRight.getChannelMode() != mode) {
                  motorRight.setChannelMode(mode);
              }
          }
      
          /**
           * Set the power to left and right motors, the values must range
           * between -1 and 1.
           * @param left
           * @param right
           */
          public void setDrivePower(double left, double right) {
              // This assumes power is given as -1 to 1
              // The range clip will make sure it is between -1 and 1
              // An incorrect value can cause the program to exception
              motorLeft.setPower(Range.clip(left, -1.0, 1.0));
              motorRight.setPower(Range.clip(right, -1.0, 1.0));
          }
      }

      Comment


      • #4
        Thanks Jonathan, It works now.

        So is the motor hum normal? When it Runs to Position, is it just trying to hold the motors? Is that the sound?

        Comment


        • #5
          Yes it is, closed loop control of position and the software you called is making small adjustments to keep it still. Wait until you attach something heavy to it...

          Comment


          • #6
            Thanks Zain and FTC 0409!

            Comment

            Working...
            X