Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 114 additions & 1 deletion src/main/java/frc/robot/constants/BiscuitConstants.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,116 @@
package frc.robot.constants;

public class BiscuitConstants {}
import static edu.wpi.first.units.Units.Rotations;

import com.ctre.phoenix6.configs.CurrentLimitsConfigs;
import com.ctre.phoenix6.configs.HardwareLimitSwitchConfigs;
import com.ctre.phoenix6.configs.MotionMagicConfigs;
import com.ctre.phoenix6.configs.MotorOutputConfigs;
import com.ctre.phoenix6.configs.Slot0Configs;
import com.ctre.phoenix6.configs.SoftwareLimitSwitchConfigs;
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.configs.VoltageConfigs;
import com.ctre.phoenix6.signals.ForwardLimitSourceValue;
import com.ctre.phoenix6.signals.ForwardLimitTypeValue;
import com.ctre.phoenix6.signals.GravityTypeValue;
import com.ctre.phoenix6.signals.NeutralModeValue;
import com.ctre.phoenix6.signals.ReverseLimitSourceValue;
import com.ctre.phoenix6.signals.ReverseLimitTypeValue;
import edu.wpi.first.units.measure.Angle;

public class BiscuitConstants {

public static TalonFXConfiguration talonConfiguration() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a duplicate of line 53? If so get rid of this

TalonFXConfiguration talonFXConfiguration = new TalonFXConfiguration();

return talonFXConfiguration;
}

// These are all wrong right now because we don't have any actual info
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move these above the talonFXconfig getter for consistency across constants files

public static Angle kZero = Rotations.of(42); // Will need to be experimentally determined
public static int talonID = 3;
public static double kCloseEnough = 2137473647; // This is a little out of wack.
public static final Angle kMaxFwd = Rotations.of(100);
public static final Angle kMaxRev = Rotations.of(-100);
// public static Angle Level1 = ;

// Disables the TalonFX by setting it's voltage to zero. Not very shocking.
public static TalonFXConfiguration disableTalon() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we needed to disable the fwd limit switch as part of disabling output if it wasn't in a safe region
This could just return a VoltageConfig instead of a full talon config - if you don't change you should get your talonFX config from the one above and just modify the voltage config, not start from a blank one

TalonFXConfiguration disableConfig = new TalonFXConfiguration();

VoltageConfigs voltage =
new VoltageConfigs().withPeakForwardVoltage(0).withPeakReverseVoltage(0);
disableConfig.Voltage = voltage;

HardwareLimitSwitchConfigs limitSwitch =
new HardwareLimitSwitchConfigs().withForwardLimitEnable(false);
disableConfig.HardwareLimitSwitch = limitSwitch;

return disableConfig;
}

// I copied and pasted this because I'm lazy
public static TalonFXConfiguration getFXConfig() {
TalonFXConfiguration fxConfig = new TalonFXConfiguration();

CurrentLimitsConfigs current =
new CurrentLimitsConfigs()
.withStatorCurrentLimit(10)
.withStatorCurrentLimitEnable(false)
.withStatorCurrentLimit(20)
.withSupplyCurrentLimit(10)
.withSupplyCurrentLowerLimit(8)
.withSupplyCurrentLowerTime(0.02)
.withSupplyCurrentLimitEnable(true);
fxConfig.CurrentLimits = current;

HardwareLimitSwitchConfigs hwLimit =
new HardwareLimitSwitchConfigs()
.withForwardLimitAutosetPositionEnable(false)
.withForwardLimitEnable(false)
.withForwardLimitType(ForwardLimitTypeValue.NormallyOpen)
.withForwardLimitSource(ForwardLimitSourceValue.LimitSwitchPin)
.withReverseLimitAutosetPositionEnable(false)
.withReverseLimitEnable(false)
.withReverseLimitType(ReverseLimitTypeValue.NormallyOpen)
.withReverseLimitSource(ReverseLimitSourceValue.LimitSwitchPin);
fxConfig.HardwareLimitSwitch = hwLimit;

SoftwareLimitSwitchConfigs swLimit =
new SoftwareLimitSwitchConfigs()
.withForwardSoftLimitEnable(true)
.withForwardSoftLimitThreshold(kMaxFwd)
.withReverseSoftLimitEnable(true)
.withReverseSoftLimitThreshold(kMaxRev);
fxConfig.SoftwareLimitSwitch = swLimit;

Slot0Configs slot0 =
new Slot0Configs()
.withKP(0)
.withKI(0)
.withKD(0)
.withGravityType(GravityTypeValue.Elevator_Static)
.withKG(0)
.withKS(0)
.withKV(0)
.withKA(0);
fxConfig.Slot0 = slot0;

MotionMagicConfigs motionMagic =
new MotionMagicConfigs()
.withMotionMagicAcceleration(0)
.withMotionMagicCruiseVelocity(0)
.withMotionMagicExpo_kA(0)
.withMotionMagicExpo_kV(0)
.withMotionMagicJerk(0);
fxConfig.MotionMagic = motionMagic;

MotorOutputConfigs motorOut =
new MotorOutputConfigs()
.withDutyCycleNeutralDeadband(0.01)
.withNeutralMode(NeutralModeValue.Coast);
fxConfig.MotorOutput = motorOut;

return fxConfig;
}
}
26 changes: 25 additions & 1 deletion src/main/java/frc/robot/subsystems/biscuit/BiscuitIO.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
package frc.robot.subsystems.biscuit;

public class BiscuitIO {}
import static edu.wpi.first.units.Units.Rotations;
import static edu.wpi.first.units.Units.RotationsPerSecond;

import edu.wpi.first.units.measure.Angle;
import edu.wpi.first.units.measure.AngularVelocity;
import org.littletonrobotics.junction.AutoLog;
import org.strykeforce.telemetry.TelemetryService;

public interface BiscuitIO {

@AutoLog
public class BiscuitIOInputs {
public Angle position = Rotations.of(0);
public AngularVelocity velocity = RotationsPerSecond.of(0);
public boolean fwdLimitSwitchOpen = false;
}

public default void setPosition(Angle position) {}

public default void updateInputs(BiscuitIOInputs inputs) {}

public default void registerWith(TelemetryService telemetry) {}

public default void zero() {}
}
83 changes: 82 additions & 1 deletion src/main/java/frc/robot/subsystems/biscuit/BiscuitIOFX.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,84 @@
package frc.robot.subsystems.biscuit;

public class BiscuitIOFX {}
import com.ctre.phoenix6.BaseStatusSignal;
import com.ctre.phoenix6.StatusSignal;
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.configs.TalonFXConfigurator;
import com.ctre.phoenix6.controls.MotionMagicDutyCycle;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.signals.ForwardLimitTypeValue;
import edu.wpi.first.units.measure.Angle;
import edu.wpi.first.units.measure.AngularVelocity;
import edu.wpi.first.wpilibj.Alert;
import edu.wpi.first.wpilibj.Alert.AlertType;
import frc.robot.constants.BiscuitConstants;
import frc.robot.subsystems.biscuit.BiscuitIO.BiscuitIOInputs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.strykeforce.telemetry.TelemetryService;

public class BiscuitIOFX implements BiscuitIO {

private Logger logger;
private TalonFX talon;

private final Angle sensorInitial;
private Angle setPoint;
private StatusSignal<Angle> position;
private StatusSignal<AngularVelocity> velocity;
private StatusSignal<ForwardLimitTypeValue> fwdLimitSwitch;
private boolean didZero;
private boolean fwdLimitSwitchOpen;
private Angle offset;
private Alert rangeAlert = new Alert("Biscuit overextended! Shuting down!", AlertType.kError);

TalonFXConfigurator configurator;
private MotionMagicDutyCycle positionRequest =
new MotionMagicDutyCycle(0).withEnableFOC(false).withFeedForward(0);

public BiscuitIOFX() {
// Logger initialization with class name
logger = LoggerFactory.getLogger(this.getClass());
// Moter initialization with ID from constants
talon = new TalonFX(BiscuitConstants.talonID);
// Set the starting encoder position
sensorInitial = talon.getPosition().getValue();

// Reset and configure moter settings
configurator = talon.getConfigurator();
configurator.apply(new TalonFXConfiguration());
configurator.apply(BiscuitConstants.talonConfiguration());
// Set our variables
velocity = talon.getVelocity();
position = talon.getPosition();
}

public void setPosition(Angle position) {
setPoint = position.plus(BiscuitConstants.kZero);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have an encoder 1:1 we can actually write to the encoder in the talonFX so we don't actually have to save off zeroed position and use that as an offset

talon.setControl(positionRequest.withPosition(setPoint));
}

public void updateInputs(BiscuitIOInputs inputs) {
BaseStatusSignal.refreshAll(velocity, position, fwdLimitSwitch);
inputs.velocity = velocity.getValue();
inputs.position = position.getValue().minus(BiscuitConstants.kZero);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be able to convert this to just getValue()

inputs.fwdLimitSwitchOpen = fwdLimitSwitch.getValueAsDouble() == 1;
}

public void registerWith(TelemetryService telemetry) {
telemetry.register(talon, true);
}

public void zero() {
didZero = false;
if (fwdLimitSwitchOpen == true) {
Angle pos = position.getValue();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can actually write to the encoder position now so need to add subtraction logic based on zero constant and current pos from a remote encoder

Right now you have no way to get that remote encoder (we need new SW api) so just use get position for now

offset = BiscuitConstants.kZero.minus(pos);
didZero = true;
} else {
rangeAlert.set(true);
logger.error("Biscuit overextended! Shutting down movement!");
configurator.apply(BiscuitConstants.disableTalon());
}
}
}
55 changes: 54 additions & 1 deletion src/main/java/frc/robot/subsystems/biscuit/BiscuitSubsystem.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,56 @@
//Blessed by the great tech-priests of the Adeptus Mechanicus

package frc.robot.subsystems.biscuit;

public class BiscuitSubsystem {}
import static edu.wpi.first.units.Units.Rotations;

import edu.wpi.first.units.measure.*;
import frc.robot.constants.BiscuitConstants;
import java.util.Set;
import org.strykeforce.telemetry.TelemetryService;
import org.strykeforce.telemetry.measurable.MeasurableSubsystem;
import org.strykeforce.telemetry.measurable.Measure;

public class BiscuitSubsystem extends MeasurableSubsystem {

private BiscuitIO io;
private BiscuitIOInputsAutoLogged inputs = new BiscuitIOInputsAutoLogged();
private Angle setPoint;

public void setPosition(Angle position) {
io.setPosition(position);
setPoint = position;
}

public Angle getPosition(Angle position) {
return inputs.position;
}

public AngularVelocity getVelocity(AngularVelocity velocity) {
return inputs.velocity;
}

@Override
public void periodic() {
io.updateInputs(inputs);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to add processInputs()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add logging of the current setpoint to the periodic - see example subsystem for a reference
Put them under "Biscuit/"

}

@Override
public void registerWith(TelemetryService telemetry) {
super.registerWith(telemetry);
io.registerWith(telemetry);
}

public boolean isFinished() {
return setPoint.minus(inputs.position).abs(Rotations) <= BiscuitConstants.kCloseEnough;
}

@Override
public Set<Measure> getMeasures() {
return Set.of(new Measure("Is Biscuit Finished", () -> isFinished() ? 1.0 : 0.0));
}

public void zero() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to use your "didZero" in the i/o layer for passing info up to robotState

io.zero();
}
}
Loading