Skip to content

Commit 94acbb1

Browse files
committed
Merge branch 'spark-dev' into develop
2 parents 60b4da2 + 83e68a0 commit 94acbb1

File tree

2 files changed

+165
-10
lines changed

2 files changed

+165
-10
lines changed

src/main/java/com/revrobotics/SparkHelpers.java

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,50 @@
99
/** Spark helpers */
1010
public class SparkHelpers {
1111
/**
12-
* Get current limit of Spark
12+
* Get current stall limit of Spark
1313
* @param spark Spark to check
1414
* @return Current limit that is currently set
1515
*/
16-
public static int getSmartCurrentLimit(CANSparkBase spark) {
16+
public static int getSmartCurrentStallLimit(CANSparkBase spark) {
1717
return CANSparkMaxJNI.c_SparkMax_GetSmartCurrentStallLimit(spark.sparkMaxHandle);
1818
}
1919

20+
/**
21+
* Get current free limit of Spark
22+
* @param spark Spark to check
23+
* @return Current limit that is currently set
24+
*/
25+
public static int getSmartCurrentFreeLimit(CANSparkBase spark) {
26+
return CANSparkMaxJNI.c_SparkMax_GetSmartCurrentFreeLimit(spark.sparkMaxHandle);
27+
}
28+
29+
/**
30+
* Get current limit RPM of Spark
31+
* @param spark Spark to check
32+
* @return Current limit that is currently set
33+
*/
34+
public static int getSmartCurrentLimitRPM(CANSparkBase spark) {
35+
return CANSparkMaxJNI.c_SparkMax_GetSmartCurrentLimitRPM(spark.sparkMaxHandle);
36+
}
37+
38+
/**
39+
* Get the secondary limit cycles of Spark, which is also the number of chop cycles
40+
* @param spark Spark to check
41+
* @return Current limit that is currently set
42+
*/
43+
public static int getSecondaryCurrentLimitCycles(CANSparkBase spark) {
44+
return CANSparkMaxJNI.c_SparkMax_GetSecondaryCurrentLimitCycles(spark.sparkMaxHandle);
45+
}
46+
47+
/**
48+
* Get the secondary current limit of Spark
49+
* @param spark Spark to check
50+
* @return Current limit that is currently set
51+
*/
52+
public static float getSecondaryCurrentLimit(CANSparkBase spark) {
53+
return CANSparkMaxJNI.c_SparkMax_GetSecondaryCurrentLimit(spark.sparkMaxHandle);
54+
}
55+
2056
/** Enable center aligned mode for the duty cycle sensor. */
2157
public static REVLibError enableCenterAlignedMode(CANSparkBase spark) {
2258
return REVLibError.fromInt(

src/main/java/org/lasarobotics/hardware/revrobotics/Spark.java

Lines changed: 127 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@
4343
import edu.wpi.first.math.filter.Debouncer;
4444
import edu.wpi.first.math.system.plant.DCMotor;
4545
import edu.wpi.first.math.trajectory.TrapezoidProfile;
46+
import edu.wpi.first.units.Angle;
4647
import edu.wpi.first.units.Current;
4748
import edu.wpi.first.units.Measure;
4849
import edu.wpi.first.units.Time;
4950
import edu.wpi.first.units.Units;
51+
import edu.wpi.first.units.Velocity;
5052
import edu.wpi.first.units.Voltage;
5153
import edu.wpi.first.util.sendable.Sendable;
5254
import edu.wpi.first.util.sendable.SendableBuilder;
@@ -154,7 +156,8 @@ public static class SparkInputs {
154156
private static final String ARB_FF_LOG_ENTRY = "/ArbitraryFF";
155157
private static final String ARB_FF_UNITS_LOG_ENTRY = "/ArbitraryFFUnits";
156158
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";
158161
private static final String TEMPERATURE_LOG_ENTRY = "/Temperature";
159162
private static final String MOTION_LOG_ENTRY = "/SmoothMotion";
160163
private static final Measure<Time> DEFAULT_STATUS_FRAME_PERIOD = Units.Milliseconds.of(20.0);
@@ -604,7 +607,8 @@ protected void periodic() {
604607

605608
handleSmoothMotion();
606609

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());
608612
Logger.recordOutput(m_id.name + MOTION_LOG_ENTRY, m_isSmoothMotionEnabled);
609613

610614
if (getMotorType() == MotorType.kBrushed) return;
@@ -1423,13 +1427,120 @@ public REVLibError setIdleMode(IdleMode mode) {
14231427
* @param limit The desired current limit
14241428
*/
14251429
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!"
14311543
);
1432-
return status;
14331544
}
14341545

14351546
/**
@@ -1482,6 +1593,14 @@ public REVLibError setClosedLoopRampRate(Measure<Time> rampTime) {
14821593
return m_spark.setClosedLoopRampRate(rampTime.in(Units.Seconds));
14831594
}
14841595

1596+
/**
1597+
* Spark approximate input current
1598+
* @return
1599+
*/
1600+
public Measure<Current> getInputCurrent() {
1601+
return getOutputCurrent().times(m_spark.getAppliedOutput());
1602+
}
1603+
14851604
/**
14861605
* Spark output current
14871606
* @return Output current

0 commit comments

Comments
 (0)