Post

Un anneau de LEDs WS2812B en feu

Avec mon contrôleur de LEDs adressables WS2812B, j’ai décidé de mettre le feu à mon anneau 12 LEDs, rien que ça…

Anneau de LEDs en feu Illustration générée par IA

Pour ce faire, voici le code en systemVerilog :

  • top.sv :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
module top (
    input logic CLOCK_50,         // Horloge 50MHz
    output logic GPIO_WS2812B     // À relier à l'entrée IN de l'anneau
);
   
   localparam NB_LEDS = 12;      // Anneau avec 12 LED adressables
   localparam ON      = 8'h20,   // luminosité maxi=8'hff, mais /!\ la consommation si toutes les Leds sont allumées 
              OFF     = 8'h00;
   
   logic [7:0] red, green, blue;
   logic [7:0] address;      // Numéro de la LED entre 0 et NB_LEDS-1
   logic load;               // Chargement du registre si load=1
   logic latch_n;            // Déverrouillage et transfert du registre sur front descendant

   logic [$clog2(NB_LEDS) - 1:0] num_led = 0;    // Numéro de led en cours
  
   logic [23:0] rgb;
   logic [25:0] delay = 0;
    
   assign red    = rgb[23-: 8]; // bits 23 à 16
   assign green  = rgb[15-: 8]; // bits 15 à 8
   assign blue   = rgb[7-: 8];  // bits 7 à 0
   
   // Instanciation du contrôleur WS2812B
   ws2812b_controller #(.NB_LEDS(NB_LEDS)) ws2812b_controller_inst (
        .clk(CLOCK_50),
        .data_ws2812b(GPIO_WS2812B),
        .*
   );

   integer i, c;  
    
   logic [23:0] led[0:NB_LEDS-1]; // État des LEDs
  logic [3:0] bottom_stack, pointer;
   logic [23:0] color[0:5];
  
   initial begin // synthétisable avec Quartus Pro
        
      for (i=0; i<NB_LEDS; i=i+1)  led[i] = {OFF, OFF, OFF};
         
      color[0] = {ON, OFF, OFF};   // red
      color[1] = {OFF, ON, OFF};   // green
      color[2] = {OFF, OFF, ON};   // blue
      color[3] = {ON, ON, OFF};    // yellow
      color[4] = {OFF, ON, ON};    // cyan
      color[5] = {ON, OFF, ON};    // purple
      
      bottom_stack = NB_LEDS - 1;
      pointer = 0;

   end

  // assignation des sorties
  assign load = (num_led < NB_LEDS);
  assign address = load ? num_led : 0;
  assign rgb = load ? led[num_led] : 0;
  assign latch_n = ~(num_led == NB_LEDS);


  // Chargement & animation
  always_ff @(posedge CLOCK_50) begin

      if (num_led <= NB_LEDS) begin // chargement led par led
         num_led <= num_led + 1;
      end else if (num_led==NB_LEDS+1) begin
               if (delay[21]==1) begin // si fin temporisation
               
                  for (i=0; i<=NB_LEDS-1 ; i=i+1) begin
                     if (i <= bottom_stack) begin
                        led[i] <= (i == pointer) ? color[c] : {OFF, OFF, OFF};
                     end else begin
                        led[i] <= color[c];
                     end
                  end
                  
                  pointer <= pointer + 1;
                  
                  if (pointer == bottom_stack) begin
                     pointer <= 0;
                     bottom_stack <= bottom_stack - 1;
                     if (bottom_stack == 1)  begin
                        bottom_stack <= NB_LEDS - 1;
                        c <= c + 1;
                        if (c==5) c<=0;
                     end
                  end

                  num_led <= 0; // retour à l'état initial
                  delay <= 0;
               end else begin
                  delay <= delay + 1;
               end
      end

  end
 
endmodule

Feu…

Ouais, je sais… Le titre du post est un poil putaclic ;-)

Cet article est sous licence CC BY 4.0 par l'auteur.