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