예제 #1
0
def config_spark(spark: CANSparkMax, motor_config: SparkMotorConfig):
    spark.restoreFactoryDefaults()
    spark.enableVoltageCompensation(motor_config.voltage_compensation)
    spark.setSmartCurrentLimit(motor_config.stall_limit)
    spark.setIdleMode(motor_config.default_mode)
    spark.setOpenLoopRampRate(motor_config.ramp_rate)
    spark.setClosedLoopRampRate(motor_config.ramp_rate)
    spark.setInverted(motor_config.reversed)
예제 #2
0
class PIDSparkMax:
    """
    Wrapper for a Rev Spark MAX that exposes all the 
    PID setup and makes it easy to set a PID setpoint.
    """

    kP = 0.035  # 6e-2
    kI = 0.01  # 1e-3
    kD = 0.001  # 0.2
    kIz = 0.001
    kFF = 0.000015
    kMinOutput = -1
    kMaxOutput = 1
    control_mode = ControlType.kVelocity

    def __init__(self, canid):
        self.motor = CANSparkMax(canid, MotorType.kBrushless)
        self.motor.restoreFactoryDefaults()
        self.motor.setClosedLoopRampRate(1)
        self._motor_pid = self.motor.getPIDController()
        self._motor_pid.setP(self.kP)
        self._motor_pid.setI(self.kI)
        self._motor_pid.setD(self.kD)
        self._motor_pid.setIZone(self.kIz)
        self._motor_pid.setFF(self.kFF)
        self._motor_pid.setOutputRange(self.kMinOutput, self.kMaxOutput)
        self.motor.setSmartCurrentLimit(10)

    def setP(self, value):
        self.kP = value
        self._motor_pid.setP(value)

    def setI(self, value):
        self.kI = value
        self._motor_pid.setI(value)

    def setD(self, value):
        self.kD = value
        self._motor_pid.setD(value)

    def setIz(self, value):
        self.kIz = value
        self._motor_pid.setIZone(value)

    def setFF(self, value):
        self.kFF = value
        self._motor_pid.setFF(value)

    def setMOutputRange(self, min, max):
        self.kMinOutput = min
        self.kMaxOutput = max
        self._motor_pid.setOutputRange(value)

    def getEncoder(self):
        return self.motor.getEncoder()

    def stop(self):
        self.motor.stopMotor()

    def set(self, setpoint):
        self._motor_pid.setReference(setpoint, self.control_mode)

    def setPID(self, kP, kI, kD):
        self.setP(kP)
        self.setI(kI)
        self.setD(kD)

    def fromKu(self, Ku: float, Tu: float) -> None:
        """
        Use the Zeigler-Nichols method to tune the PID based off the oscillations.
        Uses a P value for oscillation along with the period of the oscullations to find the PID values.

        Args:
            Ku: This is the value of P that you obtain by increasing P slowly until the system starts to oscillate
            Tu: This is the period of the oscillation, with one full stroke
        """
        self.setP(0.6 * Ku)
        self.setI(1.2 * Ku / Tu)
        self.setD(3 * Ku * Tu / 40)

    @property
    def rpm(self):
        return self.motor.getEncoder().getVelocity()