DELs adressables

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.

Note

LEDs can be controlled through this API while the robot is disabled.

Instanciation de l’objet adressableLED

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.

Avertissement

Il est important de noter que le réglage de la longueur décrit ci-haut est une tâche relativement longue à exécuter pour le roboRIO, et il n’est pas recommandé de l’exécuter périodiquement.

Une fois la longueur de la bande définie, vous devrez créer un objet AddressableLEDBuffer qui prendra le nombre de LED comme entrée. Vous appellerez ensuite myAddressableLed.setData(myAddressableLEDBuffer) pour définir les données correspondant à chaque LED. Enfin, vous pouvez appeler myAddressableLed.start() pour écrire la sortie en continu. Voici un exemple complet du processus d’initialisation.

Note

C++ ne supporte pas un AddressableLEDBuffer et utilise à la place un tableau.

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  }
11class Robot : public frc::TimedRobot {
12 private:
13  static constexpr int kLength = 60;
14
15  // PWM port 9
16  // Must be a PWM header, not MXP or DIO
17  frc::AddressableLED m_led{9};
18  std::array<frc::AddressableLED::LEDData, kLength>
19      m_ledBuffer;  // Reuse the buffer
20  // Store what the last hue of the first pixel is
21  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}

Note

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.

Définition de la bande entière sur une seule couleur

La couleur peut être définie sur chaque DEL spécifique sur la bande en utilisant deux méthodes. setRGB() qui prend les valeurs RGB comme entrée et setHSV() qui prend les valeurs HSV comme entrée.

Utilisation des valeurs RGB

RGB signifie rouge, vert et bleu. Il s’agit d’un modèle de couleur assez courant car il est assez facile à comprendre. Les LED peuvent être réglées avec la méthode setRGB qui prend 4 arguments: index (ou position de la LED sur la bande), valeur pour le rouge, valeur pour le vert, valeur pour le bleu. Les valeurs de rouge, vert et bleu sont des entiers compris entre 0 et 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);

Utilisation des valeurs HSV

HSV signifie Hue, Saturation et Value, ou Teinte, Saturation et Valeur. La teinte correspond à la couleur, la saturation étant la quantité de gris et la valeur étant la luminosité. Dans WPILib, Hue est un entier compris entre 0 et 180. Saturation et Value sont des nombres entiers compris entre 0 et 255. Si vous regardez un sélecteur de couleurs comme celui de Google, La teinte sera de 0 à 360 et la saturation et la valeur de 0% à 100%. C’est de la même façon qu’OpenCV gère les couleurs HSV. Assurez-vous que les valeurs HSV saisies dans WPILib sont correctes, sinon la couleur pourrait différer de celle attendue.

Image des modèles HSV

Les LED peuvent être réglées avec la méthode setHSV qui prend 4 arguments: index de la LED, Hue, Saturation et Value. Un exemple est illustré ci-dessous pour définir la couleur d’une bande LED sur rouge (teinte 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);

Création d’un effet arc-en-ciel

La méthode ci-dessous fait plusieurs opérations. À l’intérieur de la boucle for, la teinte (ou Hue) est distribuée de façon uniforme sur la bande de LED et stocke la teinte individuelle des LED dans une variable appelée hue. Ensuite, la boucle for définit la valeur HSV de ce pixel spécifié en utilisant la valeur hue.

À l’extérieur de la boucle for, le m_rainbowFirstPixelHue itère ensuite le pixel qui contient la teinte « initiale » créant l’effet arc-en-ciel. m_rainbowFirstPixelHue vérifie ensuite pour s’assurer que la teinte est à l’intérieur des limites de teinte de 180. En effet, la teinte HSV est une valeur de 0 à 180.

Note

C’est une bonne pratique de programmation de garder la méthode robotPeriodic() aussi claire et concise que possible, nous allons donc créer une méthode pour gérer la configuration de nos données LED. Nous appellerons cette méthode rainbow() et l’appellerons de 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}

Maintenant que nous avons créé notre méthode rainbow(), nous devons l’appeler et définir les données qui iront à la bande de 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}