Go to Post Computers have a nasty habit of doing exactly what you tell them to do instead of what you want them to do. - KenWittlief [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
 
 
Thread Tools Rate Thread Display Modes
Prev Previous Post   Next Post Next
  #1   Spotlight this post!  
Unread 25-11-2015, 20:14
Asymons Asymons is offline
Registered User
FRC #4716 (Purple Raiders)
Team Role: Driver
 
Join Date: Apr 2013
Rookie Year: 2013
Location: Ontario
Posts: 33
Asymons is an unknown quantity at this point
Oscillating Motor - PID Subsystem

Hello CD,
Yet another PID help thread, I apologize, but my team and I were having troubles with implementation of the PID Subsystem to properly work with our elevator lift. Originally we had the lift just stop once it went over a certain setpoint(which worked to some degree) but we now wanted a more accurate and elegant solution.

Setup:
We have two standard CIM motors as the output, and one encoder as the input. There is no CAN, just PWM and regular victors being used.

Issue:
-The implementation of the PID Subsystem results in the motor reaching the desired setpoint; however, oscillates when it reaches it.
-When the Robot is disabled quickly after the fear that the oscillation will break the elevator, when it is re-enabled it continues the PID command right when enabled without any buttons pressed. When the robot code is re-deployed or reset, this does not happen.

Attempted Solutions:
-Followed the GearBots Example, seems to have had some success, except for the oscillation.
-Lower P constant (I and D have remained at 0). Seems to not work, it has went as low as 0.02.
-Change the isFinished() method within the command to instead of detect for onTarget() method to a custom method that implemented our old code of the lift stopping after a certain setpoint. Did not work as well.
-Changed Absolute Tolerance and even tried Percent Tolerance, these were set to 200 ticks for the former and 30% for the latter. Still oscillation.

The Code:

Subsystem
Code:
package org.usfirst.frc.team4716.robot.subsystems;

import org.usfirst.frc.team4716.robot.RobotMap;

import edu.wpi.first.wpilibj.DigitalInput;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.CounterBase.EncodingType;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.command.PIDSubsystem;

/**
 *
 */
public class PIDElevator extends PIDSubsystem {

	private DigitalInput limitSwitch;
	private Encoder elevEncoder;
	private SpeedController m1,m2;
	
    // Initialize your subsystem here
    public PIDElevator() {
    	super("PIDElevator",0.1,0.0,0.0);
    	setAbsoluteTolerance(5);
    	getPIDController().setContinuous(false);
    	
    	limitSwitch = new DigitalInput(1);
    	m1 = new Victor(4);
    	m2 = new Victor(5);
    	elevEncoder = new Encoder(RobotMap.ELEVATOR_ENCODER_PORT_1, RobotMap.ELEVATOR_ENCDER_PORT_2,
				  false, EncodingType.k4X);
        // Use these to get going:
        // setSetpoint() -  Sets where the PID controller should move the system
        //                  to
        // enable() - Enables the PID controller.
    }
    
    public void initDefaultCommand() {
        // Set the default command for a subsystem here.
        //setDefaultCommand(new MySpecialCommand());
    }
    
    protected double returnPIDInput() {
        // Return your input value for the PID loop
        // e.g. a sensor, like a potentiometer:
        // yourPot.getAverageVoltage() / kYourMaxVoltage;
    	return elevEncoder.pidGet();
    }
    
    protected void usePIDOutput(double output) {
        // Use output to drive your system, like a motor
        // e.g. yourMotor.set(output);
    	m1.set(-output);
    	m2.set(-output);
    }
    
    public boolean getLimit(){
    	return limitSwitch.get();	
    }
    
    public boolean isUp(double setpoint){
    	return (elevEncoder.get() >= setpoint) ? true:false;
    	
    }
    
    public void setMotor(double x){
    	m1.set(x);
    	m2.set(x);
    	
    }
}


Command
Code:
package org.usfirst.frc.team4716.robot.commands;

import org.usfirst.frc.team4716.robot.Robot;

import edu.wpi.first.wpilibj.command.Command;

/**
 *
 */
public class SetElevatorSetpoint extends Command {

	private double setpoint;
	
    public SetElevatorSetpoint(double setpoint) {
        // Use requires() here to declare subsystem dependencies
        // eg. requires(chassis);
    	this.setpoint = setpoint;
    	requires(Robot.pidelevator);
    }

    // Called just before this Command runs the first time
    protected void initialize() {
    	Robot.pidelevator.enable();
    	Robot.pidelevator.setSetpoint(setpoint);
    }

    // Called repeatedly when this Command is scheduled to run
    protected void execute() {
    }

    // Make this return true when this Command no longer needs to run execute()
    protected boolean isFinished() {
    	return Robot.pidelevator.onTarget();
    }

    // Called once after isFinished returns true
    protected void end() {
    	Robot.pidelevator.disable();
    }

    // Called when another command which requires one or more of the same
    // subsystems is scheduled to run
    protected void interrupted() {
    	Robot.pidelevator.disable();
    }
}

Sorry if the post is a bit lengthy, I just wanted to give as much information as possible to reduce the amount of replies to clarify information.
Reply With Quote
 


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 10:16.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi