diff --git a/source/docs/software/hardware-apis/misc/addressable-leds.rst b/source/docs/software/hardware-apis/misc/addressable-leds.rst index f362c7c36a..75a8486d59 100644 --- a/source/docs/software/hardware-apis/misc/addressable-leds.rst +++ b/source/docs/software/hardware-apis/misc/addressable-leds.rst @@ -1,25 +1,51 @@ -# Addressable LEDs +# Addressable LEDs -LED strips have been commonly used by teams for several years for a variety of reasons. They allow teams to debug robot functionality from the audience, provide a visual marker for their robot, and can simply add some visual appeal. WPILib has an API for controlling WS2812, WS2812B, and WS2815 LEDs with their data pin connected via :term:`PWM`. +Addressable LEDs are widely used by teams for debugging, visual markers, and aesthetic appeal. -.. note:: LEDs can be controlled through this API while the robot is disabled. +WPILib provides an API for controlling WS2811, WS2812B, SK6812, and other LEDs that use similar protocols, often called NeoPixels, without the need for an external LED controller. -.. important:: The roboRIO can only control **one** ``AddressableLED`` object at a time through its PWM ports. Attempting to create multiple ``AddressableLED`` objects will result in a HAL allocation error. If you need to control multiple physical LED strips, you have several options: +Commonly they are in strips, but bars, circles, matrices, and other form factors are also available. These LEDs are individually controllable, allowing for a wide variety of patterns and effects. - - **Daisy-chain strips in series**: Connect multiple LED strips end-to-end as a single long strip, then use :ref:`buffer views ` to control different sections independently - - **Use PWM Y-cables**: If you need identical patterns on multiple strips, use PWM Y-cables to send the same signal to multiple strips simultaneously +These LEDs can be controlled even when the robot is disabled. Systemcore supports multiple addressable LED products simultaneously, unlike the roboRIO. -.. seealso:: For detailed information about powering and best practices for addressable LEDs, see the [Adafruit NeoPixel Überguide](https://learn.adafruit.com/adafruit-neopixel-uberguide/powering-neopixels). +## Supported LEDs -.. warning:: WS2812B LEDs are designed for 5V, but roboRIO PWM/Servo ports output 6V. While the LEDs will function, this may reduce their lifespan. Consider using a voltage regulator or level shifter if longevity is a concern. +This library supports only WS2812B-compliant LEDs. LEDs that do not follow the timings below may not work correctly. For example, WS2815 and DotStar LEDs are not supported. + +.. collapse:: Timing details + + - T0H: 375ns + - T0L: 875ns + - T1H: 750ns + - T1L: 500ns + +## Wiring and Power + +Wiring addressable LEDs is simple: connect the LED DATA pin to the SIGNAL pin of a SMART I/O connector, with power and ground connected to a good-quality external 5V regulator. + +.. seealso:: For more detailed information about powering and best practices for addressable LEDs, see the `Adafruit NeoPixel Überguide `_. + +### Signal + +WS281x LEDs are designed for **5V** logic, but Systemcore ports output **3.3V** logic. A logic level shifter, like the `Adafruit Pixel Shifter `_, is necessary if there is flickering or incorrect behavior. + +If you have a lot of LEDs, a 300-500 Ohm data line resistor and a 1000 µF capacitor across the power pins are recommended. Too much resistance (>500 Ohm) however, can degrade the signal and cause flickering or communication failures. Power may need to be `distributed throughout the strip `_. + +### Power + +Use a **good-quality, appropriately sized external 5V regulator** (e.g. `Redux Zinc-V+ `_ or `Pololu S13VxF5 `_) to power the LEDs, ensuring the grounds on Systemcore and the regulator are tied together. + +Avoid generic, no-name regulators as they often cannot handle voltage spikes from robot motors, may lack sufficient current capacity for addressable LEDs, and tend to fail prematurely. + +The CTRE VRM can be used if your team already has one, but it is not recommended to purchase one specifically for LED power. Its 5V outputs share a combined 2A current limit across both channels, so it is only suitable for a small number of LEDs. ## Instantiating the AddressableLED Object -You first create an ``AddressableLED`` object that takes the PWM port as an argument. It *must* be a PWM header on the roboRIO. Then you set the number of LEDs located on your LED strip, which can be done with the ``setLength()`` function. +You first create an ``AddressableLED`` object that takes the SMART I/O port (0-5) as an argument. Then you set the number of LEDs that are connected, which can be done with the ``setLength()`` function. .. warning:: It is important to note that setting the length of the LED header is an expensive task and it's **not** recommended to run this periodically. -After the length of the strip has been set, you'll have to create an ``AddressableLEDBuffer`` object that takes the number of LEDs as an input. You'll then call ``myAddressableLed.setData(myAddressableLEDBuffer)`` to set the led output data. Finally, you can call ``myAddressableLed.start()`` to write the output continuously. Below is a full example of the initialization process. +After the length of the strip has been set, you'll have to create an ``AddressableLEDBuffer`` object that takes the number of LEDs as an input. You'll then call ``myAddressableLed.setData(myAddressableLEDBuffer)`` to set the LED output data. Finally, you can call ``myAddressableLed.start()`` to write the output continuously. Below is a full example of the initialization process. .. note:: C++ does not have an AddressableLEDBuffer, and instead uses an Array. @@ -28,69 +54,79 @@ After the length of the strip has been set, you'll have to create an ``Addressab .. tab-item:: Java :sync: Java - .. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2027.0.0-alpha-1/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Robot.java - :language: java - :lines: 32-47 - :lineno-match: + .. code-block:: java + + // Use SMART I/O port 0 for the LED data signal. + AddressableLED m_led = new AddressableLED(0); + + // Set the number of LEDs in the strip. + AddressableLEDBuffer m_ledBuffer = new AddressableLEDBuffer(60); + m_led.setLength(m_ledBuffer.getLength()); + + // Write data and start output. + m_led.setData(m_ledBuffer); + m_led.start(); .. tab-item:: C++ :sync: C++ - .. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2027.0.0-alpha-1/wpilibcExamples/src/main/cpp/examples/AddressableLED/include/Robot.h - :language: c++ - :lines: 12-12, 18-27 - :linenos: - :lineno-start: 12 + .. code-block:: c++ - .. remoteliteralinclude:: https://raw.githubusercontent.com/wpilibsuite/allwpilib/v2027.0.0-alpha-1/wpilibcExamples/src/main/cpp/examples/AddressableLED/cpp/Robot.cpp - :language: c++ - :lines: 7-13 - :lineno-match: + // Use SMART I/O port 0 for the LED data signal. + frc::AddressableLED m_led{0}; + + // Set the number of LEDs in the strip. + std::array m_ledBuffer; + m_led.SetLength(m_ledBuffer.size()); + + // Write data and start output. + m_led.SetData(m_ledBuffer); + m_led.Start(); ## Controlling Sections of an LED Strip -The roboRIO can only control a single addressable LED output at a time, but there are often multiple physical LED strips daisy-chained around a robot, or a single flexible LED strip wrapped around structures on a robot. Individual sections can be accessed in Java using ``AddressableLEDBufferView``. Buffer views behave like subsections of the larger buffer, and can be accessed using indices in the typical [0, length) range. They can also be reversed, to allow for parallel serpentine sections to be animated in the same physical orientation (i.e. both sections would animate "forward" in the same direction, even if the strips are physically tip-to-tail). +Individual sections can be accessed in Java using ``AddressableLEDBufferView``. Buffer views behave like subsections of the larger buffer, and can be accessed using indices in the typical [0, length) range. They can also be reversed, to allow for parallel serpentine sections to be animated in the same physical orientation (i.e. both sections would animate "forward" in the same direction, even if the strips are physically tip-to-tail). .. tab-set:: .. tab-item:: Java :sync: Java - ```Java - // Create the buffer - AddressableLEDBuffer m_buffer = new AddressableLEDBuffer(120); + .. code-block:: java + + // Create the buffer + AddressableLEDBuffer m_buffer = new AddressableLEDBuffer(120); - // Create the view for the section of the strip on the left side of the robot. - // This section spans LEDs from index 0 through index 59, inclusive. - AddressableLEDBufferView m_left = m_buffer.createView(0, 59); + // Create the view for the section of the strip on the left side of the robot. + // This section spans LEDs from index 0 through index 59, inclusive. + AddressableLEDBufferView m_left = m_buffer.createView(0, 59); - // The section of the strip on the right side of the robot. - // This section spans LEDs from index 60 through index 119, inclusive. - // This view is reversed to cancel out the serpentine arrangement of the - // physical LED strip on the robot. - AddressableLEDBufferView m_right = m_buffer.createView(60, 119).reversed(); - ``` + // The section of the strip on the right side of the robot. + // This section spans LEDs from index 60 through index 119, inclusive. + // This view is reversed to cancel out the serpentine arrangement of the + // physical LED strip on the robot. + AddressableLEDBufferView m_right = m_buffer.createView(60, 119).reversed(); .. tab-item:: C++ :sync: C++ - ```C++ - // Create the buffer - std::array m_buffer; + .. code-block:: c++ - // Create the view for the section of the strip on the left side of the robot. - // This section spans LEDs from index 0 through index 59, inclusive. - std::view m_left = - std::ranges::take_view(m_buffer, 60); + // Create the buffer + std::array m_buffer; - // The section of the strip on the right side of the robot. - // This section spans LEDs from index 60 through index 119, inclusive. - // This view is reversed to cancel out the serpentine arrangement of the - // physical LED strip on the robot. - std::view m_right = - std::ranges::reverse_view( - std::ranges::drop_view(m_buffer, 60)); - ``` + // Create the view for the section of the strip on the left side of the robot. + // This section spans LEDs from index 0 through index 59, inclusive. + std::view m_left = + std::ranges::take_view(m_buffer, 60); + + // The section of the strip on the right side of the robot. + // This section spans LEDs from index 60 through index 119, inclusive. + // This view is reversed to cancel out the serpentine arrangement of the + // physical LED strip on the robot. + std::view m_right = + std::ranges::reverse_view( + std::ranges::drop_view(m_buffer, 60)); ## LED Patterns @@ -101,30 +137,30 @@ The ``LEDPattern`` API simplifies setting LED data. Rather than needing to manua .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that sets the entire strip to solid red - LEDPattern red = LEDPattern.solid(Color.kRed); + .. code-block:: java + + // Create an LED pattern that sets the entire strip to solid red + LEDPattern red = LEDPattern.solid(Color.kRed); - // Apply the LED pattern to the data buffer - red.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + red.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that sets the entire strip to solid red - LEDPattern red = LEDPattern.Solid(Color::kRed); + .. code-block:: c++ - // Apply the LED pattern to the data buffer - red.ApplyTo(m_ledBuffer); + // Create an LED pattern that sets the entire strip to solid red + LEDPattern red = LEDPattern.Solid(Color::kRed); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + red.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); ### Creating a Rainbow Effect @@ -191,7 +227,7 @@ Now that the rainbow pattern is defined, we only need to apply it. .. image:: images/discontinuous-gradient.png :width: 900 -### Controlling when patterns are applied +### Controlling When Patterns Are Applied Use commands. The command framework is specifically built for managing when actions run and stop, and prevents multiple actions from running simultaneously. @@ -200,93 +236,93 @@ Use commands. The command framework is specifically built for managing when acti .. tab-item:: Java :sync: Java - ```Java - public class LEDSubsystem extends SubsystemBase { - private static final int kPort = 9; - private static final int kLength = 120; - - private final AddressableLED m_led; - private final AddressableLEDBuffer m_buffer; - - public LEDSubsystem() { - m_led = new AddressableLED(kPort); - m_buffer = new AddressableLEDBuffer(kLength); - m_led.setLength(kLength); - m_led.start(); - - // Set the default command to turn the strip off, otherwise the last colors written by - // the last command to run will continue to be displayed. - // Note: Other default patterns could be used instead! - setDefaultCommand(runPattern(LEDPattern.solid(Color.kBlack)).withName("Off")); - } - - @Override - public void periodic() { - // Periodically send the latest LED color data to the LED strip for it to display - m_led.setData(m_buffer); - } - - /** - * Creates a command that runs a pattern on the entire LED strip. - * - * @param pattern the LED pattern to run - */ - public Command runPattern(LEDPattern pattern) { - return run(() -> pattern.applyTo(m_buffer)); - } - } - ``` + .. code-block:: java + + public class LEDSubsystem extends SubsystemBase { + private static final int kPort = 9; + private static final int kLength = 120; + + private final AddressableLED m_led; + private final AddressableLEDBuffer m_buffer; + + public LEDSubsystem() { + m_led = new AddressableLED(kPort); + m_buffer = new AddressableLEDBuffer(kLength); + m_led.setLength(kLength); + m_led.start(); + + // Set the default command to turn the strip off, otherwise the last colors written by + // the last command to run will continue to be displayed. + // Note: Other default patterns could be used instead! + setDefaultCommand(runPattern(LEDPattern.solid(Color.kBlack)).withName("Off")); + } + + @Override + public void periodic() { + // Periodically send the latest LED color data to the LED strip for it to display + m_led.setData(m_buffer); + } + + /** + * Creates a command that runs a pattern on the entire LED strip. + * + * @param pattern the LED pattern to run + */ + public Command runPattern(LEDPattern pattern) { + return run(() -> pattern.applyTo(m_buffer)); + } + } .. tab-item:: C++ :sync: C++ Header: - ```C++ - class LEDSubsystem : public SubsystemBase { - public: - LEDSubsystem(); - void Periodic() override; + .. code-block:: c++ + + class LEDSubsystem : public SubsystemBase { + public: + LEDSubsystem(); + void Periodic() override; + + frc::CommandPtr RunPattern(frc::LEDPattern pattern); - frc::CommandPtr RunPattern(frc::LEDPattern pattern); + private: + static constexpr int kPort = 9; + static constexpr int kLength = 120; + frc::AddressableLED m_led{kPort}; + std::array m_ledBuffer; + } - private: - static constexpr int kPort = 9; - static constexpr int kLength = 120; - frc::AddressableLED m_led{kPort}; - std::array m_ledBuffer; - } - ``` + .. code-block:: c++ - ```C++ - LEDSubsystem::LEDSubsystem() { - m_led.SetLength(kLength); - m_led.Start(); + LEDSubsystem::LEDSubsystem() { + m_led.SetLength(kLength); + m_led.Start(); - // Set the default command to turn the strip off, otherwise the last colors written by - // the last command to run will continue to be displayed. - // Note: Other default patterns could be used instead! - SetDefaultCommand(RunPattern(frc::LEDPattern::Solid(frc::Color::kBlack)).WithName("Off")); - } + // Set the default command to turn the strip off, otherwise the last colors written by + // the last command to run will continue to be displayed. + // Note: Other default patterns could be used instead! + SetDefaultCommand(RunPattern(frc::LEDPattern::Solid(frc::Color::kBlack)).WithName("Off")); + } - LEDSubsystem::Periodic() { - // Periodically send the latest LED color data to the LED strip for it to display - m_led.SetData(m_ledBuffer); - } + LEDSubsystem::Periodic() { + // Periodically send the latest LED color data to the LED strip for it to display + m_led.SetData(m_ledBuffer); + } - frc::CommandPtr LEDSubsystem::RunPattern(frc::LEDPattern pattern) { - // std::move is necessary for inline pattern declarations to work - // Otherwise we could have a use-after-free! - return Run([this, pattern = std::move(pattern)] { pattern.ApplyTo(m_buffer); }); - } - ``` + frc::CommandPtr LEDSubsystem::RunPattern(frc::LEDPattern pattern) { + // std::move is necessary for inline pattern declarations to work + // Otherwise we could have a use-after-free! + return Run([this, pattern = std::move(pattern)] { pattern.ApplyTo(m_buffer); }); + } -### Basic effects +### Basic Effects The basic effects can all be created from the factory methods declared in the ``LEDPattern`` class -#### Solid color +#### Solid Color .. image:: images/solid.png :alt: A solid red LED pattern @@ -299,30 +335,30 @@ The solid color pattern sets the target LED buffer to a single solid color. .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that sets the entire strip to solid red - LEDPattern red = LEDPattern.solid(Color.kRed); + .. code-block:: java - // Apply the LED pattern to the data buffer - red.applyTo(m_ledBuffer); + // Create an LED pattern that sets the entire strip to solid red + LEDPattern red = LEDPattern.solid(Color.kRed); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + red.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that sets the entire strip to solid red - LEDPattern red = LEDPattern.Solid(Color::kRed); + .. code-block:: c++ + + // Create an LED pattern that sets the entire strip to solid red + LEDPattern red = LEDPattern.Solid(Color::kRed); - // Apply the LED pattern to the data buffer - red.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + red.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Continuous Gradient @@ -337,35 +373,35 @@ The gradient pattern sets the target buffer to display a smooth gradient between .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient. - // The LED strip will be red at both ends and blue in the center, - // with smooth gradients between - LEDPattern gradient = LEDPattern.gradient(LEDPattern.GradientType.kContinuous, Color.kRed, Color.kBlue); + .. code-block:: java - // Apply the LED pattern to the data buffer - gradient.applyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient. + // The LED strip will be red at both ends and blue in the center, + // with smooth gradients between + LEDPattern gradient = LEDPattern.gradient(LEDPattern.GradientType.kContinuous, Color.kRed, Color.kBlue); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + gradient.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient. - // The LED strip will be red at both ends and blue in the center, - // with smooth gradients between - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern gradient = LEDPattern.Gradient(LEDPattern::GradientType::kContinuous, colors); + .. code-block:: c++ + + // Create an LED pattern that displays a red-to-blue gradient. + // The LED strip will be red at both ends and blue in the center, + // with smooth gradients between + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern gradient = LEDPattern.Gradient(LEDPattern::GradientType::kContinuous, colors); - // Apply the LED pattern to the data buffer - gradient.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + gradient.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Discontinuous Gradient @@ -380,33 +416,33 @@ The gradient pattern sets the target buffer to display a smooth gradient between .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient. - // The LED strip will be red at one end and blue at the other. - LEDPattern gradient = LEDPattern.gradient(LEDPattern.GradientType.kDiscontinuous, Color.kRed, Color.kBlue); + .. code-block:: java - // Apply the LED pattern to the data buffer - gradient.applyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient. + // The LED strip will be red at one end and blue at the other. + LEDPattern gradient = LEDPattern.gradient(LEDPattern.GradientType.kDiscontinuous, Color.kRed, Color.kBlue); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + gradient.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient. - // The LED strip will be red at one end and blue at the other. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern gradient = LEDPattern.Gradient(LEDPattern::GradientType::kDiscontinuous, colors); + .. code-block:: c++ + + // Create an LED pattern that displays a red-to-blue gradient. + // The LED strip will be red at one end and blue at the other. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern gradient = LEDPattern.Gradient(LEDPattern::GradientType::kDiscontinuous, colors); - // Apply the LED pattern to the data buffer - gradient.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + gradient.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Steps @@ -425,36 +461,36 @@ Steps are specified as a combination of the *starting position* of that color, a .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays the first half of a strip as solid red, - // and the second half of the strip as solid blue. - LEDPattern steps = LEDPattern.steps(Map.of(0, Color.kRed, 0.5, Color.kBlue)); + .. code-block:: java - // Apply the LED pattern to the data buffer - steps.applyTo(m_ledBuffer); + // Create an LED pattern that displays the first half of a strip as solid red, + // and the second half of the strip as solid blue. + LEDPattern steps = LEDPattern.steps(Map.of(0, Color.kRed, 0.5, Color.kBlue)); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + steps.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays the first half of a strip as solid red, - // and the second half of the strip as solid blue. - std::array, 2> colorSteps{std::pair{0.0, Color::kRed}, - std::pair{0.5, Color::kBlue}}; - LEDPattern steps = LEDPattern.Steps(colorSteps); + .. code-block:: c++ + + // Create an LED pattern that displays the first half of a strip as solid red, + // and the second half of the strip as solid blue. + std::array, 2> colorSteps{std::pair{0.0, Color::kRed}, + std::pair{0.5, Color::kBlue}}; + LEDPattern steps = LEDPattern.Steps(colorSteps); - // Apply the LED pattern to the data buffer - gradient.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + gradient.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); -#### Progress mask +#### Progress Mask .. only:: html @@ -478,34 +514,34 @@ Slightly different from the basic color patterns, the progress mask pattern gene .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a black-and-white mask that displays the current height of an elevator - // mechanism. This can be combined with other patterns to change the displayed color to something other than white. - LEDPattern pattern = LEDPattern.progressMaskLayer(() -> m_elevator.getHeight() / m_elevator.getMaxHeight()); + .. code-block:: java - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Create an LED pattern that displays a black-and-white mask that displays the current height of an elevator + // mechanism. This can be combined with other patterns to change the displayed color to something other than white. + LEDPattern pattern = LEDPattern.progressMaskLayer(() -> m_elevator.getHeight() / m_elevator.getMaxHeight()); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a black-and-white mask that displays the current height of an elevator - // mechanism. This can be combined with other patterns to change the displayed color to something other than white. - LEDPattern pattern = LEDPattern::ProgressMaskLayer([&]() { return m_elevator.GetHeight() / m_elevator.GetMaxHeight(); }); + .. code-block:: c++ + + // Create an LED pattern that displays a black-and-white mask that displays the current height of an elevator + // mechanism. This can be combined with other patterns to change the displayed color to something other than white. + LEDPattern pattern = LEDPattern::ProgressMaskLayer([&]() { return m_elevator.GetHeight() / m_elevator.GetMaxHeight(); }); - // Apply the LED pattern to the data buffer - pattern.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); -### Modifying effects +### Modifying Effects Basic LED patterns can be combined with modifier effects to create new patterns with a combination of effects. Multiple modifiers can be used together to create complex patterns. @@ -524,35 +560,35 @@ Offsets can be used to bias patterns forward of backward by a certain number of .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient, offset 40 pixels forward. - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern pattern = base.offsetBy(40); - LEDPattern negative = base.offsetBy(-20); // Equivalent to the above when applied to a 60-LED buffer + .. code-block:: java - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient, offset 40 pixels forward. + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern pattern = base.offsetBy(40); + LEDPattern negative = base.offsetBy(-20); // Equivalent to the above when applied to a 60-LED buffer - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient, offset 40 pixels forward. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern pattern = base.OffsetBy(40); - LEDPattern negative = base.OffsetBy(-20); // Equivalent to the above when applied to a 60-LED buffer + .. code-block:: c++ + + // Create an LED pattern that displays a red-to-blue gradient, offset 40 pixels forward. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern pattern = base.OffsetBy(40); + LEDPattern negative = base.OffsetBy(-20); // Equivalent to the above when applied to a 60-LED buffer - // Apply the LED pattern to the data buffer - heightDisplay.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + heightDisplay.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Reverse @@ -567,33 +603,33 @@ Patterns and animations can be reversed to flip the direction that patterns are .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient, then reverse it so it displays blue-to-red. - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern pattern = base.reversed(); + .. code-block:: java - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient, then reverse it so it displays blue-to-red. + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern pattern = base.reversed(); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient, then reverse it so it displays blue-to-red. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern pattern = base.Reversed(); + .. code-block:: c++ + + // Create an LED pattern that displays a red-to-blue gradient, then reverse it so it displays blue-to-red. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern pattern = base.Reversed(); - // Apply the LED pattern to the data buffer - heightDisplay.ApplyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + heightDisplay.ApplyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Scroll @@ -629,38 +665,38 @@ Scrolling can be controlled in two different ways: either at a speed as a functi .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient, then scroll at one quarter of the LED strip's length per second. - // For a half-meter length of a 120 LED-per-meter strip, this is equivalent to scrolling at 12.5 centimeters per second. - Distance ledSpacing = Meters.of(1 / 120.0); - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern pattern = base.scrollAtRelativeSpeed(Percent.per(Second).of(25)); - LEDPattern absolute = base.scrollAtAbsoluteSpeed(Centimeters.per(Second).of(12.5), ledSpacing); + .. code-block:: java + + // Create an LED pattern that displays a red-to-blue gradient, then scroll at one quarter of the LED strip's length per second. + // For a half-meter length of a 120 LED-per-meter strip, this is equivalent to scrolling at 12.5 centimeters per second. + Distance ledSpacing = Meters.of(1 / 120.0); + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern pattern = base.scrollAtRelativeSpeed(Percent.per(Second).of(25)); + LEDPattern absolute = base.scrollAtAbsoluteSpeed(Centimeters.per(Second).of(12.5), ledSpacing); - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient, then scroll at one quarter of the LED strip's length per second. - // For a half-meter length of a 120 LED-per-meter strip, this is equivalent to scrolling at 12.5 centimeters per second. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern pattern = base.ScrollAtRelativeSpeed(units::hertz_t{0.25}); - LEDPattern absolute = base.ScrollAtAbsoluteSpeed(0.125_mps, units::meter_t{1/120.0}); + .. code-block:: c++ - // Apply the LED pattern to the data buffer - heightDisplay.ApplyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient, then scroll at one quarter of the LED strip's length per second. + // For a half-meter length of a 120 LED-per-meter strip, this is equivalent to scrolling at 12.5 centimeters per second. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern pattern = base.ScrollAtRelativeSpeed(units::hertz_t{0.25}); + LEDPattern absolute = base.ScrollAtAbsoluteSpeed(0.125_mps, units::meter_t{1/120.0}); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + heightDisplay.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Breathe @@ -686,33 +722,33 @@ A breathing modifier will make the base pattern brighten and dim in a sinusoidal .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient, breathing at a 2 second period (0.5 Hz) - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern pattern = base.breathe(Seconds.of(2)); + .. code-block:: java + + // Create an LED pattern that displays a red-to-blue gradient, breathing at a 2 second period (0.5 Hz) + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern pattern = base.breathe(Seconds.of(2)); - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient, breathing at a 2 second period (0.5 Hz) - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern pattern = base.Breathe(2_s); + .. code-block:: c++ - // Apply the LED pattern to the data buffer - heightDisplay.ApplyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient, breathing at a 2 second period (0.5 Hz) + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern pattern = base.Breathe(2_s); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + heightDisplay.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Blink @@ -753,49 +789,49 @@ Blinking can be done in one of three ways: .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient, blinking at various rates. - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + .. code-block:: java + + // Create an LED pattern that displays a red-to-blue gradient, blinking at various rates. + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - // 1.5 seconds on, 1.5 seconds off, for a total period of 3 seconds - LEDPattern pattern = base.blink(Seconds.of(1.5)); + // 1.5 seconds on, 1.5 seconds off, for a total period of 3 seconds + LEDPattern pattern = base.blink(Seconds.of(1.5)); - // 2 seconds on, 1 second off, for a total period of 3 seconds - LEDPattern asymmetric = base.blink(Seconds.of(2), Seconds.of(1)); + // 2 seconds on, 1 second off, for a total period of 3 seconds + LEDPattern asymmetric = base.blink(Seconds.of(2), Seconds.of(1)); - // Turn the base pattern on when the RSL is on, and off when the RSL is off - LEDPattern sycned = base.synchronizedBlink(RobotController::getRSLState); + // Turn the base pattern on when the RSL is on, and off when the RSL is off + LEDPattern sycned = base.synchronizedBlink(RobotController::getRSLState); - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient, blinking at various rates. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + .. code-block:: c++ - // 1.5 seconds on, 1.5 seconds off, for a total period of 3 seconds - LEDPattern pattern = base.Blink(1.5_s); + // Create an LED pattern that displays a red-to-blue gradient, blinking at various rates. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - // 2 seconds on, 1 second off, for a total period of 3 seconds - LEDPattern asymmetric = base.Blink(2_s, 1_s)); + // 1.5 seconds on, 1.5 seconds off, for a total period of 3 seconds + LEDPattern pattern = base.Blink(1.5_s); - // Turn the base pattern on when the RSL is on, and off when the RSL is off - LEDPattern sycned = base.SynchronizedBlink([]() { return RobotController.GetRSLState(); }); + // 2 seconds on, 1 second off, for a total period of 3 seconds + LEDPattern asymmetric = base.Blink(2_s, 1_s)); - // Apply the LED pattern to the data buffer - pattern.ApplyTo(m_ledBuffer); + // Turn the base pattern on when the RSL is on, and off when the RSL is off + LEDPattern sycned = base.SynchronizedBlink([]() { return RobotController.GetRSLState(); }); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Brightness @@ -812,35 +848,35 @@ Patterns can be brightened and dimmed relative to their original brightness; a b .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient at half brightness - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern pattern = base.atBrightness(Percent.of(50)); + .. code-block:: java + + // Create an LED pattern that displays a red-to-blue gradient at half brightness + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern pattern = base.atBrightness(Percent.of(50)); - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient at half brightness - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern pattern = base.AtBrightness(0.5); + .. code-block:: c++ - // Apply the LED pattern to the data buffer - pattern.ApplyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient at half brightness + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern pattern = base.AtBrightness(0.5); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.ApplyTo(m_ledBuffer); -### Combinatory effects + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); + +### Combinatory Effects Complex LED patterns are built up from combining simple base patterns (such as solid colors or gradients) with animating effects (such as scrolling or breathing) and combinatory effects (like masks and overlays). Multiple effects can be combined at once, like in the scrolling rainbow effect above that takes a basic base effect - a static rainbow - and then adds a scrolling effect to it. @@ -868,41 +904,41 @@ Masks work by combining the RGB values of two patterns and keeping only the valu .. tab-item:: Java :sync: Java - ```Java - // Create an LED pattern that displays a red-to-blue gradient at a variable length - // depending on the relative position of the elevator. The blue end of the gradient - // will only be shown when the elevator gets close to its maximum height; otherwise, - // that end will be solid black when the elevator is at lower heights. - LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); - LEDPattern mask = LEDPattern.progressMaskLayer(() -> m_elevator.getHeight() / m_elevator.getMaxHeight()); - LEDPattern heightDisplay = base.mask(mask); + .. code-block:: java + + // Create an LED pattern that displays a red-to-blue gradient at a variable length + // depending on the relative position of the elevator. The blue end of the gradient + // will only be shown when the elevator gets close to its maximum height; otherwise, + // that end will be solid black when the elevator is at lower heights. + LEDPattern base = LEDPattern.discontinuousGradient(Color.kRed, Color.kBlue); + LEDPattern mask = LEDPattern.progressMaskLayer(() -> m_elevator.getHeight() / m_elevator.getMaxHeight()); + LEDPattern heightDisplay = base.mask(mask); - // Apply the LED pattern to the data buffer - heightDisplay.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + heightDisplay.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - // Create an LED pattern that displays a red-to-blue gradient at a variable length - // depending on the relative position of the elevator. The blue end of the gradient - // will only be shown when the elevator gets close to its maximum height; otherwise, - // that end will be solid black when the elevator is at lower heights. - std::array colors{Color::kRed, Color::kBlue}; - LEDPattern base = LEDPattern::DiscontinuousGradient(colors); - LEDPattern mask = LEDPattern::ProgressMaskLayer([&]() { m_elevator.GetHeight() / m_elevator.GetMaxHeight() }); - LEDPattern heightDisplay = base.Mask(mask); + .. code-block:: c++ - // Apply the LED pattern to the data buffer - heightDisplay.ApplyTo(m_ledBuffer); + // Create an LED pattern that displays a red-to-blue gradient at a variable length + // depending on the relative position of the elevator. The blue end of the gradient + // will only be shown when the elevator gets close to its maximum height; otherwise, + // that end will be solid black when the elevator is at lower heights. + std::array colors{Color::kRed, Color::kBlue}; + LEDPattern base = LEDPattern::DiscontinuousGradient(colors); + LEDPattern mask = LEDPattern::ProgressMaskLayer([&]() { m_elevator.GetHeight() / m_elevator.GetMaxHeight() }); + LEDPattern heightDisplay = base.Mask(mask); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + heightDisplay.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); .. only:: html @@ -920,46 +956,46 @@ Masks work by combining the RGB values of two patterns and keeping only the valu .. image:: images/rainbow.png :width: 900 -Masks can also be animated (see :ref:`progressMask `). Masking a base pattern with a scrolling pattern will result in a panning effect. The animation above was generated by masking a rainbow pattern with a scrolling white/black pattern +Masks can also be animated (see :ref:`progressMask `). Masking a base pattern with a scrolling pattern will result in a panning effect. The animation above was generated by masking a rainbow pattern with a scrolling white/black pattern .. tab-set:: .. tab-item:: Java :sync: Java - ```Java - Map maskSteps = Map.of(0, Color.kWhite, 0.5, Color.kBlack); - LEDPattern base = LEDPattern.rainbow(255, 255); - LEDPattern mask = - LEDPattern.steps(maskSteps).scrollAtRelativeSpeed(Percent.per(Second).of(0.25)); + .. code-block:: java + + Map maskSteps = Map.of(0, Color.kWhite, 0.5, Color.kBlack); + LEDPattern base = LEDPattern.rainbow(255, 255); + LEDPattern mask = + LEDPattern.steps(maskSteps).scrollAtRelativeSpeed(Percent.per(Second).of(0.25)); - LEDPattern pattern = base.mask(mask); + LEDPattern pattern = base.mask(mask); - // Apply the LED pattern to the data buffer - pattern.applyTo(m_ledBuffer); + // Apply the LED pattern to the data buffer + pattern.applyTo(m_ledBuffer); - // Write the data to the LED strip - m_led.setData(m_ledBuffer); - ``` + // Write the data to the LED strip + m_led.setData(m_ledBuffer); .. tab-item:: C++ :sync: C++ - ```C++ - std::array, 2> maskSteps{std::pair{0.0, Color::kWhite}, - std::pair{0.5, Color::kBlack}}; - LEDPattern base = LEDPattern::Rainbow(255, 255); - LEDPattern mask = - LEDPattern::Steps(maskSteps).ScrollAtRelativeSpeed(units::hertz_t{0.25}); + .. code-block:: c++ - LEDPattern pattern = base.Mask(mask); + std::array, 2> maskSteps{std::pair{0.0, Color::kWhite}, + std::pair{0.5, Color::kBlack}}; + LEDPattern base = LEDPattern::Rainbow(255, 255); + LEDPattern mask = + LEDPattern::Steps(maskSteps).ScrollAtRelativeSpeed(units::hertz_t{0.25}); - // Apply the LED pattern to the data buffer - pattern.ApplyTo(m_ledBuffer); + LEDPattern pattern = base.Mask(mask); - // Write the data to the LED strip - m_led.SetData(m_ledBuffer); - ``` + // Apply the LED pattern to the data buffer + pattern.ApplyTo(m_ledBuffer); + + // Write the data to the LED strip + m_led.SetData(m_ledBuffer); #### Overlay @@ -973,11 +1009,11 @@ Blends will combine the output colors of patterns together, by averaging out the ``LEDPattern`` is an easy and convenient way of controlling LEDs, but direct access to the LED colors is sometimes needed for custom patterns and animations. -Color can be set to an individual led on the strip using two methods: ``setRGB()``, which takes RGB values as an input, and ``setHSV()``, which takes HSV values as an input. Low-level access is typically done with an indexed for-loop that iterates over each LED index of the section to control. This method can be used for both ``AddressableLEDBuffer`` and ``AddressableLEDBufferView`` objects in Java, and for ``std::span`` for C++. +Color can be set to an individual LED on the strip using two methods: ``setRGB()``, which takes RGB values as an input, and ``setHSV()``, which takes HSV values as an input. Low-level access is typically done with an indexed for-loop that iterates over each LED index of the section to control. This method can be used for both ``AddressableLEDBuffer`` and ``AddressableLEDBufferView`` objects in Java, and for ``std::span`` for C++. .. note:: RGB stands for Red, Green, and Blue. This is a fairly common color model as it's quite easy to understand, and it corresponds with a typical LED configuration that's comprised of one red, one green, and one blue sub-LED. LEDs can be set with the ``setRGB`` method that takes 4 arguments: index of the LED, amount of red, amount of green, amount of blue. The amount of red, green, and blue are integer values between 0-255. -.. note:: HSV stands for Hue, Saturation, and Value. Hue describes the color or tint, saturation being the amount of gray, and value being the brightness. In WPILib, Hue is an integer from 0 - 180. Saturation and Value are integers from 0 - 255. If you look at a color picker like [Google's](https://www.google.com/search?q=color+picker), Hue will be 0 - 360 and Saturation and Value are from 0% to 100%. This is the same way that OpenCV handles HSV colors. Make sure the HSV values entered to WPILib are correct, or the color produced might not be the same as was expected. +.. note:: HSV stands for Hue, Saturation, and Value. Hue describes the color or tint, saturation being the amount of gray, and value being the brightness. In WPILib, Hue is an integer from 0 - 180. Saturation and Value are integers from 0 - 255. If you look at a color picker like `Google's `_, Hue will be 0 - 360 and Saturation and Value are from 0% to 100%. This is the same way that OpenCV handles HSV colors. Make sure the HSV values entered to WPILib are correct, or the color produced might not be the same as was expected. These examples demonstrate setting an entire LED strip to solid red using the RGB and HSV methods: @@ -986,42 +1022,42 @@ These examples demonstrate setting an entire LED strip to solid red using the RG .. tab-item:: Java (RGB) :sync: Java - ```Java - for (var i = 0; i < m_ledBuffer.getLength(); i++) { - // Sets the specified LED to the RGB values for red - m_ledBuffer.setRGB(i, 255, 0, 0); - } - m_led.setData(m_ledBuffer); - ``` + .. code-block:: java + + for (var i = 0; i < m_ledBuffer.getLength(); i++) { + // Sets the specified LED to the RGB values for red + m_ledBuffer.setRGB(i, 255, 0, 0); + } + m_led.setData(m_ledBuffer); .. tab-item:: C++ (RGB) :sync: C++ - ```C++ - for (int i = 0; i < kLength; i++) { - m_ledBuffer[i].SetRGB(255, 0, 0); - } - m_led.SetData(m_ledBuffer); - ``` + .. code-block:: c++ + + for (int i = 0; i < kLength; i++) { + m_ledBuffer[i].SetRGB(255, 0, 0); + } + m_led.SetData(m_ledBuffer); .. tab-item:: Java (HSV) - ```Java - for (var i = 0; i < m_ledBuffer.getLength(); i++) { - // Sets the specified LED to the HSV values for red - m_ledBuffer.setHSV(i, 0, 100, 100); - } - m_led.setData(m_ledBuffer); - ``` + .. code-block:: java + + for (var i = 0; i < m_ledBuffer.getLength(); i++) { + // Sets the specified LED to the HSV values for red + m_ledBuffer.setHSV(i, 0, 100, 100); + } + m_led.setData(m_ledBuffer); .. tab-item:: C++ (HSV) - ```C++ - for (int i = 0; i < kLength; i++) { - m_ledBuffer[i].SetHSV(0, 100, 100); - } - m_led.SetData(m_ledBuffer); - ``` + .. code-block:: c++ + + for (int i = 0; i < kLength; i++) { + m_ledBuffer[i].SetHSV(0, 100, 100); + } + m_led.SetData(m_ledBuffer); ### Using HSV Values diff --git a/source/redirects.txt b/source/redirects.txt index f72db16c41..1dbad3e828 100644 --- a/source/redirects.txt +++ b/source/redirects.txt @@ -258,6 +258,7 @@ "docs/software/pathplanning/robot-characterization/analyzing-data.rst" "docs/software/pathplanning/system-identification/analyzing-data.rst" "docs/software/pathplanning/robot-characterization/analyzing-feedback.rst" "docs/software/pathplanning/system-identification/analyzing-feedback.rst" "docs/software/pathplanning/robot-characterization/configuring-project.rst" "docs/software/pathplanning/system-identification/configuring-project.rst" +"docs/yearly-overview/2026-game-data.rst" "docs/yearly-overview/index.rst" "docs/software/pathplanning/robot-characterization/characterization-routine.rst" "docs/software/pathplanning/system-identification/identification-routine.rst" "docs/software/pathplanning/robot-characterization/index.rst" "docs/software/pathplanning/system-identification/index.rst" "docs/software/pathplanning/robot-characterization/introduction.rst" "docs/software/pathplanning/system-identification/introduction.rst"