FIRST-Tech-Challenge / FtcRobotController

BSD 3-Clause Clear License
685 stars 3.96k forks source link

Counterclockwise motors are getting reverse polarity voltage #322

Closed yoavnycfirst closed 10 months ago

yoavnycfirst commented 2 years ago

Please forgive me if this is the wrong place.

We noticed recently that every tutorial on the internet including Java and Block examples (here for example) are suggesting reversing the Right side motors (except for Neverest) since DC motors are generally Counterclockwise. But we are experiencing motors spinning Clockwise with positive power (from the code).

We reached GoBilda (motors manufacture in our case) and following REV Robotics. Experimenting with Multimeter does show negative voltage when motors are getting Set power to 1 from the code. Motor direction in all experiments remains untouched (forward by default).

Both REV Robotics assumption and GoBilda is that the SDK somewhere sets Counterclockwise motors to get Negative voltage by default so they will spin clockwise.

There is no where mention of such code. Every sample shows otherwise (reversing the right side motors only make sense if Counterclockwise motors remain counterclockwise unless their Direction is set to reverse with the appropriate block).

Is there anything anywhere that sets the motor direction based on the motor configuration (the configuration file XML ?) something isn't right - or so it seems

Many thanks in advance, Yoav

AlecHub commented 2 years ago

A while ago we bought a batch of Modern Robotics based motors. We always bench test motors and encoders when we get a new batch. One of the motors in the batch was turning in the opposite direction of the others. All the motors had the same gearbox. It turns out that the motor that was turning in the opposite direction had the red and black power wires soldered to the wrong terminals on the motor.

yoavnycfirst commented 2 years ago

A while ago we bought a batch of Modern Robotics based motors. We always bench test motors and encoders when we get a new batch. One of the motors in the batch was turning in the opposite direction of the others. All the motors had the same gearbox. It turns out that the motor that was turning in the opposite direction had the red and black power wires soldered to the wrong terminals on the motor.

I wish that was the case :) we tested with a multimeter the reading from the port is -13v which means that control hub sends reverse polarity on positive values from the code (Set Power to 1 for example). we tested multiple motors (after we checked the soldering of the wires to the actual motor) - indeed that was our first suspicion.

We test also Rev / Tetrix and GoBilda motors with same behavior

Lastly I will say we compared REV Hub Interface Software Power set to 1 gives a positive reading of 13v Vs. the one we get when sending power to the motor via an Op Mode

Any thoughts?

Windwoes commented 2 years ago

FWIW in LynxSetMotorConstantPowerCommand there is this comment:

private short power;    // Power level (+CW, -CCW)
yoavnycfirst commented 2 years ago

FWIW in LynxSetMotorConstantPowerCommand there is this comment:


private short power;    // Power level (+CW, -CCW)

That is very interesting find! Any idea if that automatic affects the motors by default?

yoavnycfirst commented 2 years ago

@texasdiaz

@yoavnycfirst The SDK does know which direction a motor is supposed to spin, but only in order to manage encoder data when using RunToPosition() in your code. When setting a power level on your motors the factor that affects motor power polarity is the motor.setDirection() command - if the motor's direction is set to DcMotor.Direction.FORWARD, which is the default motor direction, setting a positive value for a motor power provides a positive polarity (while a direction set to DcMotor.Direction.REVERSE provides a negative polarity).

Note: I'm pretty sure what I just said is correct, but I don't have a hub in front of me to double check.

Are you sure that your motor direction isn't being set to run in reverse?

Yes I was basing my actions on what you said in the first part (nice to learn that re:encoders though)

We tested the ports and with direction forward the ports are sending negative voltage - reverse polarity - when power set to 1 - hence all the robots that are around me (community and ours) are setting the left side motors to reverse which is opposite of normal behavior with ccw motors!

Would love it if you could check on your hub!!

Ps.

REV ROBOTICS tested my experiment with same results - they were surprised and assumed that something has changed in SDK to automatically set CCW motors to run Counterclockwise on direction forward (hence sending negative voltage) but I can't find any documentation of that

texasdiaz commented 2 years ago

@yoavnycfirst Can you provide me with the exact motor setting you're using in your Hardware Configuration? Which motor configuration are you using (so I can reproduce and track it down)?

EDIT: For example, on Motor Port 0, you might define that it's a REV Core Hex Motor and its name is infeed_motor or something along those lines.

Also, please provide the version of the Firmware you've got installed on your Hub.

Windwoes commented 2 years ago

FWIW in LynxSetMotorConstantPowerCommand there is this comment:


private short power;    // Power level (+CW, -CCW)

That is very interesting find! Any idea if that automatic affects the motors by default?

That is from the very lowest level: the binary data that is actually sent over the serial port. I would suggest testing sending a raw LynxSetMotorConstantPowerCommand directly and see what voltage polarity you get with positive power. If it is different than what you get with an SDK command, then that will require further investigation. If not, this is either a Hub firmware bug, or intended purposefully in the FW.

yoavnycfirst commented 2 years ago

@yoavnycfirst Can you provide me with the exact motor setting you're using in your Hardware Configuration? Which motor configuration are you using (so I can reproduce and track it down)?

EDIT: For example, on Motor Port 0, you might define that it's a REV Core Hex Motor and its name is infeed_motor or something along those lines.

@texasdiaz GoBilda 5202/3/4 series

And we called it Front_Right_x

We tried it configured on Control Hub and the attached Expnsion hub

Also with wires only we tried configuration of core hex and Tetrix and all 3 motors caused reverse polarity reading when power set to one and motor direction is set to forward or left at default (also forward in theory but we checked both just in case)

texasdiaz commented 2 years ago

@yoavnycfirst What version firmware is installed on your Hubs? I will be able to test this tomorrow afternoon, I'll let you know what I find.

yoavnycfirst commented 2 years ago

FWIW in LynxSetMotorConstantPowerCommand there is this comment:


private short power;    // Power level (+CW, -CCW)

That is very interesting find! Any idea if that automatic affects the motors by default?

That is from the very lowest level: the binary data that is actually sent over the serial port. I would suggest testing sending a raw LynxSetMotorConstantPowerCommand directly and see what voltage polarity you get with positive power. If it is different than what you get with an SDK command, then that will require further investigation. If not, this is either a Hub firmware bug, or intended purposefully in the FW.

I would try to find someone who can help with the Lynx I'm not sure I'll be able to do it correctly myself ha! - if intentional I would say they should deprecate any mention of reversing the right side motors in samples of drivetrain modes - no?

yoavnycfirst commented 2 years ago

@texasdiaz latest ( we updated everything this week) 🙏🏼🙏🏼

cmacfarl commented 2 years ago

I can confirm that the hub firmware thinks that a positive value is Clockwise, a negative value is CounterClockwise, and it sets pin outputs to that scheme.

yoavnycfirst commented 2 years ago

@cmacfarl if that is so there is an issue with the Control Hub hardware? Code with power set to 1 ends up giving (-13)v when tested with multimeter

Unless perhaps I read your comment incorrectly

Many thanks !!!

cmacfarl commented 2 years ago

The motor configuration for REV motors looks like this...

RevRobotics20HdHexMotor used as an example

@MotorType(ticksPerRev=560, gearing=20, maxRPM=300, orientation=Rotation.CCW)
@DeviceProperties(xmlTag="RevRobotics20HDHexMotor", name="@string/rev_20_hd_hex_name", builtIn = true)
@DistributorInfo(distributor="@string/rev_distributor", model="REV-41-1301", url="http://www.revrobotics.com/rev-41-1301")
public interface RevRobotics20HdHexMotor
    {
    }

You can see in the MotorType annotation that orientation is CCW.

And in the snippet below adjustPower() is called within the SDK when you set a motor power, and

  protected double adjustPower(double power) {
    if (getOperationalDirection() == Direction.REVERSE) power = -power;
    return power;
  }

  protected Direction getOperationalDirection() {
    return motorType.getOrientation() == Rotation.CCW ? direction.inverted() : direction;
  }

 protected Direction getOperationalDirection() {
    return motorType.getOrientation() == Rotation.CCW ? direction.inverted() : direction;
  }

direction.inverted() will return REVERSE if the set direction is FORWARD.

Pulling on the thread, if the motor configuration is CCW, then the operational direction is inverted to become REVERSE, and the power sign is swapped in adjustPower().

cmacfarl commented 2 years ago

As an aside, we don't make discovery of motor configurations easily apparent for users. We should talk about how to improve that. But here you can browse the configuration of all supported motors.

https://github.com/OpenFTC/Extracted-RC/tree/master/Hardware/src/main/java/com/qualcomm/hardware/motors

yoavnycfirst commented 2 years ago

@cmacfarl !! Wow good to know

If that is the case all motors facing the right side of a robot in drivetrain will spin CW

Hence by this new default Left side motors needs to be reversed - Tank Drive, Arcade Drive and Mechnum Drive samples needs to be changed - since they explicitly suggest to reverse the right hand side motors

We were running teacher training from our STEM center and I couldn't explain to the teachers why our drivetrains are left side reversed

Is it possible to make changes to the core samples?

cmacfarl commented 2 years ago

Thanks @yoavnycfirst. We'll take a look. In the meantime, can you specify exactly which files/samples you find confusing? If you can provide paths to filenames that would be great. If you are using Blocks screenshots would be great. Thanks.

yoavnycfirst commented 2 years ago

@cmacfarl many thanks again!

I will start with this oldie:

FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwarePushbot.java

You will see that Right motor is suggested to be direction reverse

It's the same with Blocks from the samples drop down: Tank Drive

I know these are the very basics for rookies but this is where we start with training of teachers and new students .

Of course externally Game Manual 0 hills many other community based resources the Right Motors are suggested to be reversed unless using AndyMark neverest Here is an example :

https://gm0.org/en/latest/docs/software/mecanum-drive.html

cmacfarl commented 2 years ago

Ok, yeah, if the intent of the motor configuration is to define a motor's natural direction of rotation, and then the SDK compensates to define "forward" as clockwise, then HardwarePushbot.java does indeed look backward. We'll take a closer look. Thanks for bringing this to our attention.

yoavnycfirst commented 2 years ago

@cmacfarl greatly appreciated! You are the best! Many great thanks again for the time and consideration 🙏🏼

AlecHub commented 2 years ago

In Configure Robot, if the motor port is configured for a CCW motor, such as GoBILDA or NeveRest 40, I get positive battery voltage at the Expansion Hub motor port. If the motor port is configured for a CW motor, such as NeveRest 20 or Tetrix, I get negative battery voltage at the motor port.

Running SDK 7.1 and latest hub firmware. Here is the code:

DcMotor dcMotor = hardwareMap.dcMotor.get("motor");
dcMotor.setDirection(DcMotor.Direction.FORWARD);
dcMotor.setPower(1.0);
yoavnycfirst commented 2 years ago

@AlecHub expansion hub with no control hub? Also you mean positive voltage with voltage meter? image

That's my voltage with GoBilda motor

AlecHub commented 2 years ago

@AlecHub expansion hub with no control hub? Also you mean positive voltage with voltage meter?

Yes, Expansion Hub with No Control Hub. Yes, Positive voltage reading using a voltmeter such as the one in your picture:

VM_25

yoavnycfirst commented 2 years ago

@AlecHub super interesting! That's the result I get only when using the REV Hub Interface software that allows to send power to motors bypassing the code - I suspected you had no control hub involved! Now this means for you that with power set to 1 your GoBilda motor spins CCW right?

AlecHub commented 2 years ago

... I suspected you had no control hub involved! Now this means for you that with power set to 1 your GoBilda motor spins CCW right?

No Control Hub involved; just Robot Controller phone and Expansion Hub. GoBilda 5201 and 5202 motors spin CW (when looking at gearbox side of the motor):

DcMotor dcMotor = hardwareMap.dcMotor.get("motor");
dcMotor.setDirection(DcMotor.Direction.FORWARD);
dcMotor.setPower(1.0);
AlecHub commented 2 years ago

GoBilda 5201 spins CW (when looking at gearbox side of the motor):

Actually, the 53:1 gearbox spins CW and the 26:1 gearbox spins CCW.

AlecHub commented 2 years ago

GoBilda 5201 spins CW (when looking at gearbox side of the motor):

Actually, the 53:1 gearbox spins CW and the 26:1 gearbox spins CCW.

I can get the 26:1 motor to spin CW by adding the following interface to my TeamCode:

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.hardware.configuration.DistributorInfo;
import com.qualcomm.robotcore.hardware.configuration.annotations.DeviceProperties;
import com.qualcomm.robotcore.hardware.configuration.annotations.MotorType;
import org.firstinspires.ftc.robotcore.external.navigation.Rotation;

@MotorType(ticksPerRev=724, gearing=26, maxRPM=210, orientation=Rotation.CW)
@DeviceProperties(xmlTag="goBILDA5201_26", name="GoBILDA 5201-26", builtIn = true)
@DistributorInfo(distributor="goBILDA_distributor", model="goBILDA-5201-0002-0026", url="https://www.gobilda.com/5201-series-26-1-ratio-210-rpm-spur-gear-motor-w-encoder/")
public interface GoBILDA5201_26
{
}

So in Configure Robot, I can select my new "GoBILDA 5201-26" motor instead of the SDK's "GoBILDA 5201 series" motor to make the 26:1 spin CW when I setPower(1.0).

yoavnycfirst commented 2 years ago

GoBilda 5201 spins CW (when looking at gearbox side of the motor):

Actually, the 53:1 gearbox spins CW and the 26:1 gearbox spins CCW.

I can get the 26:1 motor to spin CW by adding the following interface to my TeamCode:


package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.hardware.configuration.DistributorInfo;

import com.qualcomm.robotcore.hardware.configuration.annotations.DeviceProperties;

import com.qualcomm.robotcore.hardware.configuration.annotations.MotorType;

import org.firstinspires.ftc.robotcore.external.navigation.Rotation;

@MotorType(ticksPerRev=724, gearing=26, maxRPM=210, orientation=Rotation.CW)

@DeviceProperties(xmlTag="goBILDA5201_26", name="GoBILDA 5201-26", builtIn = true)

@DistributorInfo(distributor="goBILDA_distributor", model="goBILDA-5201-0002-0026", url="https://www.gobilda.com/5201-series-26-1-ratio-210-rpm-spur-gear-motor-w-encoder/")

public interface GoBILDA5201_26

{

}

So in Configure Robot, I can select my new "GoBILDA 5201-26" motor instead of the SDK's "GoBILDA 5201 series" motor to make the 26:1 spin CW when I setPower(1.0).

@AlecHub !!!

AlecHub commented 2 years ago

Suggested annotations for the TETRIX® MAX TorqueNADO® 60 motor:

@MotorType(ticksPerRev=1440, gearing=60, maxRPM=100, orientation=Rotation.CW)
@DeviceProperties(xmlTag="TetrixTorqueNADO_60", name="TorqueNADO® 60", builtIn = true)
@DistributorInfo(distributor="Pitsco", model="W44260", url="https://asset.pitsco.com/sharedimages/resources/torquenado_dcmotorspecs.pdf")
public interface TetrixTorqueNADO_60
{
}

I don't know if the 40 and 20 gearboxes are CW or CCW rotation. Trial and error or ask Pitsco.

Suggested annotations (Rotation needs to be verified):

@MotorType(ticksPerRev=960, gearing=40, maxRPM=150, orientation=Rotation.CW)
@DeviceProperties(xmlTag="TetrixTorqueNADO_40", name="TorqueNADO® 40", builtIn = true)
@DistributorInfo(distributor="Pitsco", model="W44240", url="https://asset.pitsco.com/sharedimages/resources/torquenado_dcmotorspecs.pdf")
public interface TetrixTorqueNADO_40
{
}

@MotorType(ticksPerRev=480, gearing=20, maxRPM=300, orientation=Rotation.CW)
@DeviceProperties(xmlTag="TetrixTorqueNADO_20", name="TorqueNADO® 20", builtIn = true)
@DistributorInfo(distributor="Pitsco", model="W44220", url="https://asset.pitsco.com/sharedimages/resources/torquenado_dcmotorspecs.pdf")
public interface TetrixTorqueNADO_20
{
}
epdu commented 10 months ago

We encountered the same challenge, which originates from the REV control hub's configuration file for GoBILDA motors. This issue can be resolved by reaching out to REV for a correction, or alternatively, by employing the REV motor configuration file, even if a specific GoBILDA file exists. Notably, the REV control hub configuration file will invert the voltage for GoBILDA motors, regardless of whether these motors rotate counter-clockwise with positive power or not. This situation impacts all teams utilizing GoBILDA motors, compelling them to either troubleshoot independently or reconsider the use of GoBILDA motors altogether. We've provided comprehensive evidence in the form of test videos and images to REV in the hopes that they will address and rectify this challenge. Despite GoBILDA being a direct competitor to REV, we believe resolving this problem would greatly benefit the entire FTC community. By Powerpuffs

NoahAndrews commented 10 months ago

We encountered the same challenge, which originates from the REV control hub's configuration file for GoBILDA motors. This issue can be resolved by reaching out to REV for a correction, or alternatively, by employing the REV motor configuration file, even if a specific GoBILDA file exists. Notably, the REV control hub configuration file will invert the voltage for GoBILDA motors, regardless of whether these motors rotate counter-clockwise with positive power or not. This situation impacts all teams utilizing GoBILDA motors, compelling them to either troubleshoot independently or reconsider the use of GoBILDA motors altogether. We've provided comprehensive evidence in the form of test videos and images to REV in the hopes that they will address and rectify this challenge. Despite GoBILDA being a direct competitor to REV, we believe resolving this problem would greatly benefit the entire FTC community. By Powerpuffs

Thank you for reporting your findings.

Just to be clear, REV does not maintain the configurations for non-REV motors, but I will make sure that the FTC Tech Team knows you've posted this.

--Noah from REV

epdu commented 10 months ago

Thank you for reporting your findings.

Just to be clear, REV does not maintain the configurations for non-REV motors, but I will make sure that the FTC Tech Team knows you've posted this.

--Noah from REV

Cool

gearsincorg commented 10 months ago

The SDK dev team endeavors to ensure that all listed motors spin in the same direction for a positive setPower() command. Eg: I know the GoBilda YallowJacket motors were tested and setup correctly.

However, as the selection of legal motors increases over time, or model numbers change, or different gearboxes are utilized, it's not always practical or possible to verify and include every one. Noone wants 50 motor selections on a configuration pulldown.

eg: With Planetary gearboxes, all the ratios spin the same way, but with spur gearboxes the direction depends on the specific gear configuration used. eg: the old Neverest 20 and 40 spin in opposite directions.

Assuming that all motorized devices will always naturally spin in the correct direction ignores many factors that can make this assumption false. Unless you are using an extremly simply direct drive wheel, you should be doing this test/setup anyway to accomodate external drive mechanisms and motor mounting configurations. For example, there are now so many ways to build a mecanum drive that these is NO "obvious" way to configure motor directions. You MUST test and set correct rotation direction on every motor. Even with manipulators you should decide on what positive sense you want (eg: positive means extend arm) and set the direction properly.

With all this in mind, the reality is that whatever motor you use, the first thing you should always verify is that the thing it's turning is moving the way you want when you give it a positive power command. And, if it's not, then simply apply the correct Motor.setDirection() command in your hardware setup. Better yet, put that setup in a class and use that class for all your OpModes. This call essentially reverese the motor and encoder values for you, for the rest of the OpMode. Do this once per opmode and you never have to worry about it again. Don't get hung up on which way it "should" turn. Make it turn in the correct direction using Motor.setDirection() as seen in all of the driving samples.

Note: I'm not saying what you are requesting is wrong, but just that it's difficult to maintain in the long run.

Late Edit:

Early on in this thread it was mentioned that many of the samples showed reversing the right drive motors, and that "appeared" to be inconsistent with assuming the +ve power drove motors CW. What was being missed was that in the early days of this SDK, the starter "PushBot" robot used an external gear reduction on the motors which did one more reversal of the drive train. Since then, the references to PushBot have been removed and the left motors are now reversed to be more consistant with a direct drive wheel setup...

epdu commented 10 months ago

In simpler terms, the issue boils down to this: when you push the joystick upwards, which should ideally send a negative signal to the control hub, it instead results in the control hub producing a positive power output.

gearsincorg commented 10 months ago

The conversion of the joystick input into a motor command is completely determined by the user code. I'm not sure what you mean by "ideally". The concept of a 'Positive Power Output" often means "moves forward" which usually (but not always) requires the Direction of some motors to be reversed. Getting this correct is the first step in any drive train. Most samples take the Y joystick value, invert it so "push forward" means "move forward", and then applies it to both sides of the robot. this assumes that you have correctly set the direction of some motors so they all run forwards (regardless of the voltage polarity being output)

Note: this is only "simple" if you are "lucky".

Windwoes commented 10 months ago

This situation impacts all teams utilizing GoBILDA motors, compelling them to either troubleshoot independently or reconsider the use of GoBILDA motors altogether.

To be honest, this seems a bit of an overreaction from in my opinion. If the motor is spinning opposite the direction you want, simply add a negative sign. Simple as that. Not to say the SDK "shouldn't" do the "right thing" in all cases, but the fix here is very straightforward and quick.

texasdiaz commented 10 months ago

I appreciate the discussion had thus far in this issue, it will serve as documentation for those who come after. Everyone who has expressed an opinion thus far has appropriately provided us with input from their perspective. We, as owners of the SDK, value all feedback.

As the owners of the SDK, we frequently have to make difficult decisions that affect the broad usability and impact on all users, and not just a subset of users. As often as possible we go out of our way to improve the experience for teams, but sometimes non-obvious factors prevent us from being able to satisfy the preferences of all of our users. This particular issue is one example.

For the SDK, motor definitions serve a couple primary purposes (though I admit not all of these were intended initially): (1) Serves to identify the motors being used in the SDK for tracking purposes. (2) Defines the pre-gearbox encoder behavior for the motors for the Control/Expansion Hub Firmware. (3) Probably something else that I'm not thinking about at the moment. (EDIT: pidf coefficients, et. al.)

@AlecHub is right, we could have one definition per motor/gearbox combination, and that would be very specific and could provide exact parameters for every motor and gearbox combination that teams could ever want. This has pros and cons. The biggest con, and the one we have to seriously consider, is the impact on users now having to scroll through a never-ending drop-down of motors and gearbox combinations. The number of options is currently minimal, but it seems to go on forever. We could break it up, but is the UI and maintenance impact actually worth it? This is not the way. Sometimes sacrifices need to be made, especially when @Windwoes is correct and the alternative is trivial and likely should be done regardless (after all, not all motors of the same type are always manufactured the same).

And what do we do if we realize there may be a simple fix to standardize the rotation of all motors of a given type given a common set of gearboxes in use by the majority of teams? Even in this case, we still have to think about the ramifications of such a change. In this specific case, think about the millions of lines of code in the wild that, at their core, assume that they have calibrated the robot in a very specific way. Any change we make at this point invalidates millions of lines of code - and it's almost guaranteed that the code will be executed without fully reading the release notes that specific motors now rotate a different way when powered a specific way. We cannot be liable when motors now reverse direction unexpectedly and cause damage to property, or impact the safety of the user. Even in the best of situations this is a non-starter.

I appreciate your feedback, but please understand this is not changing in the SDK, and I hope this post helps you understand just a few of the reasons why.

-Danny

AlecHub commented 10 months ago

FIRST sells the TorqueNADO motors via the FTC storefront, yet the SDK doesn't provide support the TorqueNADO motors:

TorqueNADO

FIRST doesn't sell the NeveRest motors yet the SDK supports the following motors:

It would be helpful to rookie teams for the SDK to support the motors that FIRST sells.

Adding support for a motor doesn't require any changes to the GUI. I've already provided the code for supporting TorqueNADO motors.

As for motors not sold by FIRST, teams can add support for their motors in their OpMode as simply as follows:

StudioR

Which renders as follows in the GUI:

Select3_40R

Still, it would be helpful to rookie teams to have out of the box support in the SDK for the motors that FIRST sells.

Although not necessary to do so, I've prefixed my motor definition names with *""** so as to: