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; 006 007import edu.wpi.first.hal.FRCNetComm.tResourceType; 008import edu.wpi.first.hal.HAL; 009import edu.wpi.first.hal.PowerDistributionFaults; 010import edu.wpi.first.hal.PowerDistributionJNI; 011import edu.wpi.first.hal.PowerDistributionStickyFaults; 012import edu.wpi.first.hal.PowerDistributionVersion; 013import edu.wpi.first.util.sendable.Sendable; 014import edu.wpi.first.util.sendable.SendableBuilder; 015import edu.wpi.first.util.sendable.SendableRegistry; 016 017/** 018 * Class for getting voltage, current, temperature, power and energy from the CTRE Power 019 * Distribution Panel (PDP) or REV Power Distribution Hub (PDH) over CAN. 020 */ 021public class PowerDistribution implements Sendable, AutoCloseable { 022 private final int m_handle; 023 private final int m_module; 024 025 /** Default module number. */ 026 public static final int kDefaultModule = PowerDistributionJNI.DEFAULT_MODULE; 027 028 /** Power distribution module type. */ 029 public enum ModuleType { 030 /** CTRE (Cross The Road Electronics) CTRE Power Distribution Panel (PDP). */ 031 kCTRE(PowerDistributionJNI.CTRE_TYPE), 032 /** REV Power Distribution Hub (PDH). */ 033 kRev(PowerDistributionJNI.REV_TYPE); 034 035 /** ModuleType value. */ 036 public final int value; 037 038 ModuleType(int value) { 039 this.value = value; 040 } 041 } 042 043 /** 044 * Constructs a PowerDistribution object. 045 * 046 * @param module The CAN ID of the PDP/PDH. 047 * @param moduleType Module type (CTRE or REV). 048 */ 049 @SuppressWarnings("this-escape") 050 public PowerDistribution(int module, ModuleType moduleType) { 051 m_handle = PowerDistributionJNI.initialize(module, moduleType.value); 052 m_module = PowerDistributionJNI.getModuleNumber(m_handle); 053 054 HAL.report(tResourceType.kResourceType_PDP, m_module + 1); 055 SendableRegistry.addLW(this, "PowerDistribution", m_module); 056 } 057 058 /** 059 * Constructs a PowerDistribution object. 060 * 061 * <p>Detects the connected PDP/PDH using the default CAN ID (0 for CTRE and 1 for REV). 062 */ 063 @SuppressWarnings("this-escape") 064 public PowerDistribution() { 065 m_handle = PowerDistributionJNI.initialize(kDefaultModule, PowerDistributionJNI.AUTOMATIC_TYPE); 066 m_module = PowerDistributionJNI.getModuleNumber(m_handle); 067 068 HAL.report(tResourceType.kResourceType_PDP, m_module + 1); 069 SendableRegistry.addLW(this, "PowerDistribution", m_module); 070 } 071 072 @Override 073 public void close() { 074 SendableRegistry.remove(this); 075 } 076 077 /** 078 * Gets the number of channels for this power distribution object. 079 * 080 * @return Number of output channels (16 for PDP, 24 for PDH). 081 */ 082 public int getNumChannels() { 083 return PowerDistributionJNI.getNumChannels(m_handle); 084 } 085 086 /** 087 * Query the input voltage of the PDP/PDH. 088 * 089 * @return The voltage in volts 090 */ 091 public double getVoltage() { 092 return PowerDistributionJNI.getVoltage(m_handle); 093 } 094 095 /** 096 * Query the temperature of the PDP. 097 * 098 * <p>Not supported on the Rev PDH and returns 0. 099 * 100 * @return The temperature in degrees Celsius 101 */ 102 public double getTemperature() { 103 return PowerDistributionJNI.getTemperature(m_handle); 104 } 105 106 /** 107 * Query the current of a single channel of the PDP/PDH. 108 * 109 * @param channel The channel (0-15 for PDP, 0-23 for PDH) to query 110 * @return The current of the channel in Amperes 111 */ 112 public double getCurrent(int channel) { 113 return PowerDistributionJNI.getChannelCurrent(m_handle, channel); 114 } 115 116 /** 117 * Query the current of all monitored channels. 118 * 119 * @return The current of all the channels in Amperes 120 */ 121 public double getTotalCurrent() { 122 return PowerDistributionJNI.getTotalCurrent(m_handle); 123 } 124 125 /** 126 * Query the total power drawn from the monitored channels of the PDP. 127 * 128 * <p>Not supported on the Rev PDH and returns 0. 129 * 130 * @return the total power in Watts 131 */ 132 public double getTotalPower() { 133 return PowerDistributionJNI.getTotalPower(m_handle); 134 } 135 136 /** 137 * Query the total energy drawn from the monitored channels of the PDP. 138 * 139 * <p>Not supported on the Rev PDH and returns 0. 140 * 141 * @return the total energy in Joules 142 */ 143 public double getTotalEnergy() { 144 return PowerDistributionJNI.getTotalEnergy(m_handle); 145 } 146 147 /** 148 * Reset the total energy to 0 of the PDP. 149 * 150 * <p>Not supported on the Rev PDH and does nothing. 151 */ 152 public void resetTotalEnergy() { 153 PowerDistributionJNI.resetTotalEnergy(m_handle); 154 } 155 156 /** Clear all PDP/PDH sticky faults. */ 157 public void clearStickyFaults() { 158 PowerDistributionJNI.clearStickyFaults(m_handle); 159 } 160 161 /** 162 * Gets module number (CAN ID). 163 * 164 * @return The module number (CAN ID). 165 */ 166 public int getModule() { 167 return m_module; 168 } 169 170 /** 171 * Gets the module type for this power distribution object. 172 * 173 * @return The module type 174 */ 175 public ModuleType getType() { 176 int type = PowerDistributionJNI.getType(m_handle); 177 if (type == PowerDistributionJNI.REV_TYPE) { 178 return ModuleType.kRev; 179 } else { 180 return ModuleType.kCTRE; 181 } 182 } 183 184 /** 185 * Gets whether the PDH switchable channel is turned on or off. Returns false with the CTRE PDP. 186 * 187 * @return The output state of the PDH switchable channel 188 */ 189 public boolean getSwitchableChannel() { 190 return PowerDistributionJNI.getSwitchableChannel(m_handle); 191 } 192 193 /** 194 * Sets the PDH switchable channel on or off. Does nothing with the CTRE PDP. 195 * 196 * @param enabled Whether to turn the PDH switchable channel on or off 197 */ 198 public void setSwitchableChannel(boolean enabled) { 199 PowerDistributionJNI.setSwitchableChannel(m_handle, enabled); 200 } 201 202 /** 203 * Returns the power distribution version number. 204 * 205 * @return The power distribution version number. 206 */ 207 public PowerDistributionVersion getVersion() { 208 return PowerDistributionJNI.getVersion(m_handle); 209 } 210 211 /** 212 * Returns the power distribution faults. 213 * 214 * @return The power distribution faults. 215 */ 216 public PowerDistributionFaults getFaults() { 217 return PowerDistributionJNI.getFaults(m_handle); 218 } 219 220 /** 221 * Returns the power distribution sticky faults. 222 * 223 * @return The power distribution sticky faults. 224 */ 225 public PowerDistributionStickyFaults getStickyFaults() { 226 return PowerDistributionJNI.getStickyFaults(m_handle); 227 } 228 229 @Override 230 public void initSendable(SendableBuilder builder) { 231 builder.setSmartDashboardType("PowerDistribution"); 232 int numChannels = getNumChannels(); 233 for (int i = 0; i < numChannels; ++i) { 234 final int chan = i; 235 builder.addDoubleProperty( 236 "Chan" + i, () -> PowerDistributionJNI.getChannelCurrentNoError(m_handle, chan), null); 237 } 238 builder.addDoubleProperty( 239 "Voltage", () -> PowerDistributionJNI.getVoltageNoError(m_handle), null); 240 builder.addDoubleProperty( 241 "TotalCurrent", () -> PowerDistributionJNI.getTotalCurrent(m_handle), null); 242 builder.addBooleanProperty( 243 "SwitchableChannel", 244 () -> PowerDistributionJNI.getSwitchableChannelNoError(m_handle), 245 value -> PowerDistributionJNI.setSwitchableChannel(m_handle, value)); 246 } 247}