Trouble reading magnetic limit switch on Falcon 500

We are using Rev Magnetic Limit Switches to limit the travel of our intake. The limit switch is working and we can see the proper switch state (open/closed) in the Phoenix Tuner app. The arm will not go past the limit switch.

This is where we are having trouble. We want to read the status of the switch so we can end the command. The status of the limit switch in code is only updated at the time of restarting the robot code.

Here is the code:

public int isRevLimit(){
       return deployMotor.isRevLimitSwitchClosed();
}

We have also tried with the SensorCollection method.

Any thoughts?

Thanks,

JMH

Sorry to ask the obvious, but is it possible that your switch is wired as a forward limit, and you should be using isFwdLimitSwitchClosed instead?

2 Likes

Thanks for the reply. We are using both the forward and reverse limit switch. For brevity, I only showed the code for reverse. Both the forward and reverse limit states are frozen at the state at robot code start.

public int isFWDLIMIT(){
    return deployMotor.isFwdLimitSwitchClosed();
}

The snippet looks correct, and I just double checked that both forward and reverse limit switch is accessible in API.
If you see the correct value in Tuner, then I suspect there’s something odd going on in your code. Do you mind linking it so I can try to reproduce the issue?

Sure, our code is here. Thanks for your help.

Another thing that could be wrong is the way we print out the state. We added the isOtherData just to test if it is only the a limit switch issue.

Y.whenPressed(new PrintCommand("Foward Limit: " + m_IntakeMotor.isFWDLIMIT())); 
A.whenPressed(new PrintCommand("Reverse Limit: " +  m_IntakeMotor.isREVLIMIT()));
RB.whenPressed(new PrintCommand("Position: " + m_IntakeMotor.isOtherData()));

I think I see your issue.
Y.whenPressed(new PrintCommand("Foward Limit: " + m_IntakeMotor.isFWDLIMIT()));
This creates a print command that prints a string which is evaluated the moment it’s constructed.
I think if you were to change that to use a lambda, it uses the lambda to evaluate the string when it’s called, so it can actually change.

So the difference is the way you do it now, the string is evaluated once, but if you use a lambda it’s evaluated whenever it’s called.

Does that make sense?

2 Likes

That makes sense and we appreciate your help. I’m not that familiar with lambda. Do you have an example?

We could just do an instant command and put the print inside the “isRevLimit()” method. We will test that tomorrow.

Thanks your help.

I would expect the following to work:
Y.whenPressed(new InstantCommand(()-> System.out.println(m_IntakeMotor.isFWDLIMIT())));
This creates an instant command that triggers whenever you press the button, and executes a print statement with the value of the limit switch.

4 Likes

Thanks again. We aren’t meeting today, but I will test tomorrow and let everyone know how it goes.

1 Like

I had a team with a similar problem where they weren’t calling the function continuously, just once. Here is an example intake command that simply ends when the limit switch trips.

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.CommandBase;
import frc.robot.Constants;
import frc.robot.subsystems.IntakeMotor;

public class Intake_Command extends CommandBase 
{
  private Boolean EndCommand = false;
  private final IntakeMotor m_intakeMotor;
  /** Creates a new Intake_Command. */
  public Intake_Command(IntakeMotor intakeMotor) 
  {
    this.m_intakeMotor = intakeMotor;
    addRequirements(intakeMotor);
    // Use addRequirements() here to declare subsystem dependencies.
  }

  // Called when the command is initially scheduled.
  @Override
  public void initialize() 
  {
    EndCommand = false;
   //initialize stuff like set zero and braking and such
  }

  // Called every time the scheduler runs while the command is scheduled.
  @Override
  public void execute() 
  {
    //Do your actual deploys and such
    EndCommand= m_IntakeMotor.isFWDLIMIT();
  }

  // Called once the command ends or is interrupted.
  @Override
  public void end(boolean interrupted) 
  {
    //Do your end stuff, probably m_intakeMotor.stop(); for example
  }

  // Returns true when the command should end.
  @Override
  public boolean isFinished() 
  { 
    return EndCommand;
  }
}

So when m_IntakeMotor.isFWDLIMIT(); becomes true, is isFinished() function will also return true. Lots of other ways to solve your problem, like with a boolean supplier for example, but this was just the easiest/first thing I thought of

1 Like

Thanks for the help. I am struggling understanding why this is different than what we have. Isn’t isFinished() called every time the scheduler runs?

  public boolean isFinished() 
  { 
    return EndCommand;
  }

Should be the same as

  public boolean isFinished() 
  { 
    return m_IntakeMotor.isFWDLIMIT() == 1;
  }

I should have looked at your github lol. Yes, that should work, though you don’t need the == 1 as that function should return a boolean already.
I assume the print statement never shows a change? Which would mean the problem is the read function itself.
When reading limit switches I usually just read them directly as digital inputs, so something like:

deployMotor.getSensorCollection().isFwdLimitSwitchClosed();

Which is similar to what you are doing, but with just the one call.

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