Limit switches on a lift -- best practice

So, I’m porting over our 2012 Robot to Java and I was wondering about how best to use limit switches within the confines of the command-based template. OI runs the raise/lower commands while a button is being held. Would it be best to put the limit switch code within the subsystem methods like so:

private CANJaguar liftMotor1;
    private CANJaguar liftMotor2;
    
    private DigitalInput upperLimitSwitch;
    private DigitalInput lowerLimitSwitch;

public void initDefaultCommand() {
        // Set the default command for a subsystem here.
        setDefaultCommand(new ArmDoNothing());
    }
    
    public Arm() {        
        initCAN();        
    }

.....

public void doNothing() throws CANTimeoutException {
        liftMotor1.setX(0.0);
        liftMotor2.setX(0.0);
    }
    
public void raiseArm() throws CANTimeoutException {
        while(!getTopLimit())
            {
                liftMotor1.setX(0.1);
                liftMotor2.setX(-0.1);
            }
    }
    
public void lowerArm() throws CANTimeoutException {
        while(!getBottomLimit())
            {
                liftMotor1.setX(0.1);
                liftMotor2.setX(-0.1);
            }
    }
    
public boolean getTopLimit() {
        if(upperLimitSwitch.get()) {
            return true;
        } else {
            return false;
        }
    }
    
    public boolean getBottomLimit() {
        if(lowerLimitSwitch.get()) {
            return true;
        } else {
            return false;
        }
    }

(and as an aside, I’ve tested none of this, and I’m sure I probably did something wrong, but you get the point)

Or, would it be best to put the limit switch code within the Commands under execute() or isFinished()? Which I assume would go something like:

protected void execute() {
while(!arm.getTopLimit()) {
try {
arm.raiseArm();
} catch (CANTimeoutException ex) {
System.out.println(ex);
}
}
}

or

boolean stop;
    // Called repeatedly when this Command is scheduled to run
    protected void execute() {
        if(arm.getTopLimit()) {
            stop = true;
        } else {
            stop = false;
        }
        
        try {
            arm.raiseArm();
        } catch (CANTimeoutException ex) {
            System.out.println(ex);
        }
    }
    
    // Make this return true when this Command no longer needs to run execute()
    protected boolean isFinished() {
        return stop;
    }

Are they all more or less equivalent, or is there one way that has significant advantages over the others? Also, am I doing this completely wrong :confused:

To me, dealing with limit switches is a problem internal to the Subsystem - if it had to be dealt with by Commands, it would make every one of your Commands more complicated, which to me seems like insufficient abstraction. As for how to do it, I’d probably do something similar to how WPILibJ’s PIDController works - use an internal TimerTask or Thread to handle the checking and overriding. That way, it doesn’t matter what the Commands try to do - the Subsystem simply won’t allow it to go beyond the limits.

A better way to do it is connect the limit switch directly to the Jaguar, so then you don’t have to write any software to make it work :slight_smile:

We did this in 2011, and when it worked, it was GREAT.

However there was a problem with the CAN software in 2011 where if a limit switch was pressed and connected to the jaguar when the robot was turned on, it would cause the scrolling CAN error. (Hundreds of error messages, resulting in a robot that couldn’t move)

I’m not sure if this was fixed. It probably was.

And you might still need some software to prevent the lift from going full speed into the limit switch. Ouch.

We haven’t messed around with direct sensor-Jaguar control yet, so I don’t know how it all works, but I’m not sure it would work for our situation. We used a screw-style lift (lead screw) which needs limit switches on both the top and the bottom. We also used two motors to drive the lift, which means two Jaguars because the GDC doesn’t allow running two motors off of one controller. Correct me if I’m wrong but the Jaguar only allows input from one sensor at a time; and we need it to be able to accept from two. And since we have two Jaguars that also means we’d need 4 limit switches unless there’s some way to split or duplicate the signal to both of them.

The best way is to wire them to the Jag inputs, but if you are doing this for a FIRST competition I think the rule book requires you to wire them to the cRio and do the work in software.

*2012 Rule R58-J:

Limit switch jumpers may be removed from a Jaguar speed controller and a custom limit switch circuit may be substituted.

At that point, it’s probably easier just to write the 10-12 lines of code it takes to control it with software.

So the general consensus was to put it on the subsystem side as opposed to in execute()?

I believe what Rule R58-J is saying is that you can simply connect the limit switch to the Jag. That is a “custom circuit”.

Correct.

The reason they said “custom” circuit is that in spirit of the rule, it could be anything from a simple limit switch to some crazy ultrasonic circuit. You could even pop in a toggle switch for the rule cares.

However, if the lift is like some I’ve seen/built, then you may have more than two switches involved (like one for each intermediate point used). In that case, then you would have to do at least some of the switches in software, as the jag is only good for two switches.

Generally those two are designed to be your high and low points; these are the points where if you were to overshoot it by a considerable margin very bad things would happen (like stripping a gearbox, breaking an arm joint, accidentally firing a ball, etc.) However, if you choose to split your switches between hardware and software, there is no “wrong” answer in terms of functionality.

http://upurs.us/image/43238.gif

i like limit switches like this where when the switch is tripped it kills power to the motor in one direction but allows you to power the motor in the other direction

i’ve used that diode with 550 china drill motor at 5s to lift 30lb robots

It should be noted that the previous custom circuit is not legal for FRC per R47.

It’s okay for non FRC use, however you must make sure to use both switches and diodes rated for the current they will be passing.
Warning - potential fire hazard

[R47]
Custom circuits shall not directly alter the power pathways between the battery, PD Board, speed controllers,
relays, motors, or other elements of the Robot control system (including the power pathways to other sensors or
circuits). Custom high impedance voltage monitoring or low impedance current monitoring circuitry connected to
the Robot’s electrical system is acceptable, if the effect on the Robot outputs is inconsequential.

The Jaguar can definitely read two limit switches at the same time. This is regardless of the communication mode (CAN or PWM).

This is exactly how the limit switches are handled in Jaguar’s firmware. There is one switch for Forward and one switch for Reverse (marked with an F and R). If only the R switch goes open-circuit, only the Reverse direction is stopped.

-David

be careful with while loops. such as;

while(!getTopLimit())

Remember that the top level loop is controlling robot communication with the field. When you add lower level loops, everything waits for those loops to finish.
It is best to use “IF” statements and avoid loops.

Not always true any more. With the old IFI system it was but now we have a real time operating system. If you spawn off your limit checking code into a new process this while(!getTopLimit()) will function as expected. However, you would need to create a new process for the bottom limit as well. Because of the cost associated with context switches it may not be the best approach.

To answer the original question, Joe has it right. Limit switches should be handled at the level of motor control, not at the level of command input.

I’d say rather that this is effectively how the firmware responds to the limit switches. The word “exactly” implies that the schematic shown represents the circuitry in the Jaguar, and that’s definitely not the case. The motor drive current doesn’t go anywhere near the limit switch connectors. They’re just digital I/O connected to the Jaguar’s microprocessor.

Effectively, though, the Jaguar does the same thing that the schematic is intended to portray. Activating the forward limit prevents the speed controller from commanding the motor to go forward while still letting it go in reverse, and vice versa.