Preseason: September 13th Summary

Operations:

Created the JDRF One Walk Team and a flyer for the event. We posted everything in FIRST Together to give information and we printing out these flyers in color in order to hang around Bethpage High to inform our peers. As well as this, we began planning on what snacks to offer for our annual Regal Eagle movie night. We came up with ideas and policies for this years season of FRC. Miraj Shah (Drive Coach) and Ankur Raghavan (VP of Engineering) from our team met with new FLL coaches and helped them understand this season better while giving advice for what is needed for a good project and team. We look forward to provide mentorship as the year progresses.

Programming:

All arm movement commands have been generalized to ArmMove.java with inputs of an enum and delay for pivot and wrist. All commands have been replaced by “command wrappers” which are sequential command groups with one command – ArmMove – and the correct enum/delay. Made it so position is only set once, so the adjustments work properly, even if command doesn’t end. We removed unused code + old auto stuff, need to make auto stuff with pathplanner next. The code has a function where the values for our arm setpositions can be adjusted live on the fly by our operator. The operator can then save the position and that position will be used from that point onwards. This is accomplished by all of our pivot and wrist setpoints being written to a text file in the deploy directory. When the robot starts it will read that file to find the setpoints. Then when the positions are adjusted and saved, the file gets overwritten with the new setpoints. This way the setpoints are able to be changed in code and persist across save files. One thing we are looking to add is a backup system that automatically backs up old versions of the setpoints in case we accidentally save it in a bad position and we don’t have time to go back and find the correct spot.

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.CommandBase;
import frc.robot.Constants;
import frc.robot.Constants.PivotConstants;
import frc.robot.Constants.WristConstants;
import frc.robot.Constants.PivotConstants.PositionsPivot;
import frc.robot.Constants.WristConstants.PositionsWrist;
import frc.robot.subsystems.PivotSubsystem;
import frc.robot.subsystems.WristSubsystem;

public class ArmMove extends CommandBase {
	private boolean hasRun = false;

	private double startTime;

	private final PivotSubsystem pivot;
	private final WristSubsystem wrist;

	private final double targetPivotPos;
	private final double targetWristPos;

	private final PositionsPivot pivotEnum;
	private final PositionsWrist wristEnum;

	private final double pivotDelay;
	private final double wristDelay;

	private int pivotCounter;
	private int wristCounter;

	private boolean pivotDone;
	private boolean wristDone;

	private boolean hasSetPivot = false;
	private boolean hasSetWrist = false;

	public ArmMove(PositionsPivot pivotEnum, PositionsWrist wristEnum, double pivotDelay, double wristDelay) {
		pivot = PivotSubsystem.getInstance();
		wrist = WristSubsystem.getInstance();

		this.pivotEnum = pivotEnum;
		this.wristEnum = wristEnum;

		this.targetPivotPos = PivotConstants.getTargetPos(pivotEnum);
		this.targetWristPos = WristConstants.getTargetPos(wristEnum);

		this.pivotDelay = pivotDelay;
		this.wristDelay = wristDelay;

		addRequirements(pivot);
		addRequirements(wrist);

	}

	@Override
	public void execute() {
		if (!hasRun) {
			startTime = Constants.autoTimer.get();
			System.out.println(startTime + ": Arm Movement:" + pivotEnum.name());
			hasRun = true;
		}

		if((Constants.autoTimer.get()-startTime)>pivotDelay && !hasSetPivot){
			pivot.position(targetPivotPos);
			pivot.setCurrentPosition(pivotEnum);
			hasSetPivot = true;
		}

		if((Constants.autoTimer.get()-startTime)>wristDelay && !hasSetWrist){
			wrist.position(targetWristPos);
			wrist.setCurrentPosition(wristEnum);
			hasSetWrist = true;
		}
	}

	@Override
	public boolean isFinished() {
		pivotDone = Math.abs(pivot.getAngle() - targetPivotPos) < PivotConstants.tolerance;
		wristDone = Math.abs(wrist.getAngle() - targetWristPos) < WristConstants.tolerance;

		if (wristDone) {
			wristCounter++;
		} else {
			wristCounter = 0;
		}
		if (pivotDone) {
			pivotCounter++;
		} else {
			pivotCounter = 0;
		}
		if (pivotCounter > Constants.pidTimer && wristCounter > Constants.pidTimer) {
			System.out.println(Constants.autoTimer.get() + ": Arm Movement Done:" + pivotEnum.name());
			return true;
		}
		return false;
	}

	@Override
	public void end(boolean isInterrupted) {
	}
}

At the end of the 2023 season, we realized that we needed more buttons than were on a standard xbox controller. The solution? Two xbox controllers. At champs, the operator used the buttons across 2 xbox controllers to control the different setpoints of the arm and the intake. Post-season we looked into different button boards, and ended up purchasing the X-Keys 60. We have planned out and programmed each of the buttons on this new button board. Here is a photo of the button board layout. We decided to make every action across 2 buttons, so they will be easier for the operator to press. Stopping the Arm/Intake is across 8 and 4 buttons respectively because they are more important buttons. The top row besides the stop button is used for on the fly adjustment. The left-most column is for scoring from the back, center left is for pickup, center right for scoring from the front, and right-most for intake.