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.phoenixpro.controls; 008 009import com.ctre.phoenixpro.StatusCode; 010import com.ctre.phoenixpro.controls.jni.ControlJNI; 011import com.ctre.phoenixpro.controls.jni.ControlConfigJNI; 012 013/** 014 * Request a specified motor current (field oriented control). 015 * <p> 016 * This control request will drive the motor to the requested motor (stator) current value. This leverages 017 * field oriented control (FOC), which means greater peak power than what is documented. This scales to 018 * torque based on Motor's kT constant. 019 */ 020public class TorqueCurrentFOC extends ControlRequest 021{ 022 private boolean applyConfigsOnRequest; 023 /** 024 * Amount of motor current in Amperes 025 */ 026 public double Output; 027 /** 028 * The maximum absolute motor output that can be applied, which effectively 029 * limits the velocity. For example, 0.50 means no more than 50% output in 030 * either direction. This is useful for preventing the motor from spinning to 031 * its terminal velocity when there is no external torque applied unto the 032 * rotor. Note this is absolute maximum, so the value should be between zero 033 * and one. 034 */ 035 public double MaxAbsDutyCycle; 036 /** 037 * Deadband in Amperes. If torque request is within deadband, the bridge output 038 * is neutral. If deadband is set to zero then there is effectively no deadband. 039 * Note if deadband is zero, a free spinning motor will spin for quite a while 040 * as the firmware attempts to hold the motor's bemf. If user expects motor to 041 * cease spinning quickly with a demand of zero, we recommend a deadband of one 042 * Ampere. This value will be converted to an integral value of amps. 043 */ 044 public double Deadband; 045 /** 046 * Set to true to coast the rotor when output is zero (or within deadband). Set 047 * to false to use the NeutralMode configuration setting (default). This flag 048 * exists to provide the fundamental behavior of this control when output is 049 * zero, which is to provide 0A (zero torque). 050 */ 051 public boolean OverrideCoastDurNeutral; 052 053 054 /** 055 * The period at which this control will update at. 056 * This is designated in Hertz, with a minimum of 20 Hz 057 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 058 * <p> 059 * If this field is set to 0 Hz, the control request will 060 * be sent immediately as a one-shot frame. This may be useful 061 * for advanced applications that require outputs to be 062 * synchronized with data acquisition. In this case, we 063 * recommend not exceeding 50 ms between control calls. 064 */ 065 public double UpdateFreqHz = 100; // Default to 100Hz 066 067 /** 068 * The timeout when sending configs associated with this control 069 */ 070 public double configTimeout = 0.1; 071 072 /** 073 * Request a specified motor current (field oriented control). 074 * <p> 075 * This control request will drive the motor to the requested motor (stator) 076 * current value. This leverages field oriented control (FOC), which means 077 * greater peak power than what is documented. This scales to torque based 078 * on Motor's kT constant. 079 * 080 * @param Output Amount of motor current in Amperes 081 * @param MaxAbsDutyCycle The maximum absolute motor output that can be 082 * applied, which effectively limits the 083 * velocity. For example, 0.50 means no more than 084 * 50% output in either direction. This is 085 * useful for preventing the motor from spinning 086 * to its terminal velocity when there is no 087 * external torque applied unto the rotor. Note 088 * this is absolute maximum, so the value should 089 * be between zero and one. 090 * @param Deadband Deadband in Amperes. If torque request is within 091 * deadband, the bridge output is neutral. If deadband 092 * is set to zero then there is effectively no deadband. 093 * Note if deadband is zero, a free spinning motor will 094 * spin for quite a while as the firmware attempts to 095 * hold the motor's bemf. If user expects motor to cease 096 * spinning quickly with a demand of zero, we recommend 097 * a deadband of one Ampere. This value will be 098 * converted to an integral value of amps. 099 * @param OverrideCoastDurNeutral Set to true to coast the rotor when 100 * output is zero (or within deadband). 101 * Set to false to use the NeutralMode 102 * configuration setting (default). This 103 * flag exists to provide the fundamental 104 * behavior of this control when output 105 * is zero, which is to provide 0A (zero 106 * torque). 107 */ 108 public TorqueCurrentFOC(double Output, double MaxAbsDutyCycle, double Deadband, boolean OverrideCoastDurNeutral) 109 { 110 super("TorqueCurrentFOC"); 111 this.Output = Output; 112 this.MaxAbsDutyCycle = MaxAbsDutyCycle; 113 this.Deadband = Deadband; 114 this.OverrideCoastDurNeutral = OverrideCoastDurNeutral; 115 } 116 117 /** 118 * Request a specified motor current (field oriented control). 119 * <p> 120 * This control request will drive the motor to the requested motor (stator) 121 * current value. This leverages field oriented control (FOC), which means 122 * greater peak power than what is documented. This scales to torque based 123 * on Motor's kT constant. 124 * 125 * @param Output Amount of motor current in Amperes 126 */ 127 public TorqueCurrentFOC(double Output) 128 { 129 this(Output, 1.0, 0.0, false); 130 } 131 132 @Override 133 public String toString() 134 { 135 String ss = "class: TorqueCurrentFOC\n"; 136 ss += "Output: " + Output + "\n"; 137 ss += "MaxAbsDutyCycle: " + MaxAbsDutyCycle + "\n"; 138 ss += "Deadband: " + Deadband + "\n"; 139 ss += "OverrideCoastDurNeutral: " + OverrideCoastDurNeutral + "\n"; 140 return ss; 141 } 142 143 @Override 144 public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests) 145 { 146 var ref = requestReference.getNameValues(); 147 ref.put("Output", String.valueOf(this.Output)); 148 ref.put("MaxAbsDutyCycle", String.valueOf(this.MaxAbsDutyCycle)); 149 ref.put("Deadband", String.valueOf(this.Deadband)); 150 ref.put("OverrideCoastDurNeutral", String.valueOf(this.OverrideCoastDurNeutral)); 151 String ss = ""; 152 153 ControlConfigJNI.JNI_RequestConfigApply(network, deviceHash, configTimeout, ss, applyConfigsOnRequest); 154 applyConfigsOnRequest = false; 155 return StatusCode.valueOf(ControlJNI.JNI_RequestControlTorqueCurrentFOC( 156 network, deviceHash, UpdateFreqHz, cancelOtherRequests, Output, MaxAbsDutyCycle, Deadband, OverrideCoastDurNeutral)); 157 } 158 159 /** 160 * Modifies this Control Request's Output parameter and returns itself for 161 * method-chaining and easier to use request API. 162 * 163 * @param newOutput Parameter to modify 164 * @return Itself 165 */ 166 public TorqueCurrentFOC withOutput(double newOutput) 167 { 168 Output = newOutput; 169 return this; 170 } 171 172 /** 173 * Modifies this Control Request's MaxAbsDutyCycle parameter and returns itself for 174 * method-chaining and easier to use request API. 175 * 176 * @param newMaxAbsDutyCycle Parameter to modify 177 * @return Itself 178 */ 179 public TorqueCurrentFOC withMaxAbsDutyCycle(double newMaxAbsDutyCycle) 180 { 181 MaxAbsDutyCycle = newMaxAbsDutyCycle; 182 return this; 183 } 184 185 /** 186 * Modifies this Control Request's Deadband parameter and returns itself for 187 * method-chaining and easier to use request API. 188 * 189 * @param newDeadband Parameter to modify 190 * @return Itself 191 */ 192 public TorqueCurrentFOC withDeadband(double newDeadband) 193 { 194 Deadband = newDeadband; 195 return this; 196 } 197 198 /** 199 * Modifies this Control Request's OverrideCoastDurNeutral parameter and returns itself for 200 * method-chaining and easier to use request API. 201 * 202 * @param newOverrideCoastDurNeutral Parameter to modify 203 * @return Itself 204 */ 205 public TorqueCurrentFOC withOverrideCoastDurNeutral(boolean newOverrideCoastDurNeutral) 206 { 207 OverrideCoastDurNeutral = newOverrideCoastDurNeutral; 208 return this; 209 } 210 /** 211 * Sets the period at which this control will update at. 212 * This is designated in Hertz, with a minimum of 20 Hz 213 * (every 50 ms) and a maximum of 1000 Hz (every 1 ms). 214 * <p> 215 * If this field is set to 0 Hz, the control request will 216 * be sent immediately as a one-shot frame. This may be useful 217 * for advanced applications that require outputs to be 218 * synchronized with data acquisition. In this case, we 219 * recommend not exceeding 50 ms between control calls. 220 * 221 * @param newUpdateFreqHz Parameter to modify 222 * @return Itself 223 */ 224 public TorqueCurrentFOC withUpdateFreqHz(double newUpdateFreqHz) 225 { 226 UpdateFreqHz = newUpdateFreqHz; 227 return this; 228 } 229 /** 230 * Forces configs to be applied the next time this is used in a setControl. 231 * <p> 232 * This is not necessary in the majority of cases, because Phoenix will make sure configs are 233 * properly set when they are not already set 234 */ 235 public void forceApplyConfigs() { applyConfigsOnRequest = true; } 236} 237