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