001/* 002 * Copyright (C) Cross The Road Electronics. All rights reserved. 003 * License information can be found in CTRE_LICENSE.txt 004 * For support and suggestions contact support@ctr-electronics.com or file 005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases 006 */ 007package com.ctre.phoenix6.controls; 008 009import com.ctre.phoenix6.StatusCode; 010import com.ctre.phoenix6.controls.jni.ControlJNI; 011import com.ctre.phoenix6.hardware.traits.*; 012 013import edu.wpi.first.units.*; 014import edu.wpi.first.units.measure.*; 015import static edu.wpi.first.units.Units.*; 016 017import java.util.HashMap; 018import java.util.Map; 019 020/** 021 * Request a specified voltage. 022 * <p> 023 * This control mode will attempt to apply the specified voltage to the motor. If the supply voltage is below 024 * the requested voltage, the motor controller will output the supply voltage. 025 */ 026public class VoltageOut extends ControlRequest implements Cloneable 027{ 028 /** 029 * Voltage to attempt to drive at 030 * 031 * <ul> 032 * <li> Units: Volts 033 * </ul> 034 * 035 */ 036 public double Output; 037 /** 038 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 039 * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to 040 * false to use trapezoidal commutation. 041 * <p> 042 * FOC improves motor performance by leveraging torque (current) control. 043 * However, this may be inconvenient for applications that require specifying 044 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 045 * combines the performances gains of FOC while still allowing applications to 046 * provide duty cycle or voltage demand. This not to be confused with simple 047 * sinusoidal control or phase voltage control which lacks the performance 048 * gains. 049 */ 050 public boolean EnableFOC = true; 051 /** 052 * Set to true to static-brake the rotor when output is zero (or within 053 * deadband). Set to false to use the NeutralMode configuration setting 054 * (default). This flag exists to provide the fundamental behavior of this 055 * control when output is zero, which is to provide 0V to the motor. 056 */ 057 public boolean OverrideBrakeDurNeutral = false; 058 /** 059 * Set to true to force forward limiting. This allows users to use other limit 060 * switch sensors connected to robot controller. This also allows use of active 061 * sensors that require external power. 062 */ 063 public boolean LimitForwardMotion = false; 064 /** 065 * Set to true to force reverse limiting. This allows users to use other limit 066 * switch sensors connected to robot controller. This also allows use of active 067 * sensors that require external power. 068 */ 069 public boolean LimitReverseMotion = false; 070 /** 071 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 072 * LimitReverseMotion parameters, instead allowing motion. 073 * <p> 074 * This can be useful on mechanisms such as an intake/feeder, where a limit 075 * switch stops motion while intaking but should be ignored when feeding to a 076 * shooter. 077 * <p> 078 * The hardware limit faults and Forward/ReverseLimit signals will still report 079 * the values of the limit switches regardless of this parameter. 080 */ 081 public boolean IgnoreHardwareLimits = false; 082 /** 083 * Set to true to delay applying this control request until a timesync boundary 084 * (requires Phoenix Pro and CANivore). This eliminates the impact of 085 * nondeterministic network delays in exchange for a larger but deterministic 086 * control latency. 087 * <p> 088 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 089 * Additionally, when this is enabled, the UpdateFreqHz of this request should 090 * be set to 0 Hz. 091 */ 092 public boolean UseTimesync = false; 093 094 /** 095 * The period at which this control will update at. 096 * This is designated in Hertz, with a minimum of 20 Hz 097 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 098 * <p> 099 * If this field is set to 0 Hz, the control request will 100 * be sent immediately as a one-shot frame. This may be useful 101 * for advanced applications that require outputs to be 102 * synchronized with data acquisition. In this case, we 103 * recommend not exceeding 50 ms between control calls. 104 */ 105 public double UpdateFreqHz = 100; 106 107 /** 108 * Request a specified voltage. 109 * <p> 110 * This control mode will attempt to apply the specified voltage to the motor. 111 * If the supply voltage is below the requested voltage, the motor controller 112 * will output the supply voltage. 113 * 114 * @param Output Voltage to attempt to drive at 115 */ 116 public VoltageOut(double Output) 117 { 118 super("VoltageOut"); 119 this.Output = Output; 120 } 121 122 /** 123 * Request a specified voltage. 124 * <p> 125 * This control mode will attempt to apply the specified voltage to the motor. 126 * If the supply voltage is below the requested voltage, the motor controller 127 * will output the supply voltage. 128 * 129 * @param Output Voltage to attempt to drive at 130 */ 131 public VoltageOut(Voltage Output) 132 { 133 this(Output.in(Volts)); 134 } 135 136 @Override 137 public String toString() 138 { 139 String ss = "Control: VoltageOut\n"; 140 ss += " Output: " + Output + " Volts" + "\n"; 141 ss += " EnableFOC: " + EnableFOC + "\n"; 142 ss += " OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n"; 143 ss += " LimitForwardMotion: " + LimitForwardMotion + "\n"; 144 ss += " LimitReverseMotion: " + LimitReverseMotion + "\n"; 145 ss += " IgnoreHardwareLimits: " + IgnoreHardwareLimits + "\n"; 146 ss += " UseTimesync: " + UseTimesync + "\n"; 147 return ss; 148 } 149 150 @Override 151 public StatusCode sendRequest(String network, int deviceHash) 152 { 153 return StatusCode.valueOf(ControlJNI.JNI_RequestControlVoltageOut( 154 network, deviceHash, UpdateFreqHz, Output, EnableFOC, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion, IgnoreHardwareLimits, UseTimesync)); 155 } 156 157 /** 158 * Gets information about this control request. 159 * 160 * @return Map of control parameter names and corresponding applied values 161 */ 162 @Override 163 public Map<String, String> getControlInfo() 164 { 165 var controlInfo = new HashMap<String, String>(); 166 controlInfo.put("Name", getName()); 167 controlInfo.put("Output", String.valueOf(this.Output)); 168 controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC)); 169 controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral)); 170 controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion)); 171 controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion)); 172 controlInfo.put("IgnoreHardwareLimits", String.valueOf(this.IgnoreHardwareLimits)); 173 controlInfo.put("UseTimesync", String.valueOf(this.UseTimesync)); 174 return controlInfo; 175 } 176 177 /** 178 * Modifies this Control Request's Output parameter and returns itself for 179 * method-chaining and easier to use request API. 180 * <p> 181 * Voltage to attempt to drive at 182 * 183 * <ul> 184 * <li> Units: Volts 185 * </ul> 186 * 187 * 188 * @param newOutput Parameter to modify 189 * @return Itself 190 */ 191 public VoltageOut withOutput(double newOutput) 192 { 193 Output = newOutput; 194 return this; 195 } 196 197 /** 198 * Modifies this Control Request's Output parameter and returns itself for 199 * method-chaining and easier to use request API. 200 * <p> 201 * Voltage to attempt to drive at 202 * 203 * <ul> 204 * <li> Units: Volts 205 * </ul> 206 * 207 * 208 * @param newOutput Parameter to modify 209 * @return Itself 210 */ 211 public VoltageOut withOutput(Voltage newOutput) 212 { 213 Output = newOutput.in(Volts); 214 return this; 215 } 216 217 /** 218 * Helper method to get this Control Request's Output parameter converted 219 * to a unit type. If not using the Java units library, {@link #Output} 220 * can be accessed directly instead. 221 * <p> 222 * Voltage to attempt to drive at 223 * 224 * <ul> 225 * <li> Units: Volts 226 * </ul> 227 * 228 * 229 * @return Output 230 */ 231 public Voltage getOutputMeasure() 232 { 233 return Volts.of(Output); 234 } 235 236 /** 237 * Modifies this Control Request's EnableFOC parameter and returns itself for 238 * method-chaining and easier to use request API. 239 * <p> 240 * Set to true to use FOC commutation (requires Phoenix Pro), which increases 241 * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to 242 * false to use trapezoidal commutation. 243 * <p> 244 * FOC improves motor performance by leveraging torque (current) control. 245 * However, this may be inconvenient for applications that require specifying 246 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that 247 * combines the performances gains of FOC while still allowing applications to 248 * provide duty cycle or voltage demand. This not to be confused with simple 249 * sinusoidal control or phase voltage control which lacks the performance 250 * gains. 251 * 252 * @param newEnableFOC Parameter to modify 253 * @return Itself 254 */ 255 public VoltageOut withEnableFOC(boolean newEnableFOC) 256 { 257 EnableFOC = newEnableFOC; 258 return this; 259 } 260 261 /** 262 * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for 263 * method-chaining and easier to use request API. 264 * <p> 265 * Set to true to static-brake the rotor when output is zero (or within 266 * deadband). Set to false to use the NeutralMode configuration setting 267 * (default). This flag exists to provide the fundamental behavior of this 268 * control when output is zero, which is to provide 0V to the motor. 269 * 270 * @param newOverrideBrakeDurNeutral Parameter to modify 271 * @return Itself 272 */ 273 public VoltageOut withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral) 274 { 275 OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral; 276 return this; 277 } 278 279 /** 280 * Modifies this Control Request's LimitForwardMotion parameter and returns itself for 281 * method-chaining and easier to use request API. 282 * <p> 283 * Set to true to force forward limiting. This allows users to use other limit 284 * switch sensors connected to robot controller. This also allows use of active 285 * sensors that require external power. 286 * 287 * @param newLimitForwardMotion Parameter to modify 288 * @return Itself 289 */ 290 public VoltageOut withLimitForwardMotion(boolean newLimitForwardMotion) 291 { 292 LimitForwardMotion = newLimitForwardMotion; 293 return this; 294 } 295 296 /** 297 * Modifies this Control Request's LimitReverseMotion parameter and returns itself for 298 * method-chaining and easier to use request API. 299 * <p> 300 * Set to true to force reverse limiting. This allows users to use other limit 301 * switch sensors connected to robot controller. This also allows use of active 302 * sensors that require external power. 303 * 304 * @param newLimitReverseMotion Parameter to modify 305 * @return Itself 306 */ 307 public VoltageOut withLimitReverseMotion(boolean newLimitReverseMotion) 308 { 309 LimitReverseMotion = newLimitReverseMotion; 310 return this; 311 } 312 313 /** 314 * Modifies this Control Request's IgnoreHardwareLimits parameter and returns itself for 315 * method-chaining and easier to use request API. 316 * <p> 317 * Set to true to ignore hardware limit switches and the LimitForwardMotion and 318 * LimitReverseMotion parameters, instead allowing motion. 319 * <p> 320 * This can be useful on mechanisms such as an intake/feeder, where a limit 321 * switch stops motion while intaking but should be ignored when feeding to a 322 * shooter. 323 * <p> 324 * The hardware limit faults and Forward/ReverseLimit signals will still report 325 * the values of the limit switches regardless of this parameter. 326 * 327 * @param newIgnoreHardwareLimits Parameter to modify 328 * @return Itself 329 */ 330 public VoltageOut withIgnoreHardwareLimits(boolean newIgnoreHardwareLimits) 331 { 332 IgnoreHardwareLimits = newIgnoreHardwareLimits; 333 return this; 334 } 335 336 /** 337 * Modifies this Control Request's UseTimesync parameter and returns itself for 338 * method-chaining and easier to use request API. 339 * <p> 340 * Set to true to delay applying this control request until a timesync boundary 341 * (requires Phoenix Pro and CANivore). This eliminates the impact of 342 * nondeterministic network delays in exchange for a larger but deterministic 343 * control latency. 344 * <p> 345 * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs. 346 * Additionally, when this is enabled, the UpdateFreqHz of this request should 347 * be set to 0 Hz. 348 * 349 * @param newUseTimesync Parameter to modify 350 * @return Itself 351 */ 352 public VoltageOut withUseTimesync(boolean newUseTimesync) 353 { 354 UseTimesync = newUseTimesync; 355 return this; 356 } 357 358 /** 359 * Sets the period at which this control will update at. 360 * This is designated in Hertz, with a minimum of 20 Hz 361 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 362 * <p> 363 * If this field is set to 0 Hz, the control request will 364 * be sent immediately as a one-shot frame. This may be useful 365 * for advanced applications that require outputs to be 366 * synchronized with data acquisition. In this case, we 367 * recommend not exceeding 50 ms between control calls. 368 * 369 * @param newUpdateFreqHz Parameter to modify 370 * @return Itself 371 */ 372 @Override 373 public VoltageOut withUpdateFreqHz(double newUpdateFreqHz) 374 { 375 UpdateFreqHz = newUpdateFreqHz; 376 return this; 377 } 378 379 /** 380 * Sets the period at which this control will update at. 381 * This is designated in Hertz, with a minimum of 20 Hz 382 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 383 * <p> 384 * If this field is set to 0 Hz, the control request will 385 * be sent immediately as a one-shot frame. This may be useful 386 * for advanced applications that require outputs to be 387 * synchronized with data acquisition. In this case, we 388 * recommend not exceeding 50 ms between control calls. 389 * 390 * @param newUpdateFreqHz Parameter to modify 391 * @return Itself 392 */ 393 @Override 394 public VoltageOut withUpdateFreqHz(Frequency newUpdateFreqHz) 395 { 396 UpdateFreqHz = newUpdateFreqHz.in(Hertz); 397 return this; 398 } 399 400 @Override 401 public VoltageOut clone() 402 { 403 try { 404 return (VoltageOut)super.clone(); 405 } catch (CloneNotSupportedException ex) { 406 /* this should never happen */ 407 throw new RuntimeException(ex); 408 } 409 } 410} 411