|
43 | 43 | import edu.wpi.first.math.filter.Debouncer;
|
44 | 44 | import edu.wpi.first.math.system.plant.DCMotor;
|
45 | 45 | import edu.wpi.first.math.trajectory.TrapezoidProfile;
|
| 46 | +import edu.wpi.first.units.Angle; |
46 | 47 | import edu.wpi.first.units.Current;
|
47 | 48 | import edu.wpi.first.units.Measure;
|
48 | 49 | import edu.wpi.first.units.Time;
|
49 | 50 | import edu.wpi.first.units.Units;
|
| 51 | +import edu.wpi.first.units.Velocity; |
50 | 52 | import edu.wpi.first.units.Voltage;
|
51 | 53 | import edu.wpi.first.util.sendable.Sendable;
|
52 | 54 | import edu.wpi.first.util.sendable.SendableBuilder;
|
@@ -154,7 +156,8 @@ public static class SparkInputs {
|
154 | 156 | private static final String ARB_FF_LOG_ENTRY = "/ArbitraryFF";
|
155 | 157 | private static final String ARB_FF_UNITS_LOG_ENTRY = "/ArbitraryFFUnits";
|
156 | 158 | private static final String IDLE_MODE_LOG_ENTRY = "/IdleMode";
|
157 |
| - private static final String CURRENT_LOG_ENTRY = "/Current"; |
| 159 | + private static final String INPUT_CURRENT_LOG_ENTRY = "/InputCurrent"; |
| 160 | + private static final String OUTPUT_CURRENT_LOG_ENTRY = "/OutputCurrent"; |
158 | 161 | private static final String TEMPERATURE_LOG_ENTRY = "/Temperature";
|
159 | 162 | private static final String MOTION_LOG_ENTRY = "/SmoothMotion";
|
160 | 163 | private static final Measure<Time> DEFAULT_STATUS_FRAME_PERIOD = Units.Milliseconds.of(20.0);
|
@@ -604,7 +607,8 @@ protected void periodic() {
|
604 | 607 |
|
605 | 608 | handleSmoothMotion();
|
606 | 609 |
|
607 |
| - Logger.recordOutput(m_id.name + CURRENT_LOG_ENTRY, getOutputCurrent()); |
| 610 | + Logger.recordOutput(m_id.name + INPUT_CURRENT_LOG_ENTRY, getInputCurrent()); |
| 611 | + Logger.recordOutput(m_id.name + OUTPUT_CURRENT_LOG_ENTRY, getOutputCurrent()); |
608 | 612 | Logger.recordOutput(m_id.name + MOTION_LOG_ENTRY, m_isSmoothMotionEnabled);
|
609 | 613 |
|
610 | 614 | if (getMotorType() == MotorType.kBrushed) return;
|
@@ -1423,13 +1427,120 @@ public REVLibError setIdleMode(IdleMode mode) {
|
1423 | 1427 | * @param limit The desired current limit
|
1424 | 1428 | */
|
1425 | 1429 | public REVLibError setSmartCurrentLimit(Measure<Current> limit) {
|
1426 |
| - REVLibError status; |
1427 |
| - status = applyParameter( |
1428 |
| - () -> m_spark.setSmartCurrentLimit((int)limit.in(Units.Amps)), |
1429 |
| - () -> SparkHelpers.getSmartCurrentLimit(m_spark) == (int)limit.in(Units.Amps), |
1430 |
| - "Set current limit failure!" |
| 1430 | + return setSmartCurrentLimit(limit, Units.Amps.zero(), Units.RPM.of(20000)); |
| 1431 | + } |
| 1432 | + |
| 1433 | + /** |
| 1434 | + * Sets the current limit in Amps. |
| 1435 | + * |
| 1436 | + * <p>The motor controller will reduce the controller voltage output to avoid surpassing this |
| 1437 | + * limit. This limit is enabled by default and used for brushless only. This limit is highly |
| 1438 | + * recommended when using the NEO brushless motor. |
| 1439 | + * |
| 1440 | + * <p>The NEO Brushless Motor has a low internal resistance, which can mean large current spikes |
| 1441 | + * that could be enough to cause damage to the motor and controller. This current limit provides a |
| 1442 | + * smarter strategy to deal with high current draws and keep the motor and controller operating in |
| 1443 | + * a safe region. |
| 1444 | + * |
| 1445 | + * <p>The controller can also limit the current based on the RPM of the motor in a linear fashion |
| 1446 | + * to help with controllability in closed loop control. For a response that is linear the entire |
| 1447 | + * RPM range leave limit RPM at 0. |
| 1448 | + * |
| 1449 | + * @param stallLimit The current limit in Amps at 0 RPM. |
| 1450 | + * @param freeLimit The current limit at free speed (5700RPM for NEO). |
| 1451 | + * @param limitRPM RPM less than this value will be set to the stallLimit, RPM values greater than |
| 1452 | + * limitRPM will scale linearly to freeLimit |
| 1453 | + * @return {@link REVLibError#kOk} if successful |
| 1454 | + */ |
| 1455 | + public REVLibError setSmartCurrentLimit(Measure<Current> stallLimit, Measure<Current> freeLimit, Measure<Velocity<Angle>> limitRPM) { |
| 1456 | + return applyParameter( |
| 1457 | + () -> m_spark.setSmartCurrentLimit((int)stallLimit.in(Units.Amps), (int)freeLimit.in(Units.Amps), (int)limitRPM.in(Units.RPM)), |
| 1458 | + () -> Units.Amp.of(SparkHelpers.getSmartCurrentFreeLimit(m_spark)).isEquivalent(freeLimit) && |
| 1459 | + Units.Amp.of(SparkHelpers.getSmartCurrentStallLimit(m_spark)).isEquivalent(stallLimit) && |
| 1460 | + Units.RPM.of(SparkHelpers.getSmartCurrentLimitRPM(m_spark)).isEquivalent(limitRPM), |
| 1461 | + "Current limits not set!" |
| 1462 | + ); |
| 1463 | + } |
| 1464 | + |
| 1465 | + /** |
| 1466 | + * Sets the current limit in Amps. |
| 1467 | + * |
| 1468 | + * <p>The motor controller will reduce the controller voltage output to avoid surpassing this |
| 1469 | + * limit. This limit is enabled by default and used for brushless only. This limit is highly |
| 1470 | + * recommended when using the NEO brushless motor. |
| 1471 | + * |
| 1472 | + * <p>The NEO Brushless Motor has a low internal resistance, which can mean large current spikes |
| 1473 | + * that could be enough to cause damage to the motor and controller. This current limit provides a |
| 1474 | + * smarter strategy to deal with high current draws and keep the motor and controller operating in |
| 1475 | + * a safe region. |
| 1476 | + * |
| 1477 | + * <p>The controller can also limit the current based on the RPM of the motor in a linear fashion |
| 1478 | + * to help with controllability in closed loop control. For a response that is linear the entire |
| 1479 | + * RPM range leave limit RPM at 0. |
| 1480 | + * |
| 1481 | + * @param stallLimit The current limit in Amps at 0 RPM. |
| 1482 | + * @param freeLimit The current limit at free speed (5700RPM for NEO). |
| 1483 | + * @return {@link REVLibError#kOk} if successful |
| 1484 | + */ |
| 1485 | + public REVLibError setSmartCurrentLimit(Measure<Current> stallLimit, Measure<Current> freeLimit) { |
| 1486 | + return setSmartCurrentLimit(stallLimit, freeLimit, Units.RPM.of(20000)); |
| 1487 | + } |
| 1488 | + |
| 1489 | + /** |
| 1490 | + * Sets the secondary current limit in Amps. |
| 1491 | + * |
| 1492 | + * <p>The motor controller will disable the output of the controller briefly if the current limit |
| 1493 | + * is exceeded to reduce the current. This limit is a simplified 'on/off' controller. This limit |
| 1494 | + * is enabled by default but is set higher than the default Smart Current Limit. |
| 1495 | + * |
| 1496 | + * <p>The time the controller is off after the current limit is reached is determined by the |
| 1497 | + * parameter limitCycles, which is the number of PWM cycles (20kHz). The recommended value is the |
| 1498 | + * default of 0 which is the minimum time and is part of a PWM cycle from when the over current is |
| 1499 | + * detected. This allows the controller to regulate the current close to the limit value. |
| 1500 | + * |
| 1501 | + * <p>The total time is set by the equation <code> |
| 1502 | + * t = (50us - t0) + 50us * limitCycles |
| 1503 | + * t = total off time after over current |
| 1504 | + * t0 = time from the start of the PWM cycle until over current is detected |
| 1505 | + * </code> |
| 1506 | + * |
| 1507 | + * @param limit The current limit in Amps. |
| 1508 | + * @return {@link REVLibError#kOk} if successful |
| 1509 | + */ |
| 1510 | + public REVLibError setSecondaryCurrentLimit(Measure<Current> limit) { |
| 1511 | + return setSecondaryCurrentLimit(limit, 0); |
| 1512 | + } |
| 1513 | + |
| 1514 | + /** |
| 1515 | + * Sets the secondary current limit in Amps. |
| 1516 | + * |
| 1517 | + * <p>The motor controller will disable the output of the controller briefly if the current limit |
| 1518 | + * is exceeded to reduce the current. This limit is a simplified 'on/off' controller. This limit |
| 1519 | + * is enabled by default but is set higher than the default Smart Current Limit. |
| 1520 | + * |
| 1521 | + * <p>The time the controller is off after the current limit is reached is determined by the |
| 1522 | + * parameter limitCycles, which is the number of PWM cycles (20kHz). The recommended value is the |
| 1523 | + * default of 0 which is the minimum time and is part of a PWM cycle from when the over current is |
| 1524 | + * detected. This allows the controller to regulate the current close to the limit value. |
| 1525 | + * |
| 1526 | + * <p>The total time is set by the equation <code> |
| 1527 | + * t = (50us - t0) + 50us * limitCycles |
| 1528 | + * t = total off time after over current |
| 1529 | + * t0 = time from the start of the PWM cycle until over current is detected |
| 1530 | + * </code> |
| 1531 | + * |
| 1532 | + * @param limit The current limit in Amps. |
| 1533 | + * @param chopCycles The number of additional PWM cycles to turn the driver off after overcurrent |
| 1534 | + * is detected. |
| 1535 | + * @return {@link REVLibError#kOk} if successful |
| 1536 | + */ |
| 1537 | + public REVLibError setSecondaryCurrentLimit(Measure<Current> limit, int chopCycles) { |
| 1538 | + return applyParameter( |
| 1539 | + () -> m_spark.setSecondaryCurrentLimit((double)limit.in(Units.Amps), chopCycles), |
| 1540 | + () -> Units.Amp.of(SparkHelpers.getSecondaryCurrentLimit(m_spark)).isEquivalent(limit) && |
| 1541 | + SparkHelpers.getSecondaryCurrentLimitCycles(m_spark) == chopCycles, |
| 1542 | + "Secondary current limits not set!" |
1431 | 1543 | );
|
1432 |
| - return status; |
1433 | 1544 | }
|
1434 | 1545 |
|
1435 | 1546 | /**
|
@@ -1482,6 +1593,14 @@ public REVLibError setClosedLoopRampRate(Measure<Time> rampTime) {
|
1482 | 1593 | return m_spark.setClosedLoopRampRate(rampTime.in(Units.Seconds));
|
1483 | 1594 | }
|
1484 | 1595 |
|
| 1596 | + /** |
| 1597 | + * Spark approximate input current |
| 1598 | + * @return |
| 1599 | + */ |
| 1600 | + public Measure<Current> getInputCurrent() { |
| 1601 | + return getOutputCurrent().times(m_spark.getAppliedOutput()); |
| 1602 | + } |
| 1603 | + |
1485 | 1604 | /**
|
1486 | 1605 | * Spark output current
|
1487 | 1606 | * @return Output current
|
|
0 commit comments