Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6421de4
Add initial AddressableLED subsystem implementation
RobotLeopard86 Feb 25, 2025
fa8e40a
Fix missing imports and improper record access
RobotLeopard86 Feb 25, 2025
8b27e76
Add missing @Override declarations and add Javadoc
RobotLeopard86 Feb 25, 2025
b26a7b9
Merge branch 'main' into addressable-led
RobotLeopard86 Feb 25, 2025
b51bcd3
Merge branch 'main' into addressable-led
RobotLeopard86 Feb 26, 2025
e827996
Address code review feedback for AddressableLED subsystem and add sca…
RobotLeopard86 Feb 27, 2025
fad22db
Add AddressableLED testing command
RobotLeopard86 Feb 27, 2025
74fb53f
Actually apply the patterns for the AddressableLED test
RobotLeopard86 Feb 27, 2025
0cc78fe
Run Spotless!
RobotLeopard86 Feb 27, 2025
40c06ef
Merge branch 'main' into addressable-led
RobotLeopard86 Feb 27, 2025
7f0147c
Add Javadocs for AddressableLED subsystem
RobotLeopard86 Feb 27, 2025
13ba9fe
Merge branch 'addressable-led' of https://github.com/redshiftrobotics…
RobotLeopard86 Feb 27, 2025
6cf0918
Clarify separation between Blinkin and AddressableLED subsystems
RobotLeopard86 Mar 1, 2025
fd39f56
Main -> addressable-led merge
RobotLeopard86 Mar 1, 2025
e9c44d4
Fix Wrist build error resulting from main merge
RobotLeopard86 Mar 1, 2025
d3c6e7b
Add superstructure LED patterns
RobotLeopard86 Mar 1, 2025
9efff02
Fix errors
RobotLeopard86 Mar 1, 2025
650ee6b
Merge branch 'main' into addressable-led
RobotLeopard86 Mar 1, 2025
79bca46
Remove redundant null check
RobotLeopard86 Mar 1, 2025
0b9126f
Add appropriate Javadoc for subsystem
RobotLeopard86 Mar 1, 2025
ebcae4c
Run autoformatting
bforcum Mar 1, 2025
cead75c
Refactor LED pattern manipulation to be within subsystems instead of …
RobotLeopard86 Mar 1, 2025
e6fedd3
Merge branch 'main' into addressable-led
MichaelLesirge Mar 4, 2025
8fcde4c
Merge branch 'main' into addressable-led
MichaelLesirge Mar 4, 2025
b5dda59
fix build
MichaelLesirge Mar 4, 2025
d3ffd09
Merge branch 'main' into addressable-led
AceiusRedshift Mar 12, 2025
21a0484
fix
AceiusRedshift Mar 12, 2025
f2ed688
Integrate LEDs into robot container and superstructure
AceiusRedshift Mar 12, 2025
ed4e9b5
ok good enough
AceiusRedshift Mar 12, 2025
ea88276
Merge branch 'main' into addressable-led
RobotLeopard86 Mar 13, 2025
b545f59
Fix incorrect AddressableLED test end check and clarify Range record …
RobotLeopard86 Mar 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/main/java/frc/robot/commands/SetAddressableLEDPattern.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package frc.robot.commands;

import edu.wpi.first.wpilibj.LEDPattern;
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.addressableled.AddressableLEDSubsystem;

public class SetAddressableLEDPattern extends Command {
private final AddressableLEDSubsystem ledSystem;

/**
* @apiNote If this is -1, that means that this command is targeting the whole strip
*/
private final int section;

private final LEDPattern pattern;

/**
* @param led Addressable LED subsystem to use
* @param pattern Pattern to apply when command run
* @param section Section of LED strip to apply pattern to (index into
* AddressableLEDConstants.SECTIONS)
*/
public SetAddressableLEDPattern(
AddressableLEDSubsystem ledSystem, LEDPattern pattern, int section) {
this.section = section;
this.pattern = pattern;
this.ledSystem = ledSystem;
addRequirements(ledSystem);
}

/**
* @param led Addressable LED subsystem to use
* @param pattern Pattern to apply when command run
*/
public SetAddressableLEDPattern(AddressableLEDSubsystem ledSystem, LEDPattern pattern) {
section = -1;
this.pattern = pattern;
this.ledSystem = ledSystem;
addRequirements(ledSystem);
}

@Override
public void execute() {
if (section < 0) {
ledSystem.applyPattern(pattern);
} else {
ledSystem.applySectionedPattern(pattern, section);
}
}

@Override
public boolean isFinished() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package frc.robot.commands.test;

import static edu.wpi.first.units.Units.MetersPerSecond;
import static edu.wpi.first.units.Units.Seconds;

import edu.wpi.first.wpilibj.LEDPattern;
import edu.wpi.first.wpilibj.util.Color;
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.addressableled.AddressableLEDConstants;
import frc.robot.subsystems.addressableled.AddressableLEDSubsystem;

public class AddressableLEDTestCommand extends Command {
private final AddressableLEDSubsystem ledSystem;
private LEDPattern currentPattern;
private int ticker = 0;
private int testCount = 0;

public AddressableLEDTestCommand(AddressableLEDSubsystem ledSystem) {
this.ledSystem = ledSystem;
addRequirements(ledSystem);
}

@Override
public void initialize() {
ticker = 0;
testCount = 0;
currentPattern =
LEDPattern.rainbow(255, 128)
.scrollAtAbsoluteSpeed(MetersPerSecond.of(1), AddressableLEDConstants.LED_DENSITY);
}

@Override
public void execute() {
if (ticker < 500) {
ticker++;
} else {
ticker = 0;
ledSystem.applySectionedPattern(LEDPattern.kOff, testCount);
testCount++;
if (testCount == AddressableLEDConstants.SECTIONS.length) {
currentPattern = LEDPattern.solid(Color.kLimeGreen).breathe(Seconds.of(2));
ledSystem.applyPattern(currentPattern);
} else {
ledSystem.applySectionedPattern(currentPattern, testCount);
}
}
}

@Override
public boolean isFinished() {
return testCount < (AddressableLEDConstants.SECTIONS.length + 1);
}

@Override
public void end(boolean interrupted) {
ledSystem.applyPattern(LEDPattern.kOff);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package frc.robot.subsystems.addressableled;

import static edu.wpi.first.units.Units.Meters;

import edu.wpi.first.units.measure.Distance;

public class AddressableLEDConstants {
/**
* @param low The lower bound of the range
* @param high The upper bound of the range
*/
public record Range(int low, int high) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does range do? It's not immediately obvious, so there should be a javadoc here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like Aceius said, it's still not clear what the purpose of Range is. The parameters are obvious, so you can remove the javadoc comments for those, but you need to make it clear when and where Range is used. Someone should not have to read through to code and use context to understand the purpose of this


// TODO: Implement real values
public static final int LED_COUNT = 64;
public static final Distance LED_DENSITY = Meters.of(1.0 / LED_COUNT);
public static final int LED_STRIP_PORT = 0;

/**
* @apiNote The lower bound of the range represents the lowest index LED for this section, and the
* upper bound represents the highest index LED
*/
public static final Range SECTIONS[] = {new Range(0, LED_COUNT)};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package frc.robot.subsystems.addressableled;

import edu.wpi.first.wpilibj.AddressableLED;
import edu.wpi.first.wpilibj.AddressableLEDBuffer;
import edu.wpi.first.wpilibj.AddressableLEDBufferView;
import edu.wpi.first.wpilibj.LEDPattern;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

public class AddressableLEDSubsystem extends SubsystemBase {
private final AddressableLED led;
private final AddressableLEDBuffer ledBuffer;
private AddressableLEDBufferView ledViews[];
private LEDPattern[] currentPatterns;

public AddressableLEDSubsystem() {
// Create strip and buffer
led = new AddressableLED(AddressableLEDConstants.LED_STRIP_PORT);
ledBuffer = new AddressableLEDBuffer(AddressableLEDConstants.LED_COUNT);
led.setLength(AddressableLEDConstants.LED_COUNT);

// Create current pattern trackers
currentPatterns = new LEDPattern[AddressableLEDConstants.SECTIONS.length];

// Create section views
ledViews = new AddressableLEDBufferView[AddressableLEDConstants.SECTIONS.length];
for (int i = 0; i < ledViews.length; i++) {
ledViews[i] =
new AddressableLEDBufferView(
ledBuffer,
AddressableLEDConstants.SECTIONS[i].low(),
AddressableLEDConstants.SECTIONS[i].high());
}
}

// Periodically update the LED strip
@Override
public void periodic() {
for (int i = 0; i < ledViews.length; i++) {
currentPatterns[i].applyTo(ledViews[i]);
}
led.setData(ledBuffer);
}

// Apply a color pattern to a section of the LED strip
public void applySectionedPattern(LEDPattern pattern, int section) {
if (section < 0 || section >= ledViews.length) return;
pattern.applyTo(ledViews[section]);
currentPatterns[section] = pattern;
}

// Apply a color pattern to a section of the LED strip
public void applyPattern(LEDPattern pattern) {
pattern.applyTo(ledBuffer);
for (int i = 0; i < currentPatterns.length; i++) {
currentPatterns[i] = pattern;
}
}
}