LED direccionables
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 LEDs with their data pin connected via PWM.
Nota
LEDs can be controlled through this API while the robot is disabled.
Crear instancias del objeto LED direccionable
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.
Advertencia
Es importante tener en cuenta que configurar la longitud del encabezado del LED es una tarea costosa y no se recomienda ejecutar esto periódicamente.
Después de que se haya establecido la longitud de la tira, tendrá que crear un objeto AddressableLEDBuffer
que toma la cantidad de LED como entrada. Entonces llamarás a myAddressableLed.setData(myAddressableLEDBuffer)
para establecer los datos de salida del led. Finalmente puedes llamar myAddressableLed.start()
para escribir la salida continuamente. A continuación, se muestra un ejemplo completo del proceso de inicialización
Nota
C++ no tiene un AddressableLEDBuffer, y en su lugar usa una matriz.
17 @Override
18 public void robotInit() {
19 // PWM port 9
20 // Must be a PWM header, not MXP or DIO
21 m_led = new AddressableLED(9);
22
23 // Reuse buffer
24 // Default to a length of 60, start empty output
25 // Length is expensive to set, so only set it once, then just update data
26 m_ledBuffer = new AddressableLEDBuffer(60);
27 m_led.setLength(m_ledBuffer.getLength());
28
29 // Set the data
30 m_led.setData(m_ledBuffer);
31 m_led.start();
32 }
12class Robot : public frc::TimedRobot {
13 private:
14 static constexpr int kLength = 60;
15
16 // PWM port 9
17 // Must be a PWM header, not MXP or DIO
18 frc::AddressableLED m_led{9};
19 std::array<frc::AddressableLED::LEDData, kLength>
20 m_ledBuffer; // Reuse the buffer
21 // Store what the last hue of the first pixel is
22 int firstPixelHue = 0;
7void Robot::RobotInit() {
8 // Default to a length of 60, start empty output
9 // Length is expensive to set, so only set it once, then just update data
10 m_led.SetLength(kLength);
11 m_led.SetData(m_ledBuffer);
12 m_led.Start();
13}
Nota
The roboRIO only supports only 1 AddressableLED
object. As WS2812B LEDs are connected in series, you can drive several strips connected in series from from AddressableLED
object.
Configuración de toda la tira a un color
El color se puede ajustar a un led individual en la tira usando dos métodos. setRGB()
el cual toma los valores RGB como entrada y setHSV()
el cual toma los valores HSV como entrada.
Usando valores RGB
RGB significa rojo, verde y azul. Este es un modelo de color bastante común, ya que es bastante fácil comprender. Los LED se pueden configurar con el método setRGB
que toma 4 argumentos: índice del LED, cantidad de rojo, cantidad de verde, cantidad de azul. La cantidad de rojo, verde y azul son valores enteros entre 0-255.
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);
for (int i = 0; i < kLength; i++) {
m_ledBuffer[i].SetRGB(255, 0, 0);
}
m_led.SetData(m_ledBuffer);
Usando valores HSV
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.
Los LED se pueden configurar con el método setHSV que toma 4 argumentos: índice del LED, tono, saturación y valor. A continuación, se muestra un ejemplo para configurar el color de una tira de LED en rojo (matiz de 0).
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);
for (int i = 0; i < kLength; i++) {
m_ledBuffer[i].SetHSV(0, 100, 100);
}
m_led.SetData(m_ledBuffer);
Crea un efecto arcoíris
El siguiente método hace un par de cosas importantes. Dentro del bucle for, distribuye equitativamente el tono en toda la longitud del hilo y almacena el tono LED individual en un variable llamada tonalidad
. Luego, el bucle for establece el valor HSV de ese píxel especificado utilizando el tono valor.
Moviéndose fuera del bucle for, m_rainbowFirstPixelHue
luego itera el píxel que contiene el tono «inicial» que crea el efecto arcoíris. m_rainbowFirstPixelHue
luego verifica para asegurarse de que el tono está dentro de los límites de tono de 180. Esto se debe a que el tono HSV es un valor de 0-180.
Nota
Es una buena práctica de robots mantener el método robotPeriodic()
lo más limpio posible, así que crearemos un método para manejar la configuración de nuestros datos LED. Llamaremos a este método rainbow()
y llamarlo desde robotPeriodic()
.
42 private void rainbow() {
43 // For every pixel
44 for (var i = 0; i < m_ledBuffer.getLength(); i++) {
45 // Calculate the hue - hue is easier for rainbows because the color
46 // shape is a circle so only one value needs to precess
47 final var hue = (m_rainbowFirstPixelHue + (i * 180 / m_ledBuffer.getLength())) % 180;
48 // Set the value
49 m_ledBuffer.setHSV(i, hue, 255, 128);
50 }
51 // Increase by to make the rainbow "move"
52 m_rainbowFirstPixelHue += 3;
53 // Check bounds
54 m_rainbowFirstPixelHue %= 180;
55 }
22void Robot::Rainbow() {
23 // For every pixel
24 for (int i = 0; i < kLength; i++) {
25 // Calculate the hue - hue is easier for rainbows because the color
26 // shape is a circle so only one value needs to precess
27 const auto pixelHue = (firstPixelHue + (i * 180 / kLength)) % 180;
28 // Set the value
29 m_ledBuffer[i].SetHSV(pixelHue, 255, 128);
30 }
31 // Increase by to make the rainbow "move"
32 firstPixelHue += 3;
33 // Check bounds
34 firstPixelHue %= 180;
35}
Ahora que hemos creado nuestro método de arco iris, tenemos que llamar al método y establecer los datos del LED.
34 @Override
35 public void robotPeriodic() {
36 // Fill the buffer with a rainbow
37 rainbow();
38 // Set the LEDs
39 m_led.setData(m_ledBuffer);
40 }
15void Robot::RobotPeriodic() {
16 // Fill the buffer with a rainbow
17 Rainbow();
18 // Set the LEDs
19 m_led.SetData(m_ledBuffer);
20}