Talons on flywheel not function correctly

Where are using the built-in PIDF for out flywheel and are unable to reach our setpoint. Our motors were working fine one moment, and the next they were not moving at all. We didn’t change anything in the code. Please help :frowning:

You will need to post your code for anyone to help you. Is it on Github? That would be the best way to share it.

1 Like

It’s a simple PIDF using setReference for our talons. Not much to share.

Even so, you need to share your code because there are many small things that could be incorrect, and that’s probably where your problem is.

package frc.robot.subsystems;

import com.ctre.phoenix.motorcontrol.ControlMode;
import com.ctre.phoenix.motorcontrol.FeedbackDevice;
import com.ctre.phoenix.motorcontrol.NeutralMode;
import com.ctre.phoenix.motorcontrol.StatusFrameEnhanced;
import com.ctre.phoenix.motorcontrol.TalonFXInvertType;
import com.ctre.phoenix.motorcontrol.can.TalonFX;
import com.ctre.phoenix.motorcontrol.can.TalonFXConfiguration;
import com.ctre.phoenix.motorcontrol.can.TalonFXPIDSetConfiguration;
import com.revrobotics.CANSparkMax;
import com.revrobotics.RelativeEncoder;
import com.revrobotics.SparkMaxPIDController;
import com.revrobotics.CANSparkMax.ControlType;
import com.revrobotics.CANSparkMax.IdleMode;
import com.revrobotics.CANSparkMaxLowLevel.MotorType;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants;

public class ShooterSubsystem extends SubsystemBase {
  /** Creates a new KickerSubsystem. */
  // CANSparkMax rightShooter = new CANSparkMax(Constants.rightShooterID,MotorType.kBrushless);
  //CANSparkMax leftShooter = new CANSparkMax(Constants.leftShootID,MotorType.kBrushless);

  TalonFX right = new TalonFX(Constants.rightShooterID);
  TalonFX left = new TalonFX(Constants.leftShootID);

  //RelativeEncoder leftEnc = leftShooter.getEncoder();
  // RelativeEncoder rightEnc = rightShooter.getEncoder();
  
  
  //SparkMaxPIDController leftPID = leftShooter.getPIDController();
  // SparkMaxPIDController rightPID = rightShooter.getPIDController();

  


  // leftShooter.enableBrakeMode();
  

  //       talon_.enableLimitSwitch(true, true);
  //       talon_.ConfigFwdLimitSwitchNormallyOpen(true);
  //       talon_.ConfigRevLimitSwitchNormallyOpen(true);
  //       talon_.setStatusFrameRateMs(CANTalon.StatusFrameRate.Feedback, 10);
  //       talon_.setFeedbackDevice(CANTalon.FeedbackDevice.CtreMagEncoder_Relative);

  // SimpleMotorFeedforward feedforward = new SimpleMotorFeedforward(.4402, .13453, .0093554);



  public ShooterSubsystem() 
  {
right.configFactoryDefault();
left.configFactoryDefault();

left.setInverted(TalonFXInvertType.Clockwise); //was CounterClockwise - is jittering

right.setInverted(TalonFXInvertType.CounterClockwise); //was Clockwise

// right.setNeutralMode(NeutralMode.Coast);
// left.setNeutralMode(NeutralMode.Coast);

// talon.configClosedloopRamp(0.5);//0.5 seconds from nuetral to full power in closed loop control
// this means you are using the intergrated sensor using the standard 0 channel(always use 0) and it is updating every 10 ms
right.configSelectedFeedbackSensor(FeedbackDevice.IntegratedSensor,0,10);
left.configSelectedFeedbackSensor(FeedbackDevice.IntegratedSensor,0,10);


// TalonFXConfiguration configs = new TalonFXConfiguration();
// /* select integ-sensor for PID0 (it doesn't matter if PID is actually used) */
// configs.primaryPID.selectedFeedbackSensor = FeedbackDevice.IntegratedSensor;
// /* config all the settings */
// talon.configAllSettings(configs);

right.configVoltageCompSaturation(11.5); // "full output" will now scale to 11 Volts for all control modes when enabled.
right.enableVoltageCompensation(true);

left.configVoltageCompSaturation(11.5); 
left.enableVoltageCompensation(true);

// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_3_Quadrature, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_10_MotionMagic, 65310);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_10_Targets, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_11_UartGadgeteer, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_14_Turn_PIDF1, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_15_FirmwareApiStatus, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_4_AinTempVbat, 65300);
// talon.setStatusFramePeriod(StatusFrameEnhanced.Status_12_Feedback1, 65300); 

double ff = 0.057;
double p = 0.168;
double i = 0;
double d = 0;
right.config_kF(0, ff, 10);
		right.config_kP(0, p, 10);
		right.config_kI(0, i, 10);
		right.config_kD(0, d, 10);

left.config_kF(0, ff, 10);
		left.config_kP(0, p, 10);
		left.config_kI(0, i, 10);
		left.config_kD(0, d, 10);




// rightShooter.restoreFactoryDefaults();
//leftShooter.restoreFactoryDefaults();
// rightShooter.setIdleMode(IdleMode.kCoast);
//leftShooter.setIdleMode(IdleMode.kCoast);
// rightShooter.setInverted(false);
//leftShooter.setInverted(true);

// leftPID.setP(0.00022);
// leftPID.setI(0.000002);
// leftPID.setD(0.00009);
// leftPID.setFF(.000252);

// rightPID.setP(0.00022);
// rightPID.setI(0.000002);
// rightPID.setD(0.00009);
// rightPID.setFF(.000252);

// rightShooter.setPeriodicFramePeriod(PeriodicFrame.kStatus1, 64500);
// rightShooter.setPeriodicFramePeriod(PeriodicFrame.kStatus2, 64400);

// leftShooter.setPeriodicFramePeriod(PeriodicFrame.kStatus2, 64300);

  }

  /**
   * 
   * @param a Velocity to be set
   */
  public void setShooterVelocity(double rpm)
  {
// leftPID.setReference(rpm, ControlType.kVelocity);
// rightPID.setReference(rpm, ControlType.kVelocity);
// leftShooter.set(1000, ControlType.kVelocity);
// leftShooter.set(a);
// rightShooter.set(a);
// SmartDashboard.putNumber("Fly Wheel", getVolicty());
right.set(ControlMode.Velocity, (rpm/600)*2048);
left.set(ControlMode.Velocity, (rpm/600)*2048);
  }

  public void setShooter(double volt) {
left.set(ControlMode.PercentOutput, volt);
right.set(ControlMode.PercentOutput, volt);
  }

  // public double getVolicty()
  // {
  //   // return (leftEnc.getVelocity()+rightEnc.getVelocity())/2;
  // }
  
  @Override
  public void periodic() {
// This method will be called once per scheduler rn
// SmartDashboard.putNumber("Fly Wheel", getVolicty());
SmartDashboard.putNumber("fly Wheel", (right.getSelectedSensorVelocity() * 600) / 2048 );
  }
}

After a cursory glance, the only thing I see that might be causing the issue is the use of whileActiveContinuous instead of whileHeld in configureButtonBindings for the shoot command. That shouldn’t make a difference in functionality based on the documentation, which seems to imply that these have identical functionality.

I would do the following in your situation, and after each action check to see if it’s working:

  • Check controllers in the driver station, make sure they’re on the correct port and that they are working properly
  • Redeploy robot code (this also restarts robot code, which is helpful alone also)
  • Replace battery (this will also reboots the robot, which is useful on it’s own)
  • Check that the motors are plugged in properly, both with power (including the breaker on the PDP/PDH) and on the CAN bus
  • Check that the rest of the robot is still functional, and see if it’s really an issue with just the shooter
  • Check that the talons have the proper, matching port numbers in both Phoenix Tuner and the code.
  • Check that the greater CAN bus is intact, checking wires, each connection, the flashing lights on the motor controllers, and in Phoenix Tuner

Going through all these steps will probably solve your issue, I know they solve nearly all of mine.

2 Likes

Quick check to see if you have the proper breaker on your power distribution hub\board

1 Like

The thing that leaps out at me is that you have two flywheel motors, and you are setting them to have separate PIDF controllers. This will probably kind-of work, but best practice would be to have one motor be PIDF-controlled, and configure the other as a follower.

Before you make that change, a few more things to check:

  • When you activate the subsystem and your motors are “not moving at all”, what do their status lights show?
  • For the same experiment, do the motors get hot? If so, this indicates that they are stalling against each other.
  • If you disconnect one of the motors in turn, does the wheel spin? In the right direction? What about if you disconnect only the other one?

Even with a leader-follower setup, you still need to be careful to set inverted correctly. I believe the best practice for TalonFX is to call setInverted before calling follow.

2 Likes

Thank you :slight_smile:

To add on to this, if they are geared together, you should absolutely set a leader and follower. Not doing so can damage your falcons. If you ever hear a high pitched, whining sound coming from the motors, stop running them immediately and double, triple check your code.

2 Likes

We tried the motor following thing, but we still had the same problem. It may just be a bad talon…

our team had an issue where our gearing made it difficult for a pid loop to control and ended up burning up 3 neos. Ask a mech mentor about gearing maybe? Our 5 lbs of flywheel might make that issue more relevant for our bot. What does your flywheel weigh? What gearing are y’all using?

The whileHeld thing fixed it. Thank you so much :grinning::grinning::grinning::grinning:

1 Like

That’s a frustrating end to this story. Here is the source code for whileHeld:

public Button whileHeld(final Command command) {
    whileActiveContinuous(command);
    return this;
}

Redeploying code or power-cycling the robot may very well have been the solution. I have found that FRC robots do not like being on for more than a few minutes at a time, and random stuff just breaks if there isn’t some restart. something something java garbage collection

True. It’s possible that a momentary loss of power (say from a voltage dip) is making the motor controllers forget their settings, specifically the inversion. I’ve seen many threads reporting such issues with the Spark MAX, but not with Talon FX.

Wow, that is weird. We haven’t experienced the issue since we implemented the whileHeld, however we also motors not follow each other in the same update. Maybe the other thing fixed it…

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.