Depending on how your robot is set up and what you’re doing, I would recommend using sensors instead of “dead reckoning” to a specific location. If you’re running into a hardstop that’s okay, but sensors make it much, much easier to know where your manipulator/subsystem is at any given time, without having to “guess” in the code. I see you have a potentiometer set up, so that’s good. Hopefully you’ll eventually be able to integrate it into your code, since I don’t see you using it anywhere at the moment.
I noticed you pushed some new code, and in particular are using a Timer object. Good! A couple notes:
- Nitpick: You’re assigning your
Timer
object twice in robotInit()
-
MotorController
objects (VictorSPX
, Talon
, etc) only accept a double input from -1
to 1
in their set()
method, with 1
being 100% forward, 0.5
being 50% forward, etc. Anything over or under this is truncated. Thus, your calls to arm.set(10)
is actually arm.set(1)
.
- You’re setting
timePassed
to timer.get()
in robotInit()
, which means it will only be updated once when your code starts (and will actually be set to 0.0
at the moment), then never set again. I would recommend not using a “timePassed” class variable, since this is already stored in your Timer object and can be easily obtained by calling timer.get()
. Instead, you can use a local variable in your method to get a consistent comparison of time.
- You’re starting your timer and then immediately stopping it in some of your if statements, such as here. I recommend calling stop() and reset() when your if statement (for example,
if(timePassed > 0.06)
) is executed instead. You’ll probably also want to move your other “ending state” logic in as well.
Overall example:
public void arms(){
if(stickL.getRawButton(3) && !areArmsOn && currentArmPos == 2){
areArmsOn = true;
arm.set(1);
timer.start(); // I think this can be called multiple times without issue?
if(timePassed > 0.06) {
arm.set(0);
areArmsOn = false;
currentArmPos = 3;
timer.stop();
timer.reset();
}
}
// More code...
}
Remember: This code is being executed once every 20ms. You want to allow it to run through your code really fast without blocking it. The teleopPeriodic()
method will be called every 20ms, which is in turn is calling your arms()
method. You don’t want it to block when these methods are called, which is why swapping to a Timer is nice. This does, however, mean that you need a slightly different mindset of how this code is being executed. Instead of having one block of code execute everything it needs to in one pass – eg with Timer.delay()
– you need to remember that this code can be executed 1, 2, 5, 10, or even more times before every part of the method you want to execute is actually executed. Namely, the part in your timePassed
if statements; these will only run once your timer has been running for a certain amount of time.
Depending on how complex you want your functions to be, it may be a good idea to consider swapping over to CommandBasedRobot, which gives you a nice, structured system that pulls logic into separate classes. This allows much better separation of code, which in turn makes very complex robots much more manageable. It comes at the cost of abstracting away some code execution logic – namely executing Commands with WPILib Scheduler constructs, such as when you’re mapping joystick button actions to Commands – and makes it a little more difficult to map out when things will execute just by looking at code, however I think it’s a much nicer system than shoving everything into one file.
Let me know if I overexplained this…