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.
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}