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