[wpilib] Add LED pattern API for easily animating addressable LEDs (#6344)

Add LEDReader and LEDWriter helper interfaces to facilitate composing simple patterns into more complex ones, e.g. LEDPattern.solid(Color.kBlue).breathe(Seconds.of(0.75)). Pattern composition relies on changing out the write behavior; for example, offsetBy increments the indexes to write to; while blink will switch between playing a base pattern and turning off all the LEDs.

Add a view class for splitting a single large buffer into smaller distinct sections, which is useful for dealing with long chained LED strips mounted on different parts of a robot. Views cannot be written directly to an LED strip (in fact, trying to do so won't even compile).

Adds some utility methods to the Color class for interpolating between two colors, and support color representations with 32-bit integers to avoid object allocations.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
This commit is contained in:
Sam Carlberg
2024-06-05 22:41:10 -04:00
committed by GitHub
parent 5221069bcc
commit ad18fa62ee
19 changed files with 3610 additions and 311 deletions

View File

@@ -13,27 +13,12 @@ void Robot::RobotInit() {
}
void Robot::RobotPeriodic() {
// Fill the buffer with a rainbow
Rainbow();
// Run the rainbow pattern and apply it to the buffer
m_scrollingRainbow.ApplyTo(m_ledBuffer);
// Set the LEDs
m_led.SetData(m_ledBuffer);
}
void Robot::Rainbow() {
// For every pixel
for (int i = 0; i < kLength; i++) {
// Calculate the hue - hue is easier for rainbows because the color
// shape is a circle so only one value needs to precess
const auto pixelHue = (firstPixelHue + (i * 180 / kLength)) % 180;
// Set the value
m_ledBuffer[i].SetHSV(pixelHue, 255, 128);
}
// Increase by to make the rainbow "move"
firstPixelHue += 3;
// Check bounds
firstPixelHue %= 180;
}
#ifndef RUNNING_FRC_TESTS
int main() {
return frc::StartRobot<Robot>();

View File

@@ -7,11 +7,11 @@
#include <array>
#include <frc/AddressableLED.h>
#include <frc/LEDPattern.h>
#include <frc/TimedRobot.h>
class Robot : public frc::TimedRobot {
public:
void Rainbow();
void RobotInit() override;
void RobotPeriodic() override;
@@ -23,6 +23,16 @@ class Robot : public frc::TimedRobot {
frc::AddressableLED m_led{9};
std::array<frc::AddressableLED::LEDData, kLength>
m_ledBuffer; // Reuse the buffer
// Store what the last hue of the first pixel is
int firstPixelHue = 0;
// Our LED strip has a density of 120 LEDs per meter
units::meter_t kLedSpacing{1 / 120.0};
// Create an LED pattern that will display a rainbow across
// all hues at maximum saturation and half brightness
frc::LEDPattern m_rainbow = frc::LEDPattern::Rainbow(255, 128);
// Create a new pattern that scrolls the rainbow pattern across the LED
// strip, moving at a speed of 1 meter per second.
frc::LEDPattern m_scrollingRainbow =
m_rainbow.ScrollAtAbsoluteSpeed(1_mps, kLedSpacing);
};