How do I Post to the Game Q&A Forum?

Welcome to the FTC Game Q&A Forum! If this is your first time here, please refer to the Instructions for Forum Use section before posting.

Thank you!

Posts created to sell a product or service are not permitted and will be deleted!

Results 1 to 9 of 9

Thread: Encoder Trouble

  1. #1
    Junior Member
    Join Date
    Jan 2017
    Location
    Leopold
    Posts
    4

    Encoder Trouble

    Hello. My team is relatively new to using encoders, and we are having some trouble getting them to work effectively. Right now, I am simply trying to get both motors to go forward 2240 counts, stop, and then move backward 3000 counts.However, when we run the code, the motors run the 2240 counts, but then stop, buzz, and then the robot gets stuck in stop. Are there any errors that I am missing?

    Here are the pertinent parts of the code:

    @Override
    public void runOpMode() throws InterruptedException {

    leftWheel = hardwareMap.dcMotor.get("ml");
    rightWheel = hardwareMap.dcMotor.get("mr");
    rightWheel.setDirection(DcMotor.Direction.REVERSE) ;;

    waitForStart();

    leftWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_E NCODER);
    rightWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_ ENCODER);
    leftWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION) ;
    rightWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION );

    leftWheel.setPower(.2);
    rightWheel.setPower(.2);

    leftWheel.setTargetPosition(2240);
    rightWheel.setTargetPosition(2240);
    while (leftWheel.getCurrentPosition() < 2240 && rightWheel.getCurrentPosition() < 2240) {
    }

    leftWheel.setPower(0);
    rightWheel.setPower(0);
    sleep(1000);

    leftWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_E NCODER);
    rightWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_ ENCODER);
    leftWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION) ;
    rightWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION );

    leftWheel.setPower(.2);
    rightWheel.setPower(.2);

    leftWheel.setTargetPosition(-3000);
    rightWheel.setTargetPosition(-3000);
    while (leftWheel.getCurrentPosition() < -3000 && rightWheel.getCurrentPosition() < -3000) {
    }

    leftWheel.setPower(0);
    rightWheel.setPower(0);

    }
    }

  2. #2
    Junior Member
    Join Date
    Apr 2016
    Location
    San Diego, CA
    Posts
    18
    You need to flip the comparison in the last while loop, that loop will exit immediately as it is currently written.
    You should also include a call to opModeIsActive in the while loop conditions. That would make your code look like this
    Code:
    @Override
    public void runOpMode() throws InterruptedException {
        
        leftWheel = hardwareMap.dcMotor.get("ml");
        rightWheel = hardwareMap.dcMotor.get("mr");
        rightWheel.setDirection(DcMotor.Direction.REVERSE) ;;
        
        waitForStart();
        
        leftWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_E NCODER);
        rightWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_ ENCODER);
        leftWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION) ;
        rightWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION );
        
        leftWheel.setPower(.2);
        rightWheel.setPower(.2);
        
        leftWheel.setTargetPosition(2240);
        rightWheel.setTargetPosition(2240);
        while (opModeIsActive() && leftWheel.getCurrentPosition() < 2240 && rightWheel.getCurrentPosition() < 2240) {
        }
        
        leftWheel.setPower(0);
        rightWheel.setPower(0);
        sleep(1000);
        
        leftWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_E NCODER);
        rightWheel.setMode(DcMotor.RunMode.STOP_AND_RESET_ ENCODER);
        leftWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION) ;
        rightWheel.setMode(DcMotor.RunMode.RUN_TO_POSITION );
        
        leftWheel.setPower(.2);
        rightWheel.setPower(.2);
        
        leftWheel.setTargetPosition(-3000);
        rightWheel.setTargetPosition(-3000);
        while (opModeIsActive() && leftWheel.getCurrentPosition() > -3000 && rightWheel.getCurrentPosition() > -3000) {
        }
        
        leftWheel.setPower(0);
        rightWheel.setPower(0);
        
    }

  3. #3
    Junior Member
    Join Date
    Jan 2017
    Location
    Leopold
    Posts
    4
    Ok, so it is no longer getting stuck in stop. However, it still doesn't go back 3000 counts. I'm assuming it has something to do with the while loop for the 2240 run time. Do we need to exit that?

  4. #4
    Junior Member
    Join Date
    Apr 2016
    Location
    San Diego, CA
    Posts
    18
    It could be that the motors are never reaching their target... that could be the buzz you hear from the motors, as they try to reach their target.
    Try adding
    telemetry.addData("left motor position", leftWheel.getCurrentPosition());
    telemetry.addData("right motor position", rightWheel.getCurrentPosition());
    telemetry.update();

    to the body of the while loops to see if the motors are truly reaching the target values.

  5. #5
    Senior Member
    Join Date
    Aug 2015
    Location
    Roswell
    Posts
    360
    When using RUN_TO_POSITION it doesn't really make sense to try to keep track of the current position yourself.

    The motor controller will do whatever it takes to reach the position, moving either forward or backward, and then it will attempt to hold that position. That's the buzzing - trying to hold the target position. In your case the actual position probably varies between 2235 and 2245 which is close enough for robotics but will still cause your loop to never exit if either is below 2240. An easier approach is to loop as long as either motor is busy. A motor is busy when it's still trying to reach the target but not busy once it's holding that target. Therefore both of your while loops can look like this:

    Code:
    while (opModeIsActive() && (leftWheel.isBusy() || rightWheel.isBusy())) {
    }
    Notice the use of || (or) instead of && (and). If one motor reaches its target first you probably want the other to keep going.

  6. #6
    Senior Member
    Join Date
    Sep 2013
    Posts
    150
    As others have said, you can use isBusy instead of counts to escape your while loop.
    You also need to make sure your controller is configured for your motors. Use the Core Device Discovery Tool on a computer with your robot phone connected via USB.
    In the motor controller advanced settings, you can choose the motor type. Each motor has unique PID parameters that will effect the performance of your RUN_TO_POSITION.
    See the ModernRobotics website for details/download of the Core Device Discovery Tool.

    A loosely associated problem occurs when the motor controller PID commands the motors to move at a speed less than that needed to overcome friction. When the distance to target is low, the PID commands a low power/speed. Sometimes this speed can't make the bot move, and the motors just keep humming as they unsuccessfully try to slowly move to close the gap.
    Having the correct parameter set from the discovery tool will improve this situation. Running with a slightly faster speed can also help - you are running 0.2. When a fraction of this gets used, the buzzing problem can occur. For us, around 0.06 is just able to start the bot moving in a reasonable amount of time.

  7. #7
    Junior Member
    Join Date
    Oct 2015
    Location
    Phoenix, AZ
    Posts
    4
    Quote Originally Posted by mlwilliams View Post
    When using RUN_TO_POSITION it doesn't really make sense to try to keep track of the current position yourself.

    The motor controller will do whatever it takes to reach the position, moving either forward or backward, and then it will attempt to hold that position. That's the buzzing - trying to hold the target position. In your case the actual position probably varies between 2235 and 2245 which is close enough for robotics but will still cause your loop to never exit if either is below 2240. An easier approach is to loop as long as either motor is busy. A motor is busy when it's still trying to reach the target but not busy once it's holding that target. Therefore both of your while loops can look like this:

    Code:
    while (opModeIsActive() && (leftWheel.isBusy() || rightWheel.isBusy())) {
    }
    Notice the use of || (or) instead of && (and). If one motor reaches its target first you probably want the other to keep going.
    Interesting point regarding using an "or" (||) operator instead of an "and" (&&) one.

    I see that PushbotAutoDriveByEncoder_Linear.java and PushbotAutoDriveByGyro_Linear.java in the external/samples files contains code like:

    Code:
                // keep looping while we are still active, and there is time left, and both motors are running.
                while (opModeIsActive() &&
                       (runtime.seconds() < timeoutS) &&
                       (robot.leftMotor.isBusy() && robot.rightMotor.isBusy())) {

  8. #8
    Senior Member
    Join Date
    Aug 2015
    Location
    Roswell
    Posts
    360
    Both could work based on the intention. Using && causes it to stop as soon as one motor reaches its target. It really depends on what you're trying to do.

  9. #9
    Senior Member
    Join Date
    Dec 2011
    Location
    MD
    Posts
    1,035
    Quote Originally Posted by mlwilliams View Post
    Both could work based on the intention. Using && causes it to stop as soon as one motor reaches its target. It really depends on what you're trying to do.
    The sample code is written with the && for a couple of reasons:

    As you say, it causes the loop to exit as soon as either one of the encoders reach it's mark.

    This usually gives a faster exits from the driving segment. If you do it the other way, the robot may struggle back and forward to get both encoders to reach their mark, and it's possible with a very gripy drive that they may never do it. For this reason we always ALSO include a timeout on any of our RUN_TO_POSITION moves so it cabn'r get stuck.

    Another reason for the && is that if you have a drive wheel/track that is dragging, one side may reach it's final position well before the other. This can cause a "twist" at the end of the motion.
    It's possible that you may need this twist if you are doing several turns, but often it's quite distracting from the desire motion.
    If final heading is important, then it may be desired to change to requiring BOTH moves to be complete before moving on.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •