001/* Copyright (C) Cross The Road Electronics 2024 */ 002package com.ctre.phoenix.motorcontrol; 003 004import com.ctre.phoenix.ErrorCode; 005import com.ctre.phoenix.motorcontrol.can.BaseTalon; 006import com.ctre.phoenix.motorcontrol.can.MotControllerJNI; 007 008/** 009 * Collection of sensors available to a motor controller. 010 * 011 * For best performance and update-rate, 012 * we recommend using the configSelectedFeedbackSensor() and getSelectedSensor*() routines. 013 * However there are occasions where accessing raw sensor values may be useful or convenient. 014 * Particularly if you are seeding one sensor based on another, or need to circumvent sensor-phase. 015 * 016 * Use the getSensorCollection() routine inside your motor controller to create a sensor collection. 017 */ 018public class SensorCollection { 019 020 private long _handle; 021 022 /** 023 * Constructor for SensorCollection 024 * @param motorController Motor Controller to connect Collection to 025 */ 026 public SensorCollection(BaseTalon motorController) { 027 _handle = motorController.getHandle(); 028 } 029 030 /** 031 * Get the position of whatever is in the analog pin of the Talon, regardless of 032 * whether it is actually being used for feedback. 033 * <p> 034 * This method relies on the Status 4 message, which has a default period of 150ms. For more 035 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 036 * 037 * @return the 24bit analog value. The bottom ten bits is the ADC (0 - 1023) 038 * on the analog pin of the Talon. The upper 14 bits tracks the overflows and underflows 039 * (continuous sensor). 040 */ 041 042 public int getAnalogIn() { 043 return MotControllerJNI.GetAnalogIn(_handle); 044 } 045 046 /** 047 * Sets analog position. 048 * 049 * @param newPosition The new position. 050 * @param timeoutMs 051 * Timeout value in ms. If nonzero, function will wait for 052 * config success and report an error if it times out. 053 * If zero, no blocking or checking is performed. 054 * 055 * @return an ErrorCode. 056 */ 057 058 public ErrorCode setAnalogPosition(int newPosition, int timeoutMs) { 059 int retval = MotControllerJNI.SetAnalogPosition(_handle, newPosition, timeoutMs); 060 return ErrorCode.valueOf(retval); 061 } 062 063 /** 064 * Get the position of whatever is in the analog pin of the Talon, regardless of whether 065 * it is actually being used for feedback. 066 * <p> 067 * This method relies on the Status 4 message, which has a default period of 150ms. For more 068 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 069 * 070 * @return the ADC (0 - 1023) on analog pin of the Talon. 071 */ 072 073 public int getAnalogInRaw() { 074 return MotControllerJNI.GetAnalogInRaw(_handle); 075 } 076 077 /** 078 * Get the velocity of whatever is in the analog pin of the Talon, regardless of 079 * whether it is actually being used for feedback. 080 * <p> 081 * This method relies on the Status 4 message, which has a default period of 150ms. For more 082 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 083 * 084 * @return the speed in units per 100ms where 1024 units is one rotation. 085 */ 086 087 public int getAnalogInVel() { 088 return MotControllerJNI.GetAnalogInVel(_handle); 089 } 090 091 /** 092 * Get the quadrature position of the Talon, regardless of whether 093 * it is actually being used for feedback. 094 * <p> 095 * This method relies on the Status 3 message, which has a default period of 150ms. For more 096 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 097 * 098 * @return the quadrature position. 099 */ 100 101 public int getQuadraturePosition() { 102 return MotControllerJNI.GetQuadraturePosition(_handle); 103 } 104 105 /** 106 * Change the quadrature reported position. Typically this is used to "zero" the 107 * sensor. This only works with Quadrature sensor. To set the selected sensor position 108 * regardless of what type it is, see SetSelectedSensorPosition in the motor controller class. 109 * 110 * @param newPosition The position value to apply to the sensor. 111 * @param timeoutMs 112 * Timeout value in ms. If nonzero, function will wait for 113 * config success and report an error if it times out. 114 * If zero, no blocking or checking is performed. 115 * 116 * @return error code. 117 */ 118 119 public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) { 120 int retval = MotControllerJNI.SetQuadraturePosition(_handle, newPosition, timeoutMs); 121 return ErrorCode.valueOf(retval); 122 } 123 124 125 /** 126 * Change the quadrature reported position based on pulse width. This can be used to 127 * effectively make quadrature absolute. For rotary mechanisms with >360 movement (such 128 * as typical swerve modules) bookend0 and bookend1 can be both set to 0 and 129 * bCrossZeroOnInterval can be set to true. For mechanisms with less than 360 travel (such 130 * as arms), bookend0 and bookend1 should be set to the pulse width values at the two 131 * extremes. If the interval crosses over the pulse width value of 0 (or any multiple of 132 * 4096), bCrossZeroOnInterval should be true and otherwise should be false. An offset can 133 * also be set. 134 * 135 * @param bookend0 value at extreme 0 136 * @param bookend1 value at extreme 1 137 * @param bCrossZeroOnInterval True iff zero/wrap-around cross occurs as mechanism moves from bookend0 to bookend1. 138 * @param offset (Optional) Value to add to pulse width 139 * @param timeoutMs (Optional) How long to wait for confirmation. Pass zero so that call 140 * does not block. 141 * 142 * @return error code. 143 */ 144 145 public ErrorCode syncQuadratureWithPulseWidth(int bookend0, int bookend1, boolean bCrossZeroOnInterval, int offset, int timeoutMs) { 146 int ticksPerRevolution = 4096; 147 /* Normalize bookends (should be 0 - ticksPerRevolution) */ 148 bookend0 &= (ticksPerRevolution - 1); 149 bookend1 &= (ticksPerRevolution - 1); 150 151 /* Assign greater and lesser bookend */ 152 int greaterBookend; 153 int lesserBookend; 154 155 if(bookend0 > bookend1) 156 { 157 greaterBookend = bookend0; 158 lesserBookend = bookend1; 159 } 160 else 161 { 162 greaterBookend = bookend1; 163 lesserBookend = bookend0; 164 } 165 166 int average = (greaterBookend + lesserBookend) / 2; 167 168 /* Get Fractional Part of Pulse Width Position (0 - ticksPerRevolution) */ 169 int pulseWidth = getPulseWidthPosition(); 170 pulseWidth &= (ticksPerRevolution - 1); 171 172 if(bCrossZeroOnInterval) 173 { 174 /* 175 * If the desire is to have the *** part be the interval 176 * (2048 - 3277 and crosses over 0): 177 * 178 * 179 * 1024 180 * ********* 181 * *********** 182 * ************* 183 * *************** 184 * ***************** 185 * ***************** 186 * ***************** 187 * 2048 ***************** 0 188 * ********* 189 * ********* 190 * ********* 191 * ********* 192 * ********** 193 * ********* 194 * ******** 195 * ******** 196 * ******* 197 * 3277 198 * 199 * The goal is to center the discontinuoity between 2048 and 3277 in the blank. 200 * So all pulse width values greater than the avg of the two bookends should be 201 * reduced by ticksPerRevolution. 202 */ 203 if(pulseWidth > average) 204 { 205 pulseWidth -= ticksPerRevolution; 206 } 207 } 208 else 209 { 210 /* 211 * If the desire is to have the blank part be the interval 212 * (2048 - 3277 and crosses over 0): 213 * 214 * 215 * 1024 216 * ********* 217 * *********** 218 * ************* 219 * *************** 220 * ***************** 221 * ***************** 222 * ***************** 223 * 2048 ***************** 0 224 * ********* 225 * ********* 226 * ********* 227 * ********* 228 * ********** 229 * ********* 230 * ******** 231 * ******** 232 * ******* 233 * 3277 234 * 235 * The goal is to center the discontinuoity between 2048 and 3277 in the ***. 236 * So all pulse width values less than the (ticksPerRevolution / 2 - avg of 237 * the two bookends) & ticksPerRevolution should be increased by 238 * ticksPerRevolution. 239 */ 240 if(pulseWidth < ((ticksPerRevolution / 2 - average) & 0x0FFF)) 241 { 242 pulseWidth += ticksPerRevolution; 243 } 244 } 245 246 pulseWidth += offset; 247 248 return setQuadraturePosition(pulseWidth, timeoutMs); 249 } 250 251 /** 252 * Change the quadrature reported position based on pulse width. This can be used to 253 * effectively make quadrature absolute. For rotary mechanisms with >360 movement (such 254 * as typical swerve modules) bookend0 and bookend1 can be both set to 0 and 255 * bCrossZeroOnInterval can be set to true. For mechanisms with less than 360 travel (such 256 * as arms), bookend0 and bookend1 should be set to the pulse width values at the two 257 * extremes. If the interval crosses over the pulse width value of 0 (or any multiple of 258 * 4096), bCrossZeroOnInterval should be true and otherwise should be false. An offset can 259 * also be set. 260 * 261 * @param bookend0 value at extreme 0 262 * @param bookend1 value at extreme 1 263 * @param bCrossZeroOnInterval True iff zero/wrap-around cross occurs as mechanism moves from bookend0 to bookend1. 264 * 265 * @return error code. 266 */ 267 public ErrorCode syncQuadratureWithPulseWidth(int bookend0, int bookend1, boolean bCrossZeroOnInterval) { 268 int offset = 0; 269 int timeoutMs = 0; 270 return syncQuadratureWithPulseWidth(bookend0, bookend1, bCrossZeroOnInterval, offset, timeoutMs); 271 } 272 /** 273 * Get the quadrature velocity, regardless of whether 274 * it is actually being used for feedback. 275 * <p> 276 * This method relies on the Status 3 message, which has a default period of 150ms. For more 277 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 278 * 279 * @return the quadrature velocity in units per 100ms. 280 */ 281 282 public int getQuadratureVelocity() { 283 return MotControllerJNI.GetQuadratureVelocity(_handle); 284 } 285 286 /** 287 * Gets pulse width position, regardless of whether 288 * it is actually being used for feedback. 289 * <p> 290 * This method relies on the Status 8 message, which has a default period of 150ms. For more 291 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 292 * 293 * @return the pulse width position. 294 */ 295 296 public int getPulseWidthPosition() { 297 return MotControllerJNI.GetPulseWidthPosition(_handle); 298 } 299 300 /** 301 * Sets pulse width position. 302 * 303 * @param newPosition The position value to apply to the sensor. 304 * @param timeoutMs 305 * Timeout value in ms. If nonzero, function will wait for 306 * config success and report an error if it times out. 307 * If zero, no blocking or checking is performed. 308 * 309 * @return an ErrErrorCode 310 */ 311 public ErrorCode setPulseWidthPosition(int newPosition, int timeoutMs) { 312 int retval = MotControllerJNI.SetPulseWidthPosition(_handle, newPosition, timeoutMs); 313 return ErrorCode.valueOf(retval); 314 } 315 316 /** 317 * Gets pulse width velocity, regardless of whether 318 * it is actually being used for feedback. 319 * <p> 320 * This method relies on the Status 8 message, which has a default period of 150ms. For more 321 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 322 * 323 * @return the pulse width velocity in units per 100ms (where 4096 units is 1 rotation). 324 */ 325 326 public int getPulseWidthVelocity() { 327 return MotControllerJNI.GetPulseWidthVelocity(_handle); 328 } 329 330 /** 331 * Gets pulse width rise to fall time. 332 * <p> 333 * This method relies on the Status 8 message, which has a default period of 150ms. For more 334 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 335 * 336 * @return the pulse width rise to fall time in microseconds. 337 */ 338 339 public int getPulseWidthRiseToFallUs() { 340 return MotControllerJNI.GetPulseWidthRiseToFallUs(_handle); 341 } 342 343 /** 344 * Gets pulse width rise to rise time. 345 * <p> 346 * This method relies on the Status 8 message, which has a default period of 150ms. For more 347 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 348 * 349 * @return the pulse width rise to rise time in microseconds. 350 */ 351 352 public int getPulseWidthRiseToRiseUs() { 353 return MotControllerJNI.GetPulseWidthRiseToRiseUs(_handle); 354 } 355 356 /** 357 * Gets pin state quad a. 358 * <p> 359 * This method relies on the Status 3 message, which has a default period of 150ms. For more 360 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 361 * 362 * @return the pin state of quad a (1 if asserted, 0 if not asserted). 363 */ 364 365 public boolean getPinStateQuadA() { 366 return MotControllerJNI.GetPinStateQuadA(_handle) != 0; 367 } 368 369 /** 370 * Gets pin state quad b. 371 * <p> 372 * This method relies on the Status 3 message, which has a default period of 150ms. For more 373 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 374 * 375 * @return Digital level of QUADB pin (1 if asserted, 0 if not asserted). 376 */ 377 378 public boolean getPinStateQuadB() { 379 return MotControllerJNI.GetPinStateQuadB(_handle) != 0; 380 } 381 382 /** 383 * Gets pin state quad index. 384 * <p> 385 * This method relies on the Status 3 message, which has a default period of 150ms. For more 386 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 387 * 388 * @return Digital level of QUAD Index pin (1 if asserted, 0 if not asserted). 389 */ 390 391 public boolean getPinStateQuadIdx() { 392 return MotControllerJNI.GetPinStateQuadIdx(_handle) != 0; 393 } 394 395 /** 396 * Is forward limit switch closed. 397 * <p> 398 * This method relies on the Status 1 message, which has a default period of 10ms. For more 399 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 400 * 401 * @return '1' iff forward limit switch is closed, 0 iff switch is open. This function works 402 * regardless if limit switch feature is enabled. Remote limit features do not impact this routine. 403 */ 404 405 public boolean isFwdLimitSwitchClosed() { 406 return MotControllerJNI.IsFwdLimitSwitchClosed(_handle) != 0; 407 } 408 409 /** 410 * Is reverse limit switch closed. 411 * <p> 412 * This method relies on the Status 1 message, which has a default period of 10ms. For more 413 * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html 414 * 415 * @return '1' iff reverse limit switch is closed, 0 iff switch is open. This function works 416 * regardless if limit switch feature is enabled. Remote limit features do not impact this routine. 417 */ 418 419 public boolean isRevLimitSwitchClosed() { 420 return MotControllerJNI.IsRevLimitSwitchClosed(_handle) != 0; 421 } 422}