[hal] Add a unified PCM object (#3331)

This commit is contained in:
Thad House
2021-06-05 22:36:39 -07:00
committed by GitHub
parent dea841103d
commit 0e702eb799
103 changed files with 2643 additions and 5676 deletions

View File

@@ -1,212 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.CompressorJNI;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
import edu.wpi.first.wpilibj.smartdashboard.SendableRegistry;
/**
* Class for operating a compressor connected to a PCM (Pneumatic Control Module). The PCM will
* automatically run in closed loop mode by default whenever a {@link Solenoid} object is created.
* For most cases, a Compressor object does not need to be instantiated or used in a robot program.
* This class is only required in cases where the robot program needs a more detailed status of the
* compressor or to enable/disable closed loop control.
*
* <p>Note: you cannot operate the compressor directly from this class as doing so would circumvent
* the safety provided by using the pressure switch and closed loop control. You can only turn off
* closed loop control, thereby stopping the compressor from operating.
*/
public class Compressor implements Sendable, AutoCloseable {
private int m_compressorHandle;
private byte m_module;
/**
* Makes a new instance of the compressor using the provided CAN device ID. Use this constructor
* when you have more than one PCM.
*
* @param module The PCM CAN device ID (0 - 62 inclusive)
*/
public Compressor(int module) {
m_module = (byte) module;
m_compressorHandle = CompressorJNI.initializeCompressor((byte) module);
HAL.report(tResourceType.kResourceType_Compressor, module + 1);
SendableRegistry.addLW(this, "Compressor", module);
}
/**
* Makes a new instance of the compressor using the default PCM ID of 0.
*
* <p>Additional modules can be supported by making a new instance and {@link #Compressor(int)
* specifying the CAN ID.}
*/
public Compressor() {
this(SensorUtil.getDefaultSolenoidModule());
}
@Override
public void close() {
SendableRegistry.remove(this);
}
/**
* Start the compressor running in closed loop control mode.
*
* <p>Use the method in cases where you would like to manually stop and start the compressor for
* applications such as conserving battery or making sure that the compressor motor doesn't start
* during critical operations.
*/
public void start() {
setClosedLoopControl(true);
}
/**
* Stop the compressor from running in closed loop control mode.
*
* <p>Use the method in cases where you would like to manually stop and start the compressor for
* applications such as conserving battery or making sure that the compressor motor doesn't start
* during critical operations.
*/
public void stop() {
setClosedLoopControl(false);
}
/**
* Get the status of the compressor.
*
* @return true if the compressor is on
*/
public boolean enabled() {
return CompressorJNI.getCompressor(m_compressorHandle);
}
/**
* Get the pressure switch value.
*
* @return true if the pressure is low
*/
public boolean getPressureSwitchValue() {
return CompressorJNI.getCompressorPressureSwitch(m_compressorHandle);
}
/**
* Get the current being used by the compressor.
*
* @return current consumed by the compressor in amps
*/
public double getCompressorCurrent() {
return CompressorJNI.getCompressorCurrent(m_compressorHandle);
}
/**
* Set the PCM in closed loop control mode.
*
* @param on if true sets the compressor to be in closed loop control mode (default)
*/
public void setClosedLoopControl(boolean on) {
CompressorJNI.setCompressorClosedLoopControl(m_compressorHandle, on);
}
/**
* Gets the current operating mode of the PCM.
*
* @return true if compressor is operating on closed-loop mode
*/
public boolean getClosedLoopControl() {
return CompressorJNI.getCompressorClosedLoopControl(m_compressorHandle);
}
/**
* If PCM is in fault state : Compressor Drive is disabled due to compressor current being too
* high.
*
* @return true if PCM is in fault state.
*/
public boolean getCompressorCurrentTooHighFault() {
return CompressorJNI.getCompressorCurrentTooHighFault(m_compressorHandle);
}
/**
* If PCM sticky fault is set : Compressor is disabled due to compressor current being too high.
*
* @return true if PCM sticky fault is set.
*/
public boolean getCompressorCurrentTooHighStickyFault() {
return CompressorJNI.getCompressorCurrentTooHighStickyFault(m_compressorHandle);
}
/**
* If PCM sticky fault is set : Compressor output appears to be shorted.
*
* @return true if PCM sticky fault is set.
*/
public boolean getCompressorShortedStickyFault() {
return CompressorJNI.getCompressorShortedStickyFault(m_compressorHandle);
}
/**
* If PCM is in fault state : Compressor output appears to be shorted.
*
* @return true if PCM is in fault state.
*/
public boolean getCompressorShortedFault() {
return CompressorJNI.getCompressorShortedFault(m_compressorHandle);
}
/**
* If PCM sticky fault is set : Compressor does not appear to be wired, i.e. compressor is not
* drawing enough current.
*
* @return true if PCM sticky fault is set.
*/
public boolean getCompressorNotConnectedStickyFault() {
return CompressorJNI.getCompressorNotConnectedStickyFault(m_compressorHandle);
}
/**
* If PCM is in fault state : Compressor does not appear to be wired, i.e. compressor is not
* drawing enough current.
*
* @return true if PCM is in fault state.
*/
public boolean getCompressorNotConnectedFault() {
return CompressorJNI.getCompressorNotConnectedFault(m_compressorHandle);
}
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* <p>If a sticky fault is set, then it will be persistently cleared. The compressor might
* momentarily disable while the flags are being cleared. Doo not call this method too frequently,
* otherwise normal compressor functionality may be prevented.
*
* <p>If no sticky faults are set then this call will have no effect.
*/
public void clearAllPCMStickyFaults() {
CompressorJNI.clearAllPCMStickyFaults(m_module);
}
/**
* Gets the module number (CAN ID).
*
* @return Module number
*/
public int getModule() {
return m_module;
}
@Override
public void initSendable(SendableBuilder builder) {
builder.setSmartDashboardType("Compressor");
builder.addBooleanProperty(
"Closed Loop Control", this::getClosedLoopControl, this::setClosedLoopControl);
builder.addBooleanProperty("Enabled", this::enabled, null);
builder.addBooleanProperty("Pressure switch", this::getPressureSwitchValue, null);
}
}

View File

@@ -6,10 +6,9 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.SolenoidJNI;
import edu.wpi.first.hal.util.UncleanStatusException;
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
import edu.wpi.first.wpilibj.smartdashboard.SendableRegistry;
import java.util.Objects;
/**
* DoubleSolenoid class for running 2 channels of high voltage Digital Output on the PCM.
@@ -17,7 +16,7 @@ import edu.wpi.first.wpilibj.smartdashboard.SendableRegistry;
* <p>The DoubleSolenoid class is typically used for pneumatics solenoids that have two positions
* controlled by two separate channels.
*/
public class DoubleSolenoid extends SolenoidBase implements Sendable, AutoCloseable {
public class DoubleSolenoid implements Sendable, AutoCloseable {
/** Possible values for a DoubleSolenoid. */
public enum Value {
kOff,
@@ -25,68 +24,44 @@ public class DoubleSolenoid extends SolenoidBase implements Sendable, AutoClosea
kReverse
}
private byte m_forwardMask; // The mask for the forward channel.
private byte m_reverseMask; // The mask for the reverse channel.
private int m_forwardHandle;
private int m_reverseHandle;
private final int m_forwardMask; // The mask for the forward channel.
private final int m_reverseMask; // The mask for the reverse channel.
private final int m_mask; // The channel mask
private PneumaticsBase m_module;
private final int m_forwardChannel;
private final int m_reverseChannel;
/**
* Constructor. Uses the default PCM ID (defaults to 0).
*
* @param forwardChannel The forward channel number on the PCM (0..7).
* @param reverseChannel The reverse channel number on the PCM (0..7).
*/
public DoubleSolenoid(final int forwardChannel, final int reverseChannel) {
this(SensorUtil.getDefaultSolenoidModule(), forwardChannel, reverseChannel);
}
/**
* Constructor.
*
* @param moduleNumber The module number of the solenoid module to use.
* @param module The module of the solenoid module to use.
* @param forwardChannel The forward channel on the module to control (0..7).
* @param reverseChannel The reverse channel on the module to control (0..7).
*/
public DoubleSolenoid(
final int moduleNumber, final int forwardChannel, final int reverseChannel) {
super(moduleNumber);
public DoubleSolenoid(PneumaticsBase module, final int forwardChannel, final int reverseChannel) {
m_module = Objects.requireNonNull(module, "Module cannot be null");
// TODO check channels
m_forwardChannel = forwardChannel;
m_reverseChannel = reverseChannel;
SensorUtil.checkSolenoidModule(m_moduleNumber);
SensorUtil.checkSolenoidChannel(forwardChannel);
SensorUtil.checkSolenoidChannel(reverseChannel);
m_forwardMask = 1 << forwardChannel;
m_reverseMask = 1 << reverseChannel;
m_mask = m_forwardMask | m_reverseMask;
int portHandle = HAL.getPortWithModule((byte) m_moduleNumber, (byte) forwardChannel);
m_forwardHandle = SolenoidJNI.initializeSolenoidPort(portHandle);
try {
portHandle = HAL.getPortWithModule((byte) m_moduleNumber, (byte) reverseChannel);
m_reverseHandle = SolenoidJNI.initializeSolenoidPort(portHandle);
} catch (UncleanStatusException ex) {
// free the forward handle on exception, then rethrow
SolenoidJNI.freeSolenoidPort(m_forwardHandle);
m_forwardHandle = 0;
m_reverseHandle = 0;
throw ex;
}
m_forwardMask = (byte) (1 << forwardChannel);
m_reverseMask = (byte) (1 << reverseChannel);
HAL.report(tResourceType.kResourceType_Solenoid, forwardChannel + 1, m_moduleNumber + 1);
HAL.report(tResourceType.kResourceType_Solenoid, reverseChannel + 1, m_moduleNumber + 1);
SendableRegistry.addLW(this, "DoubleSolenoid", m_moduleNumber, forwardChannel);
HAL.report(
tResourceType.kResourceType_Solenoid, forwardChannel + 1, module.getModuleNumber() + 1);
HAL.report(
tResourceType.kResourceType_Solenoid, reverseChannel + 1, module.getModuleNumber() + 1);
SendableRegistry.addLW(this, "DoubleSolenoid", module.getModuleNumber(), forwardChannel);
}
@Override
public synchronized void close() {
SendableRegistry.remove(this);
SolenoidJNI.freeSolenoidPort(m_forwardHandle);
SolenoidJNI.freeSolenoidPort(m_reverseHandle);
m_module = null;
}
/**
@@ -95,28 +70,23 @@ public class DoubleSolenoid extends SolenoidBase implements Sendable, AutoClosea
* @param value The value to set (Off, Forward, Reverse)
*/
public void set(final Value value) {
boolean forward = false;
boolean reverse = false;
int setValue;
switch (value) {
case kOff:
forward = false;
reverse = false;
setValue = 0;
break;
case kForward:
forward = true;
reverse = false;
setValue = m_forwardMask;
break;
case kReverse:
forward = false;
reverse = true;
setValue = m_reverseMask;
break;
default:
throw new AssertionError("Illegal value: " + value);
}
SolenoidJNI.setSolenoid(m_forwardHandle, forward);
SolenoidJNI.setSolenoid(m_reverseHandle, reverse);
m_module.setSolenoids(m_mask, setValue);
}
/**
@@ -125,12 +95,11 @@ public class DoubleSolenoid extends SolenoidBase implements Sendable, AutoClosea
* @return The current value of the solenoid.
*/
public Value get() {
boolean valueForward = SolenoidJNI.getSolenoid(m_forwardHandle);
boolean valueReverse = SolenoidJNI.getSolenoid(m_reverseHandle);
int values = m_module.getSolenoids();
if (valueForward) {
if ((values & m_forwardMask) != 0) {
return Value.kForward;
} else if (valueReverse) {
} else if ((values & m_reverseMask) != 0) {
return Value.kReverse;
} else {
return Value.kOff;
@@ -172,27 +141,23 @@ public class DoubleSolenoid extends SolenoidBase implements Sendable, AutoClosea
}
/**
* Check if the forward solenoid is blacklisted. If a solenoid is shorted, it is added to the
* blacklist and disabled until power cycle, or until faults are cleared.
* Check if the forward solenoid is Disabled. If a solenoid is shorted, it is added to the
* DisabledList and disabled until power cycle, or until faults are cleared.
*
* @return If solenoid is disabled due to short.
* @see #clearAllPCMStickyFaults()
*/
public boolean isFwdSolenoidBlackListed() {
int blackList = getPCMSolenoidBlackList();
return (blackList & m_forwardMask) != 0;
public boolean isFwdSolenoidDisabled() {
return (m_module.getSolenoidDisabledList() & m_forwardMask) != 0;
}
/**
* Check if the reverse solenoid is blacklisted. If a solenoid is shorted, it is added to the
* blacklist and disabled until power cycle, or until faults are cleared.
* Check if the reverse solenoid is Disabled. If a solenoid is shorted, it is added to the
* DisabledList and disabled until power cycle, or until faults are cleared.
*
* @return If solenoid is disabled due to short.
* @see #clearAllPCMStickyFaults()
*/
public boolean isRevSolenoidBlackListed() {
int blackList = getPCMSolenoidBlackList();
return (blackList & m_reverseMask) != 0;
public boolean isRevSolenoidDisabled() {
return (m_module.getSolenoidDisabledList() & m_reverseMask) != 0;
}
@Override

View File

@@ -0,0 +1,54 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
public interface PneumaticsBase extends AutoCloseable {
/**
* Sets solenoids on a pneumatics module.
*
* @param mask mask
* @param values values
*/
void setSolenoids(int mask, int values);
/**
* Gets solenoid values.
*
* @return values
*/
int getSolenoids();
/**
* Get module number for this module.
*
* @return module number
*/
int getModuleNumber();
/**
* Get the disabled solenoids.
*
* @return disabled list
*/
int getSolenoidDisabledList();
/**
* Fire a single solenoid shot.
*
* @param index solenoid index
*/
void fireOneShot(int index);
/**
* Set the duration for a single solenoid shot.
*
* @param index solenoid index
* @param durMs shot duration
*/
void setOneShotDuration(int index, int durMs);
boolean checkSolenoidChannel(int channel);
}

View File

@@ -0,0 +1,117 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.CTREPCMJNI;
public class PneumaticsControlModule implements PneumaticsBase {
private final int m_handle;
private final int m_module;
public PneumaticsControlModule() {
this(SensorUtil.getDefaultCTREPCMModule());
}
public PneumaticsControlModule(int module) {
m_handle = CTREPCMJNI.initialize(module);
m_module = module;
}
@Override
public void close() throws Exception {
CTREPCMJNI.free(m_handle);
}
public boolean getCompressor() {
return CTREPCMJNI.getCompressor(m_handle);
}
public void setClosedLoopControl(boolean enabled) {
CTREPCMJNI.setClosedLoopControl(m_handle, enabled);
}
public boolean getClosedLoopControl() {
return CTREPCMJNI.getClosedLoopControl(m_handle);
}
public boolean getPressureSwitch() {
return CTREPCMJNI.getPressureSwitch(m_handle);
}
public double getCompressorCurrent() {
return CTREPCMJNI.getCompressorCurrent(m_handle);
}
public boolean getCompressorCurrentTooHighFault() {
return CTREPCMJNI.getCompressorCurrentTooHighFault(m_handle);
}
public boolean getCompressorCurrentTooHighStickyFault() {
return CTREPCMJNI.getCompressorCurrentTooHighStickyFault(m_handle);
}
public boolean getCompressorShortedFault() {
return CTREPCMJNI.getCompressorShortedFault(m_handle);
}
public boolean getCompressorShortedStickyFault() {
return CTREPCMJNI.getCompressorShortedStickyFault(m_handle);
}
public boolean getCompressorNotConnectedFault() {
return CTREPCMJNI.getCompressorNotConnectedFault(m_handle);
}
public boolean getCompressorNotConnectedStickyFault() {
return CTREPCMJNI.getCompressorNotConnectedStickyFault(m_handle);
}
@Override
public void setSolenoids(int mask, int values) {
CTREPCMJNI.setSolenoids(m_handle, mask, values);
}
@Override
public int getSolenoids() {
return CTREPCMJNI.getSolenoids(m_handle);
}
@Override
public int getModuleNumber() {
return m_module;
}
@Override
public int getSolenoidDisabledList() {
return CTREPCMJNI.getSolenoidDisabledList(m_handle);
}
public boolean getSolenoidVoltageFault() {
return CTREPCMJNI.getSolenoidVoltageFault(m_handle);
}
public boolean getSolenoidVoltageStickyFault() {
return CTREPCMJNI.getSolenoidVoltageStickyFault(m_handle);
}
public void clearAllStickyFaults() {
CTREPCMJNI.clearAllStickyFaults(m_handle);
}
@Override
public void fireOneShot(int index) {
CTREPCMJNI.fireOneShot(m_handle, index);
}
@Override
public void setOneShotDuration(int index, int durMs) {
CTREPCMJNI.setOneShotDuration(m_handle, index, durMs);
}
@Override
public boolean checkSolenoidChannel(int channel) {
return CTREPCMJNI.checkSolenoidChannel(channel);
}
}

View File

@@ -11,7 +11,6 @@ import edu.wpi.first.hal.PDPJNI;
import edu.wpi.first.hal.PWMJNI;
import edu.wpi.first.hal.PortsJNI;
import edu.wpi.first.hal.RelayJNI;
import edu.wpi.first.hal.SolenoidJNI;
/**
* Stores most recent status information as well as containing utility functions for checking
@@ -49,22 +48,6 @@ public final class SensorUtil {
/** Number of PCM Modules. */
public static final int kPCMModules = PortsJNI.getNumPCMModules();
/**
* Verify that the solenoid module is correct.
*
* @param moduleNumber The solenoid module module number to check.
*/
public static void checkSolenoidModule(final int moduleNumber) {
if (!SolenoidJNI.checkSolenoidModule(moduleNumber)) {
StringBuilder buf = new StringBuilder();
buf.append("Requested solenoid module is out of range. Minimum: 0, Maximum: ")
.append(kPCMModules)
.append(", Requested: ")
.append(moduleNumber);
throw new IllegalArgumentException(buf.toString());
}
}
/**
* Check that the digital channel number is valid. Verify that the channel number is one of the
* legal channel numbers. Channel numbers are 0-based.
@@ -150,22 +133,6 @@ public final class SensorUtil {
}
}
/**
* Verify that the solenoid channel number is within limits. Channel numbers are 0-based.
*
* @param channel The channel number to check.
*/
public static void checkSolenoidChannel(final int channel) {
if (!SolenoidJNI.checkSolenoidChannel(channel)) {
StringBuilder buf = new StringBuilder();
buf.append("Requested solenoid channel is out of range. Minimum: 0, Maximum: ")
.append(kSolenoidChannels)
.append(", Requested: ")
.append(channel);
throw new IllegalArgumentException(buf.toString());
}
}
/**
* Verify that the power distribution channel number is within limits. Channel numbers are
* 0-based.
@@ -204,7 +171,8 @@ public final class SensorUtil {
*
* @return The number of the default solenoid module.
*/
public static int getDefaultSolenoidModule() {
@SuppressWarnings("AbbreviationAsWordInName")
public static int getDefaultCTREPCMModule() {
return 0;
}

View File

@@ -6,9 +6,9 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.SolenoidJNI;
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
import edu.wpi.first.wpilibj.smartdashboard.SendableRegistry;
import java.util.Objects;
/**
* Solenoid class for running high voltage Digital Output on the PCM.
@@ -16,44 +16,35 @@ import edu.wpi.first.wpilibj.smartdashboard.SendableRegistry;
* <p>The Solenoid class is typically used for pneumatic solenoids, but could be used for any device
* within the current spec of the PCM.
*/
public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
private final int m_channel; // The channel to control.
private int m_solenoidHandle;
/**
* Constructor using the default PCM ID (defaults to 0).
*
* @param channel The channel on the PCM to control (0..7).
*/
public Solenoid(final int channel) {
this(SensorUtil.getDefaultSolenoidModule(), channel);
}
public class Solenoid implements Sendable, AutoCloseable {
private final int m_mask; // The channel mask
private final int m_channel;
private PneumaticsBase m_module;
/**
* Constructor.
*
* @param moduleNumber The CAN ID of the PCM the solenoid is attached to.
* @param module The PCM the solenoid is attached to.
* @param channel The channel on the PCM to control (0..7).
*/
public Solenoid(final int moduleNumber, final int channel) {
super(moduleNumber);
public Solenoid(PneumaticsBase module, final int channel) {
m_module = Objects.requireNonNull(module, "Module cannot be null");
if (!module.checkSolenoidChannel(channel)) {
throw new IllegalArgumentException(); // TODO fix me
}
m_mask = 1 << channel;
m_channel = channel;
SensorUtil.checkSolenoidModule(m_moduleNumber);
SensorUtil.checkSolenoidChannel(m_channel);
int portHandle = HAL.getPortWithModule((byte) m_moduleNumber, (byte) m_channel);
m_solenoidHandle = SolenoidJNI.initializeSolenoidPort(portHandle);
HAL.report(tResourceType.kResourceType_Solenoid, m_channel + 1, m_moduleNumber + 1);
SendableRegistry.addLW(this, "Solenoid", m_moduleNumber, m_channel);
HAL.report(tResourceType.kResourceType_Solenoid, channel + 1, module.getModuleNumber() + 1);
SendableRegistry.addLW(this, "Solenoid", module.getModuleNumber(), channel);
}
@Override
public void close() {
SendableRegistry.remove(this);
SolenoidJNI.freeSolenoidPort(m_solenoidHandle);
m_solenoidHandle = 0;
m_module = null;
}
/**
@@ -62,7 +53,8 @@ public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
* @param on True will turn the solenoid output on. False will turn the solenoid output off.
*/
public void set(boolean on) {
SolenoidJNI.setSolenoid(m_solenoidHandle, on);
int value = on ? (0xFFFF & m_mask) : 0;
m_module.setSolenoids(m_mask, value);
}
/**
@@ -71,7 +63,8 @@ public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
* @return True if the solenoid output is on or false if the solenoid output is off.
*/
public boolean get() {
return SolenoidJNI.getSolenoid(m_solenoidHandle);
int currentAll = m_module.getSolenoids();
return (currentAll & m_mask) != 0;
}
/**
@@ -90,15 +83,13 @@ public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
}
/**
* Check if solenoid is blacklisted. If a solenoid is shorted, it is added to the blacklist and
* disabled until power cycle, or until faults are cleared.
* Check if solenoid is DisabledListed. If a solenoid is shorted, it is added to the Disabled List
* and disabled until power cycle, or until faults are cleared.
*
* @return If solenoid is disabled due to short.
* @see #clearAllPCMStickyFaults()
*/
public boolean isBlackListed() {
int value = getPCMSolenoidBlackList() & (1 << m_channel);
return value != 0;
public boolean isDisabled() {
return (m_module.getSolenoidDisabledList() & m_mask) != 0;
}
/**
@@ -111,7 +102,7 @@ public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
*/
public void setPulseDuration(double durationSeconds) {
long durationMS = (long) (durationSeconds * 1000);
SolenoidJNI.setOneShotDuration(m_solenoidHandle, durationMS);
m_module.setOneShotDuration(m_channel, (int) durationMS);
}
/**
@@ -120,7 +111,7 @@ public class Solenoid extends SolenoidBase implements Sendable, AutoCloseable {
* @see #setPulseDuration(double)
*/
public void startPulse() {
SolenoidJNI.fireOneShot(m_solenoidHandle);
m_module.fireOneShot(m_channel);
}
@Override

View File

@@ -1,147 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.SolenoidJNI;
/**
* SolenoidBase class is the common base class for the {@link Solenoid} and {@link DoubleSolenoid}
* classes.
*/
public class SolenoidBase {
protected final int m_moduleNumber; // The number of the solenoid module being used.
/**
* Constructor.
*
* @param moduleNumber The PCM CAN ID
*/
protected SolenoidBase(final int moduleNumber) {
m_moduleNumber = moduleNumber;
}
/**
* Get the CAN ID of the module this solenoid is connected to.
*
* @return the module number.
*/
public int getModuleNumber() {
return m_moduleNumber;
}
/**
* Read all 8 solenoids from the specified module as a single byte.
*
* @param moduleNumber the module number to read
* @return The current value of all 8 solenoids on the module.
*/
public static int getAll(int moduleNumber) {
return SolenoidJNI.getAllSolenoids(moduleNumber);
}
/**
* Read all 8 solenoids from the module used by this solenoid as a single byte.
*
* @return The current value of all 8 solenoids on this module.
*/
public int getAll() {
return SolenoidBase.getAll(m_moduleNumber);
}
/**
* Reads complete solenoid blacklist for all 8 solenoids as a single byte. If a solenoid is
* shorted, it is added to the blacklist and disabled until power cycle, or until faults are
* cleared.
*
* @param moduleNumber the module number to read
* @return The solenoid blacklist of all 8 solenoids on the module.
* @see #clearAllPCMStickyFaults()
*/
public static int getPCMSolenoidBlackList(int moduleNumber) {
return SolenoidJNI.getPCMSolenoidBlackList(moduleNumber);
}
/**
* Reads complete solenoid blacklist for all 8 solenoids as a single byte. If a solenoid is
* shorted, it is added to the blacklist and disabled until power cycle, or until faults are
* cleared.
*
* @return The solenoid blacklist of all 8 solenoids on the module.
* @see #clearAllPCMStickyFaults()
*/
public int getPCMSolenoidBlackList() {
return SolenoidBase.getPCMSolenoidBlackList(m_moduleNumber);
}
/**
* If true, the common highside solenoid voltage rail is too low, most likely a solenoid channel
* is shorted.
*
* @param moduleNumber the module number to read
* @return true if PCM sticky fault is set
*/
public static boolean getPCMSolenoidVoltageStickyFault(int moduleNumber) {
return SolenoidJNI.getPCMSolenoidVoltageStickyFault(moduleNumber);
}
/**
* If true, the common highside solenoid voltage rail is too low, most likely a solenoid channel
* is shorted.
*
* @return true if PCM sticky fault is set
*/
public boolean getPCMSolenoidVoltageStickyFault() {
return SolenoidBase.getPCMSolenoidVoltageStickyFault(m_moduleNumber);
}
/**
* The common highside solenoid voltage rail is too low, most likely a solenoid channel is
* shorted.
*
* @param moduleNumber the module number to read
* @return true if PCM is in fault state.
*/
public static boolean getPCMSolenoidVoltageFault(int moduleNumber) {
return SolenoidJNI.getPCMSolenoidVoltageFault(moduleNumber);
}
/**
* The common highside solenoid voltage rail is too low, most likely a solenoid channel is
* shorted.
*
* @return true if PCM is in fault state.
*/
public boolean getPCMSolenoidVoltageFault() {
return SolenoidBase.getPCMSolenoidVoltageFault(m_moduleNumber);
}
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* <p>If a sticky fault is set, then it will be persistently cleared. Compressor drive maybe
* momentarily disable while flags are being cleared. Care should be taken to not call this too
* frequently, otherwise normal compressor functionality may be prevented.
*
* <p>If no sticky faults are set then this call will have no effect.
*
* @param moduleNumber the module number to read
*/
public static void clearAllPCMStickyFaults(int moduleNumber) {
SolenoidJNI.clearAllPCMStickyFaults(moduleNumber);
}
/**
* Clear ALL sticky faults inside PCM that Compressor is wired to.
*
* <p>If a sticky fault is set, then it will be persistently cleared. Compressor drive maybe
* momentarily disable while flags are being cleared. Care should be taken to not call this too
* frequently, otherwise normal compressor functionality may be prevented.
*
* <p>If no sticky faults are set then this call will have no effect.
*/
public void clearAllPCMStickyFaults() {
SolenoidBase.clearAllPCMStickyFaults(m_moduleNumber);
}
}

View File

@@ -4,18 +4,19 @@
package edu.wpi.first.wpilibj.simulation;
import edu.wpi.first.hal.simulation.CTREPCMDataJNI;
import edu.wpi.first.hal.simulation.NotifyCallback;
import edu.wpi.first.hal.simulation.PCMDataJNI;
import edu.wpi.first.wpilibj.Compressor;
import edu.wpi.first.wpilibj.PneumaticsBase;
import edu.wpi.first.wpilibj.SensorUtil;
/** Class to control a simulated Pneumatic Control Module (PCM). */
public class PCMSim {
@SuppressWarnings("AbbreviationAsWordInName")
public class CTREPCMSim {
private final int m_index;
/** Constructs for the default PCM. */
public PCMSim() {
m_index = SensorUtil.getDefaultSolenoidModule();
public CTREPCMSim() {
m_index = SensorUtil.getDefaultCTREPCMModule();
}
/**
@@ -23,53 +24,17 @@ public class PCMSim {
*
* @param module module number
*/
public PCMSim(int module) {
public CTREPCMSim(int module) {
m_index = module;
}
/**
* Constructs from a Compressor object.
*
* @param compressor Compressor connected to PCM to simulate
* @param module PCM module to simulate
*/
public PCMSim(Compressor compressor) {
m_index = compressor.getModule();
}
/**
* Register a callback to be run when a solenoid is initialized on a channel.
*
* @param channel the channel to monitor
* @param callback the callback
* @param initialNotify should the callback be run with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerSolenoidInitializedCallback(
int channel, NotifyCallback callback, boolean initialNotify) {
int uid =
PCMDataJNI.registerSolenoidInitializedCallback(m_index, channel, callback, initialNotify);
return new CallbackStore(m_index, channel, uid, PCMDataJNI::cancelSolenoidInitializedCallback);
}
/**
* Check if a solenoid has been initialized on a specific channel.
*
* @param channel the channel to check
* @return true if initialized
*/
public boolean getSolenoidInitialized(int channel) {
return PCMDataJNI.getSolenoidInitialized(m_index, channel);
}
/**
* Define whether a solenoid has been initialized on a specific channel.
*
* @param channel the channel
* @param solenoidInitialized is there a solenoid initialized on that channel
*/
public void setSolenoidInitialized(int channel, boolean solenoidInitialized) {
PCMDataJNI.setSolenoidInitialized(m_index, channel, solenoidInitialized);
public CTREPCMSim(PneumaticsBase module) {
m_index = module.getModuleNumber();
}
/**
@@ -83,8 +48,9 @@ public class PCMSim {
*/
public CallbackStore registerSolenoidOutputCallback(
int channel, NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerSolenoidOutputCallback(m_index, channel, callback, initialNotify);
return new CallbackStore(m_index, channel, uid, PCMDataJNI::cancelSolenoidOutputCallback);
int uid =
CTREPCMDataJNI.registerSolenoidOutputCallback(m_index, channel, callback, initialNotify);
return new CallbackStore(m_index, channel, uid, CTREPCMDataJNI::cancelSolenoidOutputCallback);
}
/**
@@ -94,7 +60,7 @@ public class PCMSim {
* @return the solenoid output
*/
public boolean getSolenoidOutput(int channel) {
return PCMDataJNI.getSolenoidOutput(m_index, channel);
return CTREPCMDataJNI.getSolenoidOutput(m_index, channel);
}
/**
@@ -104,7 +70,7 @@ public class PCMSim {
* @param solenoidOutput the new solenoid output
*/
public void setSolenoidOutput(int channel, boolean solenoidOutput) {
PCMDataJNI.setSolenoidOutput(m_index, channel, solenoidOutput);
CTREPCMDataJNI.setSolenoidOutput(m_index, channel, solenoidOutput);
}
/**
@@ -115,10 +81,9 @@ public class PCMSim {
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerCompressorInitializedCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerCompressorInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, PCMDataJNI::cancelCompressorInitializedCallback);
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
int uid = CTREPCMDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, CTREPCMDataJNI::cancelInitializedCallback);
}
/**
@@ -126,17 +91,17 @@ public class PCMSim {
*
* @return true if initialized
*/
public boolean getCompressorInitialized() {
return PCMDataJNI.getCompressorInitialized(m_index);
public boolean getInitialized() {
return CTREPCMDataJNI.getInitialized(m_index);
}
/**
* Define whether the compressor has been initialized.
*
* @param compressorInitialized whether the compressor is initialized
* @param initialized whether the compressor is initialized
*/
public void setCompressorInitialized(boolean compressorInitialized) {
PCMDataJNI.setCompressorInitialized(m_index, compressorInitialized);
public void setInitialized(boolean initialized) {
CTREPCMDataJNI.setInitialized(m_index, initialized);
}
/**
@@ -149,8 +114,8 @@ public class PCMSim {
*/
public CallbackStore registerCompressorOnCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerCompressorOnCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, PCMDataJNI::cancelCompressorOnCallback);
int uid = CTREPCMDataJNI.registerCompressorOnCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, CTREPCMDataJNI::cancelCompressorOnCallback);
}
/**
@@ -159,7 +124,7 @@ public class PCMSim {
* @return true if the compressor is active
*/
public boolean getCompressorOn() {
return PCMDataJNI.getCompressorOn(m_index);
return CTREPCMDataJNI.getCompressorOn(m_index);
}
/**
@@ -168,7 +133,7 @@ public class PCMSim {
* @param compressorOn the new value
*/
public void setCompressorOn(boolean compressorOn) {
PCMDataJNI.setCompressorOn(m_index, compressorOn);
CTREPCMDataJNI.setCompressorOn(m_index, compressorOn);
}
/**
@@ -181,8 +146,8 @@ public class PCMSim {
*/
public CallbackStore registerClosedLoopEnabledCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerClosedLoopEnabledCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, PCMDataJNI::cancelClosedLoopEnabledCallback);
int uid = CTREPCMDataJNI.registerClosedLoopEnabledCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, CTREPCMDataJNI::cancelClosedLoopEnabledCallback);
}
/**
@@ -191,7 +156,7 @@ public class PCMSim {
* @return true if active
*/
public boolean getClosedLoopEnabled() {
return PCMDataJNI.getClosedLoopEnabled(m_index);
return CTREPCMDataJNI.getClosedLoopEnabled(m_index);
}
/**
@@ -200,7 +165,7 @@ public class PCMSim {
* @param closedLoopEnabled whether the control loop is active
*/
public void setClosedLoopEnabled(boolean closedLoopEnabled) {
PCMDataJNI.setClosedLoopEnabled(m_index, closedLoopEnabled);
CTREPCMDataJNI.setClosedLoopEnabled(m_index, closedLoopEnabled);
}
/**
@@ -213,8 +178,8 @@ public class PCMSim {
*/
public CallbackStore registerPressureSwitchCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerPressureSwitchCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, PCMDataJNI::cancelPressureSwitchCallback);
int uid = CTREPCMDataJNI.registerPressureSwitchCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, CTREPCMDataJNI::cancelPressureSwitchCallback);
}
/**
@@ -223,7 +188,7 @@ public class PCMSim {
* @return the pressure switch value
*/
public boolean getPressureSwitch() {
return PCMDataJNI.getPressureSwitch(m_index);
return CTREPCMDataJNI.getPressureSwitch(m_index);
}
/**
@@ -232,7 +197,7 @@ public class PCMSim {
* @param pressureSwitch the new value
*/
public void setPressureSwitch(boolean pressureSwitch) {
PCMDataJNI.setPressureSwitch(m_index, pressureSwitch);
CTREPCMDataJNI.setPressureSwitch(m_index, pressureSwitch);
}
/**
@@ -245,8 +210,8 @@ public class PCMSim {
*/
public CallbackStore registerCompressorCurrentCallback(
NotifyCallback callback, boolean initialNotify) {
int uid = PCMDataJNI.registerCompressorCurrentCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, PCMDataJNI::cancelCompressorCurrentCallback);
int uid = CTREPCMDataJNI.registerCompressorCurrentCallback(m_index, callback, initialNotify);
return new CallbackStore(m_index, uid, CTREPCMDataJNI::cancelCompressorCurrentCallback);
}
/**
@@ -255,7 +220,7 @@ public class PCMSim {
* @return the current of the compressor connected to this module
*/
public double getCompressorCurrent() {
return PCMDataJNI.getCompressorCurrent(m_index);
return CTREPCMDataJNI.getCompressorCurrent(m_index);
}
/**
@@ -264,11 +229,11 @@ public class PCMSim {
* @param compressorCurrent the new compressor current
*/
public void setCompressorCurrent(double compressorCurrent) {
PCMDataJNI.setCompressorCurrent(m_index, compressorCurrent);
CTREPCMDataJNI.setCompressorCurrent(m_index, compressorCurrent);
}
/** Reset all simulation data for this object. */
public void resetData() {
PCMDataJNI.resetData(m_index);
CTREPCMDataJNI.resetData(m_index);
}
}

View File

@@ -1,182 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj.simulation;
import edu.wpi.first.hal.simulation.NotifyCallback;
import edu.wpi.first.wpilibj.DoubleSolenoid;
/** Class to control a simulated {@link edu.wpi.first.wpilibj.DoubleSolenoid}. */
public class DoubleSolenoidSim {
private final PCMSim m_pcm;
private final int m_fwd;
private final int m_rev;
/**
* Constructs for a double solenoid on the default PCM.
*
* @param fwd the forward solenoid channel.
* @param rev the reverse solenoid channel.
* @see PCMSim#PCMSim()
*/
public DoubleSolenoidSim(int fwd, int rev) {
this.m_pcm = new PCMSim();
this.m_fwd = fwd;
this.m_rev = rev;
}
/**
* Constructs for a double solenoid.
*
* @param fwd the forward solenoid channel.
* @param rev the reverse solenoid channel.
* @see PCMSim#PCMSim(int)
*/
public DoubleSolenoidSim(int module, int fwd, int rev) {
this(new PCMSim(module), fwd, rev);
}
/**
* Constructs for a double solenoid on the given PCM.
*
* @param pcm the PCM the double solenoid is on.
* @param fwd the forward solenoid channel.
* @param rev the reverse solenoid channel.
*/
public DoubleSolenoidSim(PCMSim pcm, int fwd, int rev) {
this.m_pcm = pcm;
this.m_fwd = fwd;
this.m_rev = rev;
}
/**
* Constructs for the given solenoid.
*
* @param solenoid the solenoid to simulate.
*/
public DoubleSolenoidSim(DoubleSolenoid solenoid) {
this(solenoid.getModuleNumber(), solenoid.getFwdChannel(), solenoid.getRevChannel());
}
/**
* Register a callback to be run when the forward solenoid is initialized.
*
* @param callback the callback
* @param initialNotify should the callback be run with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerFwdInitializedCallback(
NotifyCallback callback, boolean initialNotify) {
return m_pcm.registerSolenoidInitializedCallback(m_fwd, callback, initialNotify);
}
/**
* Check if the forward solenoid has been initialized.
*
* @return true if initialized
*/
public boolean getFwdInitialized() {
return m_pcm.getSolenoidInitialized(m_fwd);
}
/**
* Define whether the forward solenoid has been initialized.
*
* @param initialized whether the solenoid is intiialized.
*/
public void setFwdInitialized(boolean initialized) {
m_pcm.setSolenoidInitialized(m_fwd, initialized);
}
/**
* Register a callback to be run when the reverse solenoid is initialized.
*
* @param callback the callback
* @param initialNotify should the callback be run with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerRevInitializedCallback(
NotifyCallback callback, boolean initialNotify) {
return m_pcm.registerSolenoidInitializedCallback(m_rev, callback, initialNotify);
}
/**
* Check if the reverse solenoid has been initialized.
*
* @return true if initialized
*/
public boolean getRevInitialized() {
return m_pcm.getSolenoidInitialized(m_rev);
}
/**
* Define whether the reverse solenoid has been initialized.
*
* @param initialized whether the solenoid is intiialized.
*/
public void setRevInitialized(boolean initialized) {
m_pcm.setSolenoidInitialized(m_rev, initialized);
}
/**
* Set the value of the double solenoid output.
*
* @param value The value to set (Off, Forward, Reverse)
*/
public void set(final DoubleSolenoid.Value value) {
boolean forward = false;
boolean reverse = false;
switch (value) {
case kOff:
forward = false;
reverse = false;
break;
case kForward:
forward = true;
reverse = false;
break;
case kReverse:
forward = false;
reverse = true;
break;
default:
throw new AssertionError("Illegal value: " + value);
}
m_pcm.setSolenoidOutput(m_fwd, forward);
m_pcm.setSolenoidOutput(m_rev, reverse);
}
/**
* Check the value of the double solenoid output.
*
* @return the output value of the double solenoid.
*/
public DoubleSolenoid.Value get() {
boolean fwdState = m_pcm.getSolenoidOutput(m_fwd);
boolean revState = m_pcm.getSolenoidOutput(m_rev);
if (!fwdState && !revState) {
return DoubleSolenoid.Value.kOff;
} else if (fwdState && !revState) {
return DoubleSolenoid.Value.kForward;
} else if (!fwdState && revState) {
return DoubleSolenoid.Value.kReverse;
} else {
throw new AssertionError(
"In a double solenoid, both fwd and rev can't be on at the same time.");
}
}
/**
* Get the wrapped {@link PCMSim} object.
*
* @return the wrapped {@link PCMSim} object.
*/
public PCMSim getPCMSim() {
return m_pcm;
}
}

View File

@@ -1,125 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj.simulation;
import edu.wpi.first.hal.simulation.NotifyCallback;
import edu.wpi.first.wpilibj.Solenoid;
/** Class to control a simulated {@link edu.wpi.first.wpilibj.Solenoid}. */
public class SolenoidSim {
private final PCMSim m_pcm;
private final int m_channel;
/**
* Constructs for a solenoid on the default PCM.
*
* @param channel the solenoid channel.
* @see PCMSim#PCMSim()
*/
public SolenoidSim(int channel) {
this.m_pcm = new PCMSim();
this.m_channel = channel;
}
/**
* Constructs for a solenoid.
*
* @param module the CAN ID of the PCM the solenoid is connected to.
* @param channel the solenoid channel.
* @see PCMSim#PCMSim(int)
*/
public SolenoidSim(int module, int channel) {
this(new PCMSim(module), channel);
}
/**
* Constructs for a solenoid on the given PCM.
*
* @param pcm the PCM the solenoid is connected to.
* @param channel the solenoid channel.
*/
public SolenoidSim(PCMSim pcm, int channel) {
this.m_pcm = pcm;
this.m_channel = channel;
}
/**
* Constructs for the given solenoid.
*
* @param solenoid the solenoid to simulate.
*/
public SolenoidSim(Solenoid solenoid) {
this(solenoid.getModuleNumber(), solenoid.getChannel());
}
/**
* Register a callback to be run when this solenoid is initialized.
*
* @param callback the callback
* @param initialNotify should the callback be run with the initial state
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
return m_pcm.registerSolenoidInitializedCallback(m_channel, callback, initialNotify);
}
/**
* Check if this solenoid has been initialized.
*
* @return true if initialized
*/
public boolean getInitialized() {
return m_pcm.getSolenoidInitialized(m_channel);
}
/**
* Define whether this solenoid has been initialized.
*
* @param initialized whether the solenoid is intiialized.
*/
public void setInitialized(boolean initialized) {
m_pcm.setSolenoidInitialized(m_channel, initialized);
}
/**
* Register a callback to be run when the output of this solenoid has changed.
*
* @param callback the callback
* @param initialNotify should the callback be run with the initial value
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
* this object so GC doesn't cancel the callback.
*/
public CallbackStore registerOutputCallback(NotifyCallback callback, boolean initialNotify) {
return m_pcm.registerSolenoidOutputCallback(m_channel, callback, initialNotify);
}
/**
* Check the solenoid output.
*
* @return the solenoid output
*/
public boolean getOutput() {
return m_pcm.getSolenoidOutput(m_channel);
}
/**
* Change the solenoid output.
*
* @param output the new solenoid output
*/
public void setOutput(boolean output) {
m_pcm.setSolenoidOutput(m_channel, output);
}
/**
* Get the wrapped {@link PCMSim} object.
*
* @return the wrapped {@link PCMSim} object.
*/
public PCMSim getPCMSim() {
return m_pcm;
}
}