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