ftctechnh / ftc_app

FTC Android Studio project to create FTC Robot Controller app.
759 stars 3.17k forks source link

Core Motor Controller randomly reverses polarity of motor control power #286

Open AlecHub opened 7 years ago

AlecHub commented 7 years ago

The NeveRest 3.7 Gearmotor (am-3461) is purportedly a legal motor because it purportedly employs the legal am-3104 motor.

Numerous applications of a DC motor, such as a flywheel particle accelerator, require the DC motor to maintain a constant RPM.

When programmed to maintain a constant RPM, the Core Motor Controller reverses the direction of the am-3461 motor (i.e. the polarity of the power it sends to the motor) at randomly intervals, usually within 1 to 2 minutes of the last time the motor controller reversed polarity.

Code to reproduce:

flywheel.setPower(0.0);
flywheel.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER);
flywheel.setMaxSpeed(3000);
flywheel.setMode(DcMotor.RunMode.RUN_USING_ENCODER);
flywheel.setPower(1.0);

Environment:

gearsincorg commented 7 years ago

Once the SDK issues the power command to the Core motor controller, it goes "hands off". At that point the motor is under the control of the controller.

I notice that you are setting the MaxSpeed to 3000. My experience is that the Neverest motor (which has the encoder on the motor shaft, not the output shaft) can only achieve about 2400 - 2600 CPS, depending on battery voltage.

So the PID in the Core Controller is probably constantly accumulating an integration error as you are running. I can not speak to the math inside the controller, but it's possible that after several minutes of accumulation there may be a math error that is doing the reversal.

You should try setting the max speed to something achievable (eg: 2400). and see if the problem persists.

AlecHub commented 7 years ago

setMaxSpeed(2400) yields same result, Core Motor Controller randomly reverses polarity of power sent to the motor.

Note that I've said "Core Motor Controller reverses polarity"; not "SDK reverses polarity".

gearsincorg commented 7 years ago

Got it.

Since we don't have much insight into the Core Controller logic, I will propose some other options.

Does this happen on more than one motor? If the encoder lines or the encoder itself was failing, it's possible that many erroneous counts could be generated in either direction. Could you try displaying the encoder values while it's running? This might shed light on "why" the controller is reversing. eg: if the encoder values jump suddenly.

If it happens on two motors (say on a shooter) does it happen at similar times,or are the reversals really "random".

gearsincorg commented 7 years ago

I've loaded your original test code into an opmode, and run it on one of my CORE controllers with a non-neverest motor attached.

I ran the motor for 10 minutes with no reversals or any strange behavior (several times). The encoders got up to 1,200,000 with no trouble.

So I'm still suspecting an encoder/cable issue on your motors (or on the new 3.7 motors.. I don't have any to test)

AlecHub commented 7 years ago

I am able to reproduce the issue with all four of our 3.7 motors. I am not able to reproduce the issue when I swap the 3.7 motor with a 20, 40, or 60 motor (i.e. same Core Motor Controller, encoder cable, and power cable).

When testing the 3.7 motor with the Core Device Discovery App, the encoder values increase or decrease smoothly. When the Core Motor Controller reverses polarity, the encoder values change direction also. If the encoder values were increasing, they start decreasing, and if they were decreasing they start increasing. The encoder values don't suddenly change sign, nor jump to some random value at the time the Core Motor Controller reverses polarity.

Given that there are no obvious anomalies in the encoder values for the 3.7 motor, I don't see any reason for the Modern Robotics firmware to randomly reverse polarity. It's not like the firmware is only momentarily reversing polarity, which may make sense. The firmware is reversing polarity for good (or rather until the next time it decides to randomly reverse polarity).

I've conducted the tests both under load and no load with the same results.

AlecHub commented 7 years ago

Some new data...

Over a 30 second period, the NeveRest 20, 40, and 60 motors yield roughly 75K pulses with no load (observed using Core Device Discovery App with power set to 100). We expect all NeveRest motors to yield the same number of pulses. However, all four 3.7 motors yield roughly 38K pulses in 30 seconds.

So there is definitely an issue with the NeveRest 3.7 encoder (root cause may not be the encoder itself).

Regardless, I feel the Core Motor Controller firmware should not randomly reverse power polarity under these circumstances.

gearsincorg commented 7 years ago

Ah... if the encoders are actually outputting less than expected CPS (as I've also heard from another coach), then setting the Max CPM at 2400 is still to high. (May still be causing the PID integrator to wind up too high and wrap the signed number to the opposite polarity.)

Try setting either the max speed to 1000, or just request a lower speed (say 0.25)

NOW, I think the reversal will go away...

tip: Always ensure that the motor is running at less than full speed by seeing that the speed is being controlled)

AlecHub commented 7 years ago

Try setting either the max speed to 1000, or just request a lower speed (say 0.25)

According to the specs, the no load CPS for the NeveRest 3.7 motor is 3063. There is a bug in the AndyMark specs and/or a bug in the encoder, AND there is a bug in the Modern Robotics firmware. Setting max speed to 1000 or requesting lower speed is just a workaround to these bugs.

Consider the case where your encoder cable or cable header goes bad. The Core Motor Controller firmware will randomly change power polarity in this case. Should be an easy fix for Modern Robotics.

gearsincorg commented 7 years ago

If the current assumptions are correct, all of what you say is true.

At this point the questions are best directed to the parties that can act on them. I've sent a question through to AndyMark on their general contact form, you are free to do the same.
You should also forward your concerns directly to MR.

At this point, there is little that can be done by the SDK, so it's probably best to close this issue here, and take it up closer to the source.

AlecHub commented 7 years ago

I've been dialoging with AndyMark since yesterday. They are aware of this ticket and are free to comment on it.

I will send an email to Modern Robotics and ask them to comment on this ticket as well.

I think that teams are better served if we consolidate tracking of this issue in one public tracing system (i.e. this one), rather than forking off this issue into 2 private tracking systems.

There is also the question of the legality of the NeveRest am-3104 motor in combination with gearboxes that affect the published specs of the am-3104 encoder.

gearsincorg commented 7 years ago

Well...... it seems that this issue is already active on several forums already. Most importantly, the FTC Technology Forum (recommended by FIRST to post general control questions/issues/answers).

Since it's becoming of a more general hardware issue, than a SDK one (which is the focus of this repository) I'll be continuing my activity on the Tech Forum.

AlecHub commented 7 years ago

Oops, somehow I completely forgot about our other tracking system. My bad.

acgandhi commented 7 years ago

Over a 30 second period, the NeveRest 20, 40, and 60 motors yield roughly 75K pulses with no load (observed using Core Device Discovery App with power set to 100). We expect all NeveRest motors to yield the same number of pulses. However, all four 3.7 motors yield roughly 38K pulses in 30 seconds.

My experience is that the Neverest motor (which has the encoder on the motor shaft, not the output shaft) can only achieve about 2400 - 2600 CPS, depending on battery voltage.

Interesting fact: the Neverest 3.7 actually has 3/7th of the counts per revolution of the internal motor. Andymark states on their product page, as of an update on 12/07/16, that the Neverest 3.7 has 44.4 CPR (counts per rotation), on the output shaft. Divide by the gear ratio, that gives 12 CPR on the internal motor. Compare this with the 1120 CPR of the Neverest 40, which divided by the gear ratio, gives 28 CPR on the internal motor, or the same value stated by Andymark on the page for the am-3104.

12/28 gives a ratio of 3/7, which correlates with another value given by Andymark, the 3 poles-per-magnet on the Neverest 3.7, vs the 7 poles-per-magnet on all other Neverests.

AlecHub commented 7 years ago

Update: Modern Robotics has reproduced the issue and has provided a workaround:

... Load the Core Device Discovery program from the MRI web site, http://modernroboticsinc.com/coredevicediscovery with the motor controller connected to your PC USB port. Note the motor controller must be powered from the 12v battery via the Power Distribution module. Device discovery will display the attached motor controller details. Click on the Advanced button. For the motor channel with the 3.7 motor connected, click on the motor type dropdown and chose "Custom Configuration". Enter the following, P=128, I=40, D=192, Ratio =57. Click on PID Set button to save the parameters in the controller.

The workaround appears to resolve the issue, however, we are not getting the encoder counts per second we are expecting. Our maximum no-load CPS is 1250. The following are our CPS readings at setPower(1.0):

setMaxSpeed() value Measured CPS
1000 285
1250 348
2000 560
3000 843
4000 1123

In other words, the encoder counts per second yield is roughly 28% of the setMaxSpeed() value (i.e. 72% headroom), which is way more than the 20-30% headroom percentages that have been floated around.

When we run our tests with the Core Device Discovery App, we are getting roughly 1100 CPS at Power=100, so this appears to be an SDK issue.

gearsincorg commented 7 years ago

I think you'll find that the changes you have made using the Core Discovery Utility (CDU) negates the need to change the MaxSpeed value in the SDK.

ie: if you are going to use the CDU to load the parameters for a NR3.7 motor into your controller, then you must let the SDK issue the full range of power commands. You do this by either not issuing any setMaxSpeed() commands, or by issuing the highest possible speed. setMaxSpeed(4000).

From your chart you can see that this most closely reflects the expected behavior.

It's confusing, but you need to remember that the Code Discovery Module is NOT JUST provided just for FTC teams. It's use is more generalized, and it can utilize information and interfaces not shared with FIRST. The SDK isn't aware of changes you have made to the controller, it so assumes an unmodified Motor controller.

You need to choose to do one or the other: Use the CDU or Use the setMaxSpeed()

Either way, the SDK is reporting the correct encoder counts... By setting a lower MaxSpeed, you are essentially asking the SDK to scale down the "power" request to the Motor controller, which is is causing it to run slower (because you have changed your controller settings), which is now causing your lower counts.

AlecHub commented 7 years ago

The SDK isn't aware of changes you have made to the controller, it so assumes an unmodified Motor controller.

An unmodified motor controller is configured with the PID parameters of the Matrix motors. Are you suggesting that when using SDK, teams should use the Matrix "PID" parameters to control their Tetrix, AndyMark, and AndyMark3.7 motors?

gearsincorg commented 7 years ago

For the record, teams have been using the PID values that were tuned for the TETRIX motor for the past 7 years. Only recently has there even been the suggestion of using different PID values. The older controllers have all had PID registers, but there was no information available to indicate how they should be set.

So, the ability to set "other" PID values is pretty new, and the information on what values to use has just recently come to light. The fact than an "Unmodified Controller is using values for a MATRIX motor" is a pretty stunning revelation, since that motor has only been released this year, and has yet to gain any real traction in FTC in the US. Until recently I'm pretty sure that EVERYONE was assuming that the default motor controller configuration was for a TETRIX motor.

I don't know what you mean by: "when using SDK". what are you setting maxSpeed to in this instance?

If you believe what MR is saying, then the best bet would be to configure your Controllers to suite your motor type, and then don't tell the SDK anything different... Just let it use maxSpeed of 4000. That way it will issue the full range of power values (-1 to + 1) and the controller will take care of choosing the correct CPS (ratio) and PID parameters.

Am I a believer? We'll see.

AlecHub commented 7 years ago

For the record, teams have been using the PID values that were tuned for the TETRIX motor for the past 7 years. Only recently has there even been the suggestion of using different PID values. The older controllers have all had PID registers, but there was no information available to indicate how they should be set.

That was with the old technology. The Core Motor Controller is the new technology, so it shouldn't be a surprise that the new technology is different than the old technology.

So, the ability to set "other" PID values is pretty new, and the information on what values to use has just recently come to light. The fact than an "Unmodified Controller is using values for a MATRIX motor" is a pretty stunning revelation, since that motor has only been released this year, and has yet to gain any real traction in FTC in the US. Until recently I'm pretty sure that EVERYONE was assuming that the default motor controller configuration was for a TETRIX motor.

Again, this is the new technology. The Core Motor Controller currently has 4 possible PID configurations, AndyMark, Matrix, Tetrix, and Custom. One of these configurations must be active. The Matrix PID configuration is the active configuration on both ports of a stock unmodified motor controller.

We request that FIRST and Modern Robotics get together to draft the necessary documentation on how to properly configure the Core Motor Controller in the new technology, and how to properly use the setMaxSpeed() function for each brand/model of legal FTC motor.