001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj.motorcontrol; 006 007import edu.wpi.first.util.sendable.Sendable; 008import edu.wpi.first.util.sendable.SendableBuilder; 009import edu.wpi.first.util.sendable.SendableRegistry; 010import edu.wpi.first.wpilibj.MotorSafety; 011import edu.wpi.first.wpilibj.PWM; 012 013/** Common base class for all PWM Motor Controllers. */ 014public abstract class PWMMotorController extends MotorSafety 015 implements MotorController, Sendable, AutoCloseable { 016 private boolean m_isInverted; 017 protected PWM m_pwm; 018 019 /** 020 * Constructor. 021 * 022 * @param name Name to use for SendableRegistry 023 * @param channel The PWM channel that the controller is attached to. 0-9 are on-board, 10-19 are 024 * on the MXP port 025 */ 026 protected PWMMotorController(final String name, final int channel) { 027 m_pwm = new PWM(channel, false); 028 SendableRegistry.addLW(this, name, channel); 029 } 030 031 /** Free the resource associated with the PWM channel and set the value to 0. */ 032 @Override 033 public void close() { 034 SendableRegistry.remove(this); 035 m_pwm.close(); 036 } 037 038 /** 039 * Set the PWM value. 040 * 041 * <p>The PWM value is set using a range of -1.0 to 1.0, appropriately scaling the value for the 042 * FPGA. 043 * 044 * @param speed The speed value between -1.0 and 1.0 to set. 045 */ 046 @Override 047 public void set(double speed) { 048 m_pwm.setSpeed(m_isInverted ? -speed : speed); 049 feed(); 050 } 051 052 /** 053 * Get the recently set value of the PWM. This value is affected by the inversion property. If you 054 * want the value that is sent directly to the MotorController, use {@link 055 * edu.wpi.first.wpilibj.PWM#getSpeed()} instead. 056 * 057 * @return The most recently set value for the PWM between -1.0 and 1.0. 058 */ 059 @Override 060 public double get() { 061 return m_pwm.getSpeed() * (m_isInverted ? -1.0 : 1.0); 062 } 063 064 @Override 065 public void setInverted(boolean isInverted) { 066 m_isInverted = isInverted; 067 } 068 069 @Override 070 public boolean getInverted() { 071 return m_isInverted; 072 } 073 074 @Override 075 public void disable() { 076 m_pwm.setDisabled(); 077 } 078 079 @Override 080 public void stopMotor() { 081 disable(); 082 } 083 084 @Override 085 public String getDescription() { 086 return "PWM " + getChannel(); 087 } 088 089 /** 090 * Gets the backing PWM handle. 091 * 092 * @return The pwm handle. 093 */ 094 public int getPwmHandle() { 095 return m_pwm.getHandle(); 096 } 097 098 /** 099 * Gets the PWM channel number. 100 * 101 * @return The channel number. 102 */ 103 public int getChannel() { 104 return m_pwm.getChannel(); 105 } 106 107 /** 108 * Optionally eliminate the deadband from a motor controller. 109 * 110 * @param eliminateDeadband If true, set the motor curve for the motor controller to eliminate the 111 * deadband in the middle of the range. Otherwise, keep the full range without modifying any 112 * values. 113 */ 114 public void enableDeadbandElimination(boolean eliminateDeadband) { 115 m_pwm.enableDeadbandElimination(eliminateDeadband); 116 } 117 118 @Override 119 public void initSendable(SendableBuilder builder) { 120 builder.setSmartDashboardType("Motor Controller"); 121 builder.setActuator(true); 122 builder.setSafeState(this::disable); 123 builder.addDoubleProperty("Value", this::get, this::set); 124 } 125}